1.apk安装升级:
Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent =new Intent(Intent.ACTION_INSTALL_PACKAGE);
Uri apkUri = FileProvider.getUriForFile(mContext,"com.sitech.ac.fileProvider", new File(UpdateInfo.localApkPath));
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}else {
intent =new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(UpdateInfo.localApkPath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
mContext.startActivity(intent);
2.权限的动态申请(Android6.0引入的动态权限控制)
AndPermission:
https://github.com/yanzhenjie/AndPermission
3.Android8.0引入了通知渠道:
NotificationManager mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("sitechNotification", "通知消息", NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(channel);
builder = new Notification.Builder(mContext, "sitechNotification");
} else {
builder = new Notification.Builder(mContext);
}
Notification notification = builder.build();
4.startForegroundService:
开启服务:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// Android 8.0 改为前台服务方式启动
mContext.startForegroundService(intent);
} else {
mContext.startService(intent);
}
在Service的onCreate()中添加:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
//channel 设置为null,此方法只适用于targetSdkVersion = 26的情况
Notification.Builder builder = new Notification.Builder(mService, null)
.setContentTitle(mService.getString(R.string.app_name))
.setContentText("")
.setAutoCancel(true);
Notification notification = builder.build();
mService.startForeground(id, notification);
}
5.图片选择和裁剪
Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.ct.client/files/com.ct.client/camere/1547090088847.jpg exposed beyond app through ClipData.Item.getUri()
第一步:
在AndroidManifest.xml清单文件中注册provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.ct.client.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<!--元数据-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
需要注意一下几点:
exported:必须为false
grantUriPermissions:true,表示授予 URI 临时访问权限。
authorities 组件标识,都以包名开头,避免和其它应用发生冲突。
第二步:
指定共享文件的目录,需要在res文件夹中新建xml目录,并且创建file_paths
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path
name="external_files"
path="." />
</paths>
</resources>
path=”“,是有特殊意义的,它代表根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了。
第三步:
使用FileProvider
根据版本号把Uri改成使用FiliProvider创建的Uri,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
cameraFileUri = FileProvider.getUriForFile(mContext, "com.ct.client.fileProvider", new File(saveCamerePath, saveCameraFileName));
} else {
cameraFileUri = Uri.fromFile(new File(saveCamerePath, saveCameraFileName));
}
添加intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)来对目标应用临时授权该Uri所代表的文件
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
在设置裁剪要保存的 intent.putExtra(MediaStore.EXTRA_OUTPUT, outUri);的时候,这个outUri是要使用Uri.fromFile(file)生成的,而不是使用FileProvider.getUriForFile。
6.Android SQLCipher数据库迁移升级,不能覆盖,file is not a database: , while compiling: select count(*) from sqlite_master:https://github.com/Tencent/wcdb/wiki/Android%E6%8E%A5%E5%85%A5%E4%B8%8E%E8%BF%81%E7%A7%BB
7.8.0及以上系统接收不到广播的问题
解决方法:
<receiver android:name=".receiver.DataReceiverPublic">
<intent-filter>
<action android:name="izis_MinaPushServiceOpen_kyteach" />
</intent-filter>
</receiver>
if(Build.VERSION.SDK_INT >= 26){
ComponentName componentName=new ComponentName(context.getPackageName(),"cn.izis.kyteach.receiver.DataReceiverPublic");//参数1-包名 参数2-广播接收者所在的路径名
myIntent.setComponent(componentName);
}
但是如果是在2个不同的包之间发送广播,这句话是没用的,而是需要加上后面这段代码:
if(Build.VERSION.SDK_INT >= 26){
myIntent.addFlags(0x01000000);//加上这句话,可以解决在android8.0系统以上2个module之间发送广播接收不到的问题}