从TargetApi22升级到TargetApi26注意事项

最近谷歌爸爸要求在8月份,在googleplay上架的app必须升级到TargetApi26以上,作为常年使用TargetApi22的我,不得不去研究一下升级为TargetApi26的影响,主要如下:

1.运行时权限

如果你声明在清单文件的权限,这对用户的隐私或设备的操作不构成很大风险,系统会自动将这些权限授予您的应用程序。否则需要用户必须明确同意授予这些权限。权限危险等级分为3种,其中危险权限必须用户动态授权.

1.1 Normal permissions:

ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MANAGE_OWN_CALLS
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_COMPANION_RUN_IN_BACKGROUND
REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
REQUEST_DELETE_PACKAGES
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS

1.2 Signature permissions
系统在安装时授予这些应用程序权限,但仅当试图使用权限的应用程序由与定义权限的应用程序相同的证书签名时。

BIND_ACCESSIBILITY_SERVICE
BIND_AUTOFILL_SERVICE
BIND_CARRIER_SERVICES
BIND_CHOOSER_TARGET_SERVICE
BIND_CONDITION_PROVIDER_SERVICE
BIND_DEVICE_ADMIN
BIND_DREAM_SERVICE
BIND_INCALL_SERVICE
BIND_INPUT_METHOD
BIND_MIDI_DEVICE_SERVICE
BIND_NFC_SERVICE
BIND_NOTIFICATION_LISTENER_SERVICE
BIND_PRINT_SERVICE
BIND_SCREENING_SERVICE
BIND_TELECOM_CONNECTION_SERVICE
BIND_TEXT_SERVICE
BIND_TV_INPUT
BIND_VISUAL_VOICEMAIL_SERVICE
BIND_VOICE_INTERACTION
BIND_VPN_SERVICE
BIND_VR_LISTENER_SERVICE
BIND_WALLPAPER
CLEAR_APP_CACHE
MANAGE_DOCUMENTS
READ_VOICEMAIL
REQUEST_INSTALL_PACKAGES
SYSTEM_ALERT_WINDOW
WRITE_SETTINGS
WRITE_VOICEMAIL

1.3Dangerous permissions
要使用危险权限,您的应用必须提示用户在运行时授予权限。

android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR
android.permission.CAMERA
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
android.permission.RECORD_AUDIO
android.permission.READ_PHONE_STATE
android.permission.READ_PHONE_NUMBERS
android.permission.CALL_PHONE
android.permission.ANSWER_PHONE_CALLS
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
android.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS
android.permission.BODY_SENSORS
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.SYSTEM_ALERT_WINDOW

关于悬浮窗权限:android.permission.SYSTEM_ALERT_WINDOW
同时api26时开始,下面5种类型的type将会被废弃,不能使用,但运行在低于api26版本的手机上还是可以使用以下的type,所以需要对api26的悬浮窗进行兼容处理:
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR

转为必须使用TYPE_APPLICATION_OVERLAY,同时使用该type之后:
1)但是会在重要的系统窗口(如状态栏、IME)之下
2)系统可以调整这种形式窗口的位置、大小和可见性
3)运行在api26的手机上,只要应用使用[TYPE_APPLICATION_OVERLAY] 来弹出悬浮窗,系统会自动发送一条通知,告知用户”xxx正在其他应用上显示内容”,用户可以通过点击通知栏跳转,禁用悬浮窗权限

申请TYPE_APPLICATION_OVERLAY权限的代码:

 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CALL_PHONE},
                        MY_PERMISSIONS_REQUEST_ALERT);
            }
        }

if (!Settings.canDrawOverlays(MainActivity.this)) {
  Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
   startActivityForResult(intent, 10);
}

2.私有文件的文件权限不在放权给所有的应用

使用 MODE_WORLD_READABLE 或 MODE_WORLD_WRITEABLE 进行的操作将触发 SecurityException。

MODE_WORLD_READABLE:该文件的内容可以被其他程序读取;
MODE_WORLD_WRITEABLE:该文件的内容可被其他程序读、写

3.App对外无法暴露file://类型的URI

如果你使用Intent携带这样的URI去打开外部App(比如:打开系统相机拍照),那么会抛出FileUriExposedException异常

String cachePath = getApplicationContext().getExternalCacheDir().getPath(); 
File picFile = new File(cachePath, "test.jpg"); 
Uri picUri = Uri.fromFile(picFile); 
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, picUri); startActivityForResult(intent, 100);

4.DownloadManager 不再按文件名分享私人存储的文件。

COLUMN_LOCAL_FILENAME在Android7.0中被标记为deprecated ,
旧版应用在访问 COLUMN_LOCAL_FILENAME时可能出现无法访问的路径。 面向 Android N 或更高版本的应用在尝试访问 COLUMN_LOCAL_FILENAME 时会触发 SecurityException。

5.使用用户账户信息

在安卓8.0中,应用只能使用authenticator拥有的账户信息或者用户授权的账户信息。仅仅申请GET_ACCOUNTS权限不足以获得账户信息的授权,为了获得使用权限,需要调用AccountManager.newChooseAccountIntent() ,或者其他authenticator相关的方法。得到了权限之后,应用可以调用AccountManager.getAccounts()来获得账户信息。

安卓8.0废弃了LOGIN_ACCOUNTS_CHANGED_ACTION,应该应该使用addOnAccountsUpdatedListener()来获取运行时账户变化。

6.权限组调整

安卓8.0之前,如果应用在运行时申请一个权限,并且用户授予了这个权限,那么系统会错误的将这个权限所属的权限组里的并且在manifest里注册过的权限都授予这个应用。

对于targetApi为8.0的应用,以上行为已经被修正了,应用将只被授予其申请的权限。但是,如果应用之后再申请同一权限组中的其他权限时,将自动被授予。

例如,应用在Manifest里同时注册了READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAG两个权限。在targetApi=25或之前的版本中,当应用请求READ_EXTERNAL_STORAGE权限并且用户授权了之后,系统会自动授予WRITE_EXTERNAL_STORAG权限,因为READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAG同属STORAGE权限组其都在manifest里注册了。但在安卓8.0系统中,只有READ_EXTERNAL_STORAGE会被授权,但是当应用再次申请WRITE_EXTERNAL_STORAG权限时,系统会不提示用户直接授权。

相关官方说明:

https://developer.android.com/about/versions/marshmallow/android-6.0-changes

https://developer.android.com/about/versions/nougat/android-7.0-changes

https://developer.android.com/about/versions/oreo/android-8.0-changes#o-apps

你可能感兴趣的:(Android,TargetApi26)