安卓视频录制、调用系统音乐、视频播放器所遇问题及解决(包含7.0兼容问题)

1.所遇问题:在部分手机上无法录制视频(测试的几个手机:华为P9(7.0),华为mate8(6.0), 锤子( 7.0)都无法录制)
问题原因:录制视频编码格式的问题,手机不支持 MPEG_4_SP 编码格式
解决方法:改为 H264 编码格式,以下为录制视频代码
1
/**
2
     * 初始化录像
3
     *
4
     * @param path
5
     */
6
    private void prepareVideoRecorder(String path) {
7
        releaseCamera();
8
        if (mCamera == null) {
9
            mCamera = getCamera(mCameraId);
10
            startPreview(mCamera, mHolder);
11
            mCamera.unlock();
12
        }
13
        if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder();
14
        mMediaRecorder.reset();
15
        mMediaRecorder.setCamera(mCamera);
16
        mMediaRecorder.setPreviewDisplay(mHolder.getSurface());
17
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 音频源
18
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 视频源
19
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 视频输出格式
20
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 音频格式
21
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 视频编码格式
22
        if (ScreenUtils.checkDeviceHasNavigationBar(CameraActivity.this)) {
23
            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
24
                mMediaRecorder.setVideoSize(640, 480);
25
            } else {
26
                mMediaRecorder.setVideoSize(VIDEO_HEIGHT, VIDEO_WIDTH);
27
            }
28
        } else {
29
            mMediaRecorder.setVideoSize(VIDEO_HEIGHT, VIDEO_WIDTH);
30
        }
31
        mMediaRecorder.setVideoFrameRate(30);
32
        mMediaRecorder.setVideoEncodingBitRate(VIDEO_ENCODINGBITRATE);
33
        mMediaRecorder.setOrientationHint(90);// 输出旋转90度,保持竖屏录制
34
        mMediaRecorder.setOutputFile(path);
35
        mMediaRecorder.setPreviewDisplay(mHolder.getSurface());
36
37
        try {
38
            mMediaRecorder.prepare();
39
            mMediaRecorder.start();
40
            ll_time.setVisibility(View.VISIBLE);
41
            ct_time.setBase(SystemClock.elapsedRealtime());
42
            ct_time.start();
43
        } catch (IllegalStateException e) {
44
            e.printStackTrace();
45
        } catch (IOException e) {
46
            e.printStackTrace();
47
        }
48
        videoPath = path;
49
    }
2.所遇问题:安卓7.0版本调用系统播放器播放本地视频文件会崩溃的问题(解决方法是从网上找的,附上原文链接: http://blog.csdn.net/zz110753/article/details/60877594  会谈到照相后获取照片的问题),同样原因也会导致播放本地音频文件崩溃,app版本更新时 用系统安装器安装APK会崩溃,这些在  http://blog.csdn.net/msn465780/article/details/59058088?locationNum=8&fps=1 链接中有做描述
问题原因: 实际是7.0系统调用本地文件的问题Android7.0中尝试传递 file:// URI 会触发 FileUriExposedException,因为在Android7.0之后Google认为直接使用本地的根目录即file:// URI是不安全的操作,直接访问会抛出FileUriExposedExCeption 异常
解决方法:

Google为我们提供了FileProvider类,进行一种特殊的内容提供,FileProvider时ContentProvide的子类,它使用了和内容提供器类似的机制来对数据进行保护,可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性。下面就让我们看一下如何使用这个内容提供者进行数据访问的:

步骤一、 使用FileProvider获取Uri就会将以前的file:// URI准换成content:// URI,实现一种安全的应用间数据访问,内容提供者作为Android的四大组件之一,使用同样需要在清单文件AndroidManifest.xml中进行注册的,注册方法如下:

    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.zz.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
            android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />

provider标签里的 android:name的值是FileProvider的包名+类名为固定值。android:authorities的值相当于一个标志,当我们使用FileProvider的getUriForFile方法时的一个参数需和清单文件注册时的保持一致,这里我使用的是:com.zz.fileprovider可自行定义。exported:要求必须为false,为true则会报安全异常。grantUriPermissions:true,表示授予 URI 临时访问权限。标签里面是用来指定共享的路径。 

步骤二、android:resource="@xml/file_paths"就是我们的共享路径配置的xml文件。关于xml文件的配置如下:

在res目录下创建xml文件夹,file_paths.xml文件内容如下:

xml version="1.0" encoding="utf-8"?>

    
                    name="camera_photos"
            path="" />
    
external-path标签用来指定Uri共享的,name属性的值可以自定义,path属性的值表示共享的具体位置,设置为空,就表示共享整个SD卡,也可指定对应的SDcard下的文件目录,根据需求自行定义。
步骤三、具体的代码中使用如下,附上调用系统播放器播放视频方法:
1
private void playVideo(String path) {
2
        Intent intent = new Intent();
3
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4
        intent.setAction(Intent.ACTION_VIEW);
5
        intent.addCategory("android.intent.category.DEFAULT");
6
        File file = new File(path);
7
        Uri uri;
8
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {    //解决7.0崩溃问题
9
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
10
            uri = FileProvider.getUriForFile(ShowPicActivity.this, getPackageName() + ".fileprovider", file);
11
        } else {
12
            uri = Uri.parse("file://" + path);
13
        }
14
        intent.setDataAndType(uri, "video/mp4");
15
        if (intent.resolveActivity(getPackageManager()) != null) {
16
            startActivity(intent);
17
        } else {
18
            Toast.makeText(ShowPicActivity.this, "抱歉,不支持打开此类文件", Toast.LENGTH_SHORT).show();
19
        }
20
    }

3.所遇问题:调用系统播放器播放音频文件时,部分华为手机无法播放,对此的解决方法是在调用时添加 
intent = Intent.createChooser(intent, "Choose an application to open with:");
另附上调用系统播放器播放音频文件的代码
1
/**
2
     * 播放录音文件
3
     *
4
     * @param path
5
     */
6
    private void playMusic(String path) {
7
        Intent intent = new Intent();
8
        intent.setAction(Intent.ACTION_VIEW);
9
        intent.addCategory("android.intent.category.DEFAULT");
10
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
11
        File file = new File(path);
12
        Uri uri;
13
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
14
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
15
            uri = FileProvider.getUriForFile(ShowPicActivity.this, getPackageName() + ".fileprovider", file);
16
        } else {
17
//            uri = Uri.fromFile(file);
18
            uri = Uri.parse("file://" + path);
19
        }
20
        intent.setDataAndType(uri, "audio/vnd.android.cursor.dir/playlist");
21
        intent = Intent.createChooser(intent, "Choose an application to open with:");   //部分华为手机需加
22
        if (intent.resolveActivity(getPackageManager()) != null) {
23
            startActivity(intent);
24
        } else {
25
            Toast.makeText(ShowPicActivity.this, "抱歉,不支持打开此类文件", Toast.LENGTH_SHORT).show();
26
        }
27
    }

注:目前大部分手机测试没有问题,但是目前锤子 7.0手机,以及华为mate8(6.0)手机,还是无法调用系统播放器播放音频和视频文件,正在定位问题,后续会做更新

你可能感兴趣的:(安卓视频录制、调用系统音乐、视频播放器所遇问题及解决(包含7.0兼容问题))