在开篇之前,如不了解 MediaRecorder,可以先行阅读 Android–MediaRecorder录音录像。
另外,在 stackoverflow 上也有关于 service 录像的回答:Background video recording in Android 4.0。我所实现的功能也参考了此 answer。
此外,关于 WindowsManager 的先验知识还可以参考这篇博客:Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果。
进入正题。
1、定义录像布局:recorder_layout.xml
<RelativeLayout
android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:keepScreenOn="true"
>
<SurfaceView
android:id="@+id/sv_recorder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
/>
</RelativeLayout>
2、实现 MonitorService.java
public class MonitorService extends Service implements SurfaceHolder.Callback {
public static final String ACTION_BACK_HOME = "com.byd.recorder.ACTION_BACK_HOME";
public static final String ACTION_SHOW_RECORDER = "com.byd.recorder.ACTION_SHOW_RECORDER";
private static final int NOTIFICATION_DI = 1234;
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
private int screenWidth;
private int screenHeight;
private View mRecorderView;
private SurfaceView mSurfaceView;
/* RecorderManager manages the job of video recording */
private RecorderManager mRecorderManager;
private LocalBroadcastManager mLocalBroadcastManager;
private LocalReceiver mLocalReceiver;
@Override
public void onCreate() {
super.onCreate();
// Start foreground service to avoid unexpected kill
Notification notification = new Notification.Builder(this)
.setContentTitle("Background Video Recorder")
.setContentText("Click into the application")
.setSmallIcon(R.drawable.icon)
.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0))
.build();
startForeground(NOTIFICATION_DI, notification);
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mRecorderView = LayoutInflater.from(this).inflate(R.layout.recorder_layout, null);
mSurfaceView = (SurfaceView) mRecorderView.findViewById(R.id.sv_recorder);
mSurfaceView.getHolder().addCallback(this);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
mLayoutParams = new WindowManager.LayoutParams();
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mLayoutParams.width = screenWidth;
mLayoutParams.height = screenHeight;
mWindowManager.addView(mRecorderView, mLayoutParams);
registerLocalReceiver();
}
@Override
public void onDestroy() {
if (mWindowManager != null) {
mWindowManager.removeView(mRecorderView);
}
if (mRecorderManager != null) {
mRecorderManager.stop();
}
mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);
stopForeground(true);
}
private void registerLocalReceiver() {
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_BACK_HOME);
intentFilter.addAction(ACTION_SHOW_RECORDER);
mLocalReceiver = new LocalReceiver();
mLocalBroadcastManager.registerReceiver(mLocalReceiver, intentFilter);
}
public void hideRecorder(boolean isHide) {
if (isHide) {
mLayoutParams.width = 1;
mLayoutParams.height = 1;
} else {
mLayoutParams.width = screenWidth;
mLayoutParams.height = screenHeight;
}
mWindowManager.updateViewLayout(mRecorderView, mLayoutParams);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mRecorderManager = new RecorderManager();
mRecorderManager.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
private class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_BACK_HOME)) {
hideRecorder(true);
}
if (intent.getAction().equals(ACTION_SHOW_RECORDER)) {
hideRecorder(false);
}
}
}
}
3、几点说明
mLayoutParams.width
和 mLayoutParams.height
决定了 mRecorderView
所显示出来的大小,所以我们可以通过 WindowManager.updateViewLayout(view, layoutParams)
这一方法实现隐藏和显示监控录像。
我们在进入 MainActivity 后,可以向 MonitorService 发送本地广播,实现对监控录像的显示和隐藏
private void hideRecorder() {
Intent intent = new Intent(MonitorService.ACTION_BACK_HOME);
mLocalBroadcastManager.sendBroadcast(intent);
}
private void showRecorder() {
Intent intent = new Intent(MonitorService.ACTION_SHOW_RECORDER);
mLocalBroadcastManager.sendBroadcast(intent);
}
4、没有 demo project,请根据以上关键源码实现你想要的功能吧!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章