我目前正在使用 Activity 在 ICS 及更高版本中使用相机和手电筒,我使用 SurfaceView,现在我的问题是如何在服务中使用相同的代码,如何创建 SurfaceView 并使用相机?
谢谢 。
我目前正在使用 Activity 在 ICS 及更高版本中使用相机和手电筒,我使用 SurfaceView,现在我的问题是如何在服务中使用相同的代码,如何创建 SurfaceView 并使用相机?
谢谢 。
您应该使用 aTextureSurface
而不是 a SurfaceView
(可从 API 11 获得)。看看这个问题。
您想在服务中创建一个表面视图并使用该视图到相机。源代码在这里https://github.com/renhongtao/FloatCameraWindow
1.在服务示例中创建表面视图。此解决方案有助于了解如何在服务中创建视图。
使用名为WindowManager的类和名为LayoutParams的参数对象。注意 params.type,在不同的 SDK 版本中可能会失败。
在 AndroidManifest.xml 中
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<service android:name=".FloatWindowService" />
创建一个新的服务子类
public class TopWindowService extends Service
{
private static WindowManager wm;
private static WindowManager.LayoutParams params;
private Button btn_floatView;
@Override
public void onCreate()
{
super.onCreate();
createFloatView();
}
private void createFloatView()
{
btn_floatView = new Button(getApplicationContext());
btn_floatView.setText("Hello");
wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
//in different sdk this type should change
params.format = PixelFormat.RGBA_8888; //
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
// set float view size
params.width = 100;
params.height = 100;
// set touch listen action
btn_floatView.setOnTouchListener(new OnTouchListener()
{
int lastX, lastY;
int paramX, paramY;
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
paramX = params.x;
paramY = params.y;
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
params.x = paramX + dx;
params.y = paramY + dy;
wm.updateViewLayout(btn_floatView, params);
break;
}
return true;
}
});
wm.addView(btn_floatView, params);
isAdded = true;
}
2.将服务创建的表面设置为相机示例。这部分源码太多了。主要思想是使用类LayoutInflater加载一个xml文件。然后findViewById得到相机需要的表面。如示例 1 所示。使用 WindowManager 添加视图(在 xml 中)。
2.1 准备一个xml包含一个表面视图,名字是cmera_layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/camera_window_layout"
android:layout_width="100dip"
android:layout_height="100dip"
android:background="@drawable/ic_launcher_background"
>
<SurfaceView
android:id="@+id/camera_surface"
android:layout_width="80dip"
android:layout_height="80dip"
android:layout_gravity="center" />
</LinearLayout>
2.2 创建视图类
public class FloatWindowCamera extends LinearLayout {
protected SurfaceView mCameraView;
public static int viewWidth;
public static int viewHeight;
private static int statusBarHeight;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mParams;
private float xInScreen;
private float yInScreen;
private float xDownInScreen;
private float yDownInScreen;
private float xInView;
private float yInView;
public FloatWindowCamera(Context context) {
super(context);
/************************Main idea here**************************/
mWindowManager = context.getSystemService(Context.WINDOW_SERVICE);
LayoutInflater.from(context).inflate(R.layout.cmera_layout, this);
View view = findViewById(R.id.camera_surface);
viewWidth = view.getLayoutParams().width;
viewHeight = view.getLayoutParams().height;
mCameraView = (SurfaceView) view;
/****************************************************/
}
public SurfaceView getCameraView(){
return mCameraView;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
xInView = event.getX();
yInView = event.getY();
xDownInScreen = event.getRawX();
yDownInScreen = event.getRawY() - getStatusBarHeight();
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
break;
case MotionEvent.ACTION_MOVE:
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
updateViewPosition();
break;
default:
break;
}
return true;
}
public void setParams(WindowManager.LayoutParams params) {
mParams = params;
}
private void updateViewPosition() {
mParams.x = (int) (xInScreen - xInView);
mParams.y = (int) (yInScreen - yInView);
mWindowManager.updateViewLayout(this, mParams);
}
private int getStatusBarHeight() {
if (statusBarHeight == 0) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object o = c.newInstance();
Field field = c.getField("status_bar_height");
int x = (Integer) field.get(o);
statusBarHeight = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
}
return statusBarHeight;
}
}
2.3 创建表面视图然后给出对象。
我们使用 TopFloatWindowService 相同的类名
public class TopWindowService extends Service
{
...
@Override
public void onCreate()
{
super.onCreate();
/********************add the view in WindowManager**************/
mView = createCameraWindow(getApplicationContext()).getCameraView();
//**now you can use this mView to the camera** then startpreview
}
public static FloatWindowCamera createCameraWindow(Context context) {
WindowManager windowManager = context.getSystemService(Context.WINDOW_SERVICE);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
if (mCameraWindow == null) {
mCameraWindow = new FloatWindowCamera(context);
if (mCameraWindowParams == null) {
mCameraWindowParams = new LayoutParams();
mCameraWindowParams.type = LayoutParams.TYPE_TOAST ;
mCameraWindowParams.format = PixelFormat.RGBA_8888;
mCameraWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
mCameraWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
mCameraWindowParams.width = FloatWindowCamera.viewWidth;
mCameraWindowParams.height = FloatWindowCamera.viewHeight;
mCameraWindowParams.x = screenWidth;
mCameraWindowParams.y = screenHeight / 2;
}
mCameraWindow.setParams(mCameraWindowParams);
//here add the view to show
windowManager.addView(mCameraWindow, mCameraWindowParams);
Log.e("FLOAT","create small success");
}
return mCameraWindow;
}
代码太多了,希望对大家有所帮助。
服务不是使用这些元素的地方。你将无法做到这一点。