Android个版本之间的变更

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jackzhouyu/article/details/83094779

Android 6.0

运行时权限,可以使用[PermissionDispatch][1]框架完成权限控制,也可以自己写代码,不过比较繁琐,如下代码:

@RequiresApi(api = Build.VERSION_CODES.M)
    private void initPermission(){
        permissionS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        permissionS.add(Manifest.permission.VIBRATE);
        permissionS.add(Manifest.permission.CAMERA);
        permissionS.add(Manifest.permission.ACCESS_FINE_LOCATION);

        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M){
            return;
        }

        ArrayList<String> needPermission = new ArrayList<>();
        for(int i= 0 ; i< permissionS.size(); i++){
            if(checkSelfPermission(permissionS.get(i)) != PackageManager.PERMISSION_GRANTED){
                needPermission.add(permissionS.get(i));
            }
        }

        if(needPermission.size() > 0){
            ActivityCompat.requestPermissions(this, needPermission.toArray(new String[needPermission.size()]), 127);
        }

//权限处理结果回调方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

	super.onRequestPermissionsResult(requestCode, permissions, grantResults);
	switch (requestCode) {
		case PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
			if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
					// 该权限已经通过
			} else {

					// 权限已经被拒绝
			}

	return;
	}
	}
}

Android O 8.0

通知栏notification

每个应用的通知需要为其创建对应的NotificationChannel通知渠道,通知管理器为其创建渠道channel,并且每个应用通知需要设置一个NOTIFICATION_ID

如下代码,写好的兼容代码:

 @RequiresApi(api = 26)
    private NotificationChannel createNoticationChannel(){
            NotificationChannel channel = new NotificationChannel(String.valueOf(NOTIFICATION_ID), "heyichong",
                    NotificationManager.IMPORTANCE_DEFAULT);
            channel.canBypassDnd();//是否绕过请勿打扰模式
            channel.enableLights(true);//闪光灯
            channel.setLockscreenVisibility(VISIBILITY_SECRET);//锁屏显示通知
            channel.setLightColor(Color.RED);//闪关灯的灯光颜色
            channel.canShowBadge();//桌面launcher的消息角标
            channel.enableVibration(true);//是否允许震动
            channel.getAudioAttributes();//获取系统通知响铃声音的配置
            channel.getGroup();//获取通知取到组
            channel.setBypassDnd(true);//设置可绕过  请勿打扰模式
            channel.setVibrationPattern(new long[]{100, 100, 200});//设置震动模式
            channel.shouldShowLights();//是否会有灯光

            return channel;
    }

    @Override
    public void showNotification() {
        Intent cancelIntent = new Intent();
        cancelIntent.setAction(DownloadReceiver.INTENT_ACTION_CANCEL);
        PendingIntent piCancel = PendingIntent.getBroadcast(this, 0, cancelIntent, 0);

        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            mBuilder = new NotificationCompat.Builder(this, String.valueOf(NOTIFICATION_ID));
            mNotificationManager.createNotificationChannel(createNoticationChannel());
        }else{
            mBuilder = new NotificationCompat.Builder(this);
            mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
        }

        mBuilder.setContentTitle(getString(R.string.start_download))
                .setTicker(getString(R.string.start_download)) //通知首次出现在通知栏,带上升动画效果的
                .setProgress(100, 0, true)
                .setSmallIcon(R.mipmap.ic_launcher)
                .addAction(R.drawable.ic_close, getString(R.string.cancel_download), piCancel);

        //        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
        /**
         * 设置为前台service
         */
        startForeground(NOTIFICATION_ID, mBuilder.build());
    }

添加support-library >= 26

小于26的support库只需要用SDK Manager更新,即可;大于则需要在Android Studio中的根build.gradle添加maven的Google库,如下:

在这里插入图片描述

Android 7.0

应用间共享文件

Android 框架强制运行了 StrictMode API 政策禁止向你的应用外公开 file:// URI。假设一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常,如调用系统相机拍照,或裁切照片。
这时需要用FileProvider来解决该问题:
第一步:在manifest清单文件里注冊provider

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="包名.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

exported:要求必须为false,为true则会报安全异常。grantUriPermissions:true,表示授予 URI 暂时訪问权限。

第二步:指定共享的文件夹
为了指定共享的文件夹我们须要在资源(res)文件夹下创建一个xml文件夹,然后创建一个名为“file_paths”(名字能够随便起,仅仅要和在manifest注冊的provider所引用的resource保持一致就可以)的资源文件。内容例如以下:

xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path path="" name="camera_photos" />
    </paths>
</resources>

代表的根文件夹: Context.getFilesDir()
代表的根文件夹: Environment.getExternalStorageDirectory()
代表的根文件夹: getCacheDir()

上述代码中path=”“,是有特殊意义的,它代码根文件夹。也就是说你能够向其它的应用共享根文件夹及其子文件夹下不论什么一个文件了,假设你将path设为path=”pictures”,
那么它代表着根文件夹下的pictures文件夹(eg:/storage/emulated/0/pictures),假设你向其它应用分享pictures文件夹范围之外的文件是不行的。

__第三步:使用FileProvider __
上述准备工作做完之后,如今我们就能够使用FileProvider了。
还是以调用系统相机拍照为例,我们须要将上述拍照代码改动为例如以下:

File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg");
if (!file.getParentFile().exists())file.getParentFile().mkdirs();
Uri imageUri = FileProvider.getUriForFile(context, "com.jph.takephoto.fileprovider", file);//通过FileProvider创建一个content类型的Uri
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //加入这一句表示对目标应用暂时授权该Uri所代表的文件
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI
startActivityForResult(intent,1006);

上述代码中主要有两处改变:

1、将之前Uri的scheme类型为file的Uri改成了有FileProvider创建一个content类型的Uri。
2、加入了intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);来对目标应用暂时授权该Uri所代表的文件。
[1]:https://github.com/MichaelJokAr/PermissionDispatcher

猜你喜欢

转载自blog.csdn.net/jackzhouyu/article/details/83094779