美文网首页简化开发iOS
Android RTMP录频直播一(录屏)

Android RTMP录频直播一(录屏)

作者: Sky_Blue | 来源:发表于2022-04-06 15:30 被阅读0次
    一、录频
    1. 录频简单流程
    录屏简单流程.png
    2. 录频代码

    2.1 录屏帮助类

    /**
     * 录屏帮助类
     */
    public class ProjectionUtils {
        public static final int REQUEST_CODE = 101;
        private MediaProjectionManager mManager;
        private Activity mActivity;
        private Intent mService;
    
        /**
         * 开始录屏,调起录屏权限窗口
         */
        public void start(Activity activity) {
            this.mActivity = activity;
            // 创建前先停止
            stop();
            mManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            Intent screenCapture = mManager.createScreenCaptureIntent();
            activity.startActivityForResult(screenCapture, REQUEST_CODE);
        }
    
        // 录屏权限回调处理
        public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
                // 这里开启服务
                mService = new Intent(mActivity, ProjectionService.class);
                mService.putExtra("code", resultCode);
                mService.putExtra("data", data);
                // 开启服务
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    mActivity.startForegroundService(mService);
                } else {
                    mActivity.startService(mService);
                }
            }
        }
    
        public void stop() {
            // 停止服务
            if (mService != null && mActivity != null) {
                mActivity.stopService(mService);
                mService = null;
            }
        }
    }
    

    2.2 录屏服务

    /**
     * 录屏服务
     * 主要是创建录屏类:MediaProjection
     */
    public class ProjectionService extends Service {
    
        private static int mId = ProjectionUtils.REQUEST_CODE;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        // 开启前台通知
        private void startForeground() {
            // Intent activityIntent = new Intent(this, RtmpPushActivity.class);
            // 点击通知栏处理
            //PendingIntent contentIntent = PendingIntent.getActivity(this, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                String channelId = "Projection:" + mId;
                String channelName = "ProjectionChannel";
                NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
                NotificationChannel channel = new NotificationChannel(channelId, channelName,
                        NotificationManager.IMPORTANCE_NONE);
                channel.setLightColor(Color.BLUE);
                channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
                manager.createNotificationChannel(channel);
    
                Notification notification = new Notification.
                        Builder(getApplicationContext(), channelId)
                        .setOngoing(true)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setCategory(Notification.CATEGORY_SERVICE)
                        .setContentTitle(getString(R.string.app_name))
                        // 点击通知栏处理
                        // .setContentIntent(contentIntent)
                        .build();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    startForeground(mId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
                } else {
                    startForeground(mId, notification);
                }
            } else {
                startForeground(mId, new Notification());
            }
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // 开启前台通知
            startForeground();
    
            // 创建MediaProjection,录屏用
            int resultCode = intent.getIntExtra("code", -1);
            Intent data = intent.getParcelableExtra("data");
            MediaProjectionManager manager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            MediaProjection mediaProjection = manager.getMediaProjection(resultCode, data);
            // 回调
            ProjectionObservable.getInstance().onChange(mediaProjection);
    
            return Service.START_STICKY;
        }
    
    
        @Override
        public void onDestroy() {
            stopForeground(true);
            stopSelf();
            super.onDestroy();
        }
    }
    

    2.3 录屏回调:主要是在服务创建好MediaProjection ,回调出去

    /**
     * 消息观察者模式中的观察者接口
     */
    public interface ProjectionObserver {
        void onChange(MediaProjection mediaProjection);
    }
    
    /**
     * 消息观察者模式,状态改变后执行的操作
     */
    public class ProjectionObservable {
    
        private List<ProjectionObserver> observers = new ArrayList<>();
        private static ProjectionObservable observable;
    
        private ProjectionObservable() {
        }
    
        public static ProjectionObservable getInstance() {
            if (observable == null) {
                synchronized (ProjectionObservable.class) {
                    if (observable == null) {
                        observable = new ProjectionObservable();
                    }
                }
            }
            return observable;
        }
    
        // 发生改变
        public void onChange(MediaProjection mediaProjection) {
            for (ProjectionObserver observer : observers) {
                observer.onChange(mediaProjection);
            }
        }
    
        // 注册
        public void register(ProjectionObserver observer) {
            observers.add(observer);
        }
    
        // 反注册
        public void unregister(ProjectionObserver observer) {
            observers.remove(observer);
        }
    
    }
    

    2.4 录屏(测试)

    // 录屏推流类
    public class RtmpPushActivity extends AppActivity implements ProjectionObserver, XPermissionListener {
        private ProjectionUtils mProjectionUtils;
    
        @Override
        protected void initTitle(DefTitleBar titleBar) {
            titleBar.setTitle("RtmpPush");
        }
    
        @Override
        public int getContentLayout() {
            return R.layout.activity_push_rtmp;
        }
    
        @Override
        public void initData(Bundle savedInstanceState) {
            // 录屏帮助类
            mProjectionUtils = new ProjectionUtils();
            // 创建录屏MediaProjection类成功回调
            ProjectionObservable.getInstance().register(this);
        }
    
        // 1. 开启录屏申请
        public void start(View view) {
            // 1. 方法调用后,到->onActivityResult
            mProjectionUtils.start(this);
        }
    
        // 2.处理录屏申请
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
        // 2. 处理录屏申请 -> 到onChange(MediaProjection mediaProjection)
            mProjectionUtils.onActivityResult(requestCode, resultCode, data);
        }
    
        // 3. 录屏创建MediaProjection成功回调
        @Override
        public void onChange(MediaProjection mediaProjection) {
            // TODO 录频编码
        }
        // 4.停止录频
        public void stop(View view) {
            if (mProjectionUtils != null) {
                mProjectionUtils.stop();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mProjectionUtils != null) {
                mProjectionUtils.stop();
            }
        // 反注册录屏回调
            ProjectionObservable.getInstance().unregister(this);
        }
    
    }
    
    3. 录屏服务清单配置
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
     
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      
        <application>
          
            <service
                android:name=".ProjectionService"
                android:enabled="true"
                android:exported="true"
                android:foregroundServiceType="mediaProjection"
                android:stopWithTask="true" />
        </application>
    
    </manifest>
    
    4. 注意事项

    录屏API调用,得注意Android系统版本适配的问题。
    Android RTMP录频直播二(录屏H264编码)

    相关文章

      网友评论

        本文标题:Android RTMP录频直播一(录屏)

        本文链接:https://www.haomeiwen.com/subject/utgtsrtx.html