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之間發送廣播接收不到的問題}