3. 权限与基础配置:AndroidManifest权限声明、Camera与Audio权限动态申请、应用级配置与初始化
各位同学,咱们今天聊一个绕不开的话题——权限与基础配置。
说实话,做WebRTC开发,权限这块儿是第一个坑。我当年第一次跑通视频通话,结果发现对方听不到声音,折腾了半天,最后发现是麦克风权限没申请。嗯,这种低级错误,我相信你们不会犯,但该走的流程咱们还是得走一遍。
3.1 AndroidManifest中的权限声明
先说说清单文件。AndroidManifest.xml 是咱们App的身份证,所有权限都得在这儿先声明。
WebRTC视频通话需要哪些权限?我列个清单:
- CAMERA — 打开摄像头,拍你帅气的脸
- RECORD_AUDIO — 录音,让对方听到你的声音
- INTERNET — 网络通信,WebRTC的核心
- ACCESS_NETWORK_STATE — 检查网络状态,判断连接质量
- MODIFY_AUDIO_SETTINGS — 调整音频设置,比如扬声器切换
- BLUETOOTH — 蓝牙耳机支持(这个很多人会漏掉)
代码长这样:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
另外,如果你的App只做视频通话,不需要拍照功能,可以加个uses-feature声明:
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
这样Google Play会帮你过滤掉没有摄像头的设备。嗯,虽然现在几乎没有手机没摄像头了,但平板、电视盒子之类的设备还是有的。
3.2 Camera与Audio权限动态申请
好,清单文件写完了,接下来是运行时申请。这部分我建议你封装成一个工具类,别到处写重复代码。
我个人习惯用这种方式:
public class PermissionUtils {
private static final int PERMISSION_REQUEST_CODE = 1001;
public static boolean hasPermissions(Context context) {
return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED;
}
public static void requestPermissions(Activity activity) {
ActivityCompat.requestPermissions(activity,
new String[]{
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
},
PERMISSION_REQUEST_CODE);
}
}
然后在Activity里处理回调:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean allGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (allGranted) {
// 权限已获取,开始初始化WebRTC
initWebRTC();
} else {
// 权限被拒绝,提示用户
showPermissionDeniedDialog();
}
}
}
为什么会这样?因为Android从6.0开始,权限机制变得很严格。用户拒绝一次后,如果你还反复弹窗,Google Play可能会给你差评。所以,做好引导很重要。
3.3 应用级配置与初始化
权限搞定了,接下来是初始化。WebRTC的初始化其实不复杂,但顺序很重要。
我一般在Application的onCreate里做全局初始化:
public class WebRTCApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 初始化WebRTC
initWebRTC();
}
private void initWebRTC() {
// 1. 初始化PeerConnectionFactory
PeerConnectionFactory.InitializationOptions initOptions =
PeerConnectionFactory.InitializationOptions.builder(this)
.setFieldTrials(FieldTrials.DEFAULT)
.setEnableInternalTracer(true)
.createInitializationOptions();
PeerConnectionFactory.initialize(initOptions);
// 2. 创建PeerConnectionFactory实例
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
PeerConnectionFactory factory = PeerConnectionFactory.builder()
.setOptions(options)
.createPeerConnectionFactory();
// 3. 保存到全局单例
WebRTCManager.getInstance().setFactory(factory);
}
}
这里有个细节——初始化顺序。我记得有一次在项目中,同事把PeerConnectionFactory.initialize()和PeerConnectionFactory.builder()写反了,结果崩溃了一整天。你想想看,初始化都没完成,你怎么创建工厂?
所以,记住这个顺序:
- 先调用
PeerConnectionFactory.initialize() - 再调用
PeerConnectionFactory.builder().createPeerConnectionFactory()
另外,关于音频配置,我建议在初始化时就把音频模式设置好:
// 设置音频配置
AudioConstraints audioConstraints = new AudioConstraints();
audioConstraints.autoGainControl = true;
audioConstraints.echoCancellation = true;
audioConstraints.noiseSuppression = true;
这三个参数什么意思?
- autoGainControl:自动增益控制。说白了就是让麦克风自动调节音量,避免你说话声音忽大忽小。
- echoCancellation:回声消除。这个很重要,不然对方会听到自己的回声。
- noiseSuppression:噪声抑制。过滤掉背景噪音,比如风扇声、键盘声。
我曾经在一个项目中,用户反馈说通话有回声,排查了半天,最后发现是echoCancellation没开。嗯,从那以后我每次初始化都会检查这个参数。
3.4 知识体系总览
下面这张图,帮你理清本章的知识结构:
3.5 避坑指南
最后,分享几个我踩过的坑:
坑1:权限申请后不检查结果
我曾经见过有人直接调用requestPermissions,然后不管结果就开始初始化WebRTC。结果呢?摄像头打不开,音频录不了,整个通话都是黑的。所以,一定要在onRequestPermissionsResult里检查grantResults。
坑2:在子线程初始化PeerConnectionFactory
PeerConnectionFactory的初始化必须在主线程。如果你在子线程里调,会直接崩溃。我刚开始做的时候也犯过这个错,后来养成了习惯,所有WebRTC初始化都放在主线程。
坑3:忘记释放资源
WebRTC的PeerConnectionFactory、PeerConnection、VideoSource这些都是重量级对象。不用了记得释放,不然内存泄漏等着你。我一般在Activity的onDestroy里做清理。
好了,这一章的内容就这些。权限和配置是WebRTC开发的第一步,也是最重要的一步。把这些基础打牢了,后面的开发才会顺风顺水。