一、android:7.0系统共享文件权限
7.0系统,不再将应用程序的私有程序向使用者放宽,随之带来的就是你的App对外无法暴露file://类型的URI了;如果继续使用intent携带file://类型的uri去访问其他应用,比如说相机、安装apk等则会抛出FileUriExposedException异常;
解决办法:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
android:authorities 【自定义】 推荐以包名+”.fileprovider”方式命名,系统唯一
android:exproted 要求必须为false,为true则会报安全异常
android:grantUriPermissions 是否允许为文件设置临时权限
android:initOrer: 优先级
android:resource="@xml/update_cache_path"就是我们的共享路径配置的xml文件(此文件需要在res文件夹下面创建一个名字为xml的目录,然后在此目录下创建一个资源文件,这里的资源文件名称为file_paths)
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-cache-path name="update_cache" path="."/>
<!--<external-path name="external_path" path=""/>-->
<!--<root-path path="txgw" name="cache" />-->
<!--/ path可以为空 表示指定目录下的所有文件、文件夹 都可以被共享-->
<file-path name="my_image" path=""/>
<!--物理路径相当于Context.getFilesDir() + /path/-->
<!--<files-path name="name" path="path" />-->
<!--物理路径相当于Context.getCacheDir() + /path/-->
<!--<cache-path name="name" path="path" />-->
<!--物理路径相当于Environment.getExternalStorageDirectory() + /path/。-->
<!--<external-path name="name" path="path" />-->
<!--物理路径相当于Context.getExternalFilesDir(String) + /path/。-->
<!--注意:external-cache-path在support-v4:24.0.0这个版本并未支持,直到support-v4:25.0.0才支持-->
<!--<external-files-path name="name" path="path" />-->
<!--物理路径相当于Context.getExternalCacheDir() + /path/。-->
<!--<external-cache-path name="name" path="path" />-->
<!--如果你想使用外置SD卡,可以用这个:物理路径相当于/path/-->
<!--<root-path name="name" path="path" />-->
</paths>
例:安装APK的时候,APK在属于本程序的文件夹中,现在要调用系统的页面去安装APK涉及到了文件共享:
private void installApk(String fileSavePath) {
File file = new File(fileSavePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri data;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//判断版本大于等于7.0
// "sven.com.fileprovider.fileprovider"即是在清单文件中配置的authorities
// 通过FileProvider创建一个content类型的Uri
data =FileProvider.getUriForFile(this,mContext.getPackageName()+".fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 给目标应用一个临时授权
} else {
data = Uri.fromFile(file);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
startActivity(intent);
}
需要注意的地方:
1.FileProvider.getUriForFile()方法的第二个参数要和mainfeast中的provider的android:authorities属性的值一样
2.注意加临时权限 :intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
3.如果这样干了还出问题,注意权限有的权限例如播放录音和播放视频是需要动态的申请的,安装apk不需要动态申请但是需要在manifest文件中加静态权限:<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
二、6.0之后有的私密的权限需要在代码中动态申请
1.在8.0后文档中虽然说申请权限不像之前6.0的时候申请一条给一组权限,但是实际上还是给了一组权限
2.注意申请权限成功后有一个回调,在成功的回调方法中写应该在onCreate中的代码逻辑实现逻辑阻塞(如果不这样干会出现很多搞笑的问题。。。亲测)
三、Notification前台通知栏
1.使用方法上发生了变化,需要加一个channel,注意在android7.0以上的NotificationCompat.Builder的构造方法需要一个channelID,如果创建channel的话这个channelID和
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
notificationManager.createNotificationChannel(channel);
中的channel的id必须是相同的
然后再通过NotificationManager显示在前台,注意:channelID和channel都是必须的,否则虽然不crash但是Notification显示不出来,用NotificationManager显示的Notification用户是可以右划移除的
2.service的Context.startForegroundService()开启前台服务,必须在服务创建后五秒内调用startForeground,这个starForeground需要一个Notification参数,是用来提示用户有前台有服务启动了
所以service中的startForeground方法也有把Notification显示在前台的作用
注意:startForeground显示的Notification是不能右划移除的,startForeground也需要notificationManager.createNotificationChannel(channel);如果不设置会crash
四、service
service的启动,在应用在后台时,要启动service不能用start的方式启动后台服务要用startForegroundService启动前台服务,但是并没有发现应用在后台启动后台服务会报错
发现问题:在使用broadcastreceiver接受广播然后开启service的时候,会出现这个问题。