Android 7.0アクセス権の適合

8025 ワード

会社のニーズに合わせてandroid 7を作ってみました.0アダプティブ、アダプティブ7.0は主に携帯電話のローカルファイルのUriを変換する処理です.7.0の适切な配合、携帯电话のストレージの中の私有のファイルの経路の保护に対して、システムがあなたのintentが1つのUriを持っていくことを発见して、住所は地元のファイルで、制限することができて、その他の原理は普及して他の绍介を検索して下で使うステップと私のツール类を贴ってください
一、現在のmoduleのAndroidManifestを修正する必要がある.xmlファイル、providerラベルを追加し、パスをマッピングします.

 
        
            
        
    

ファイルの中の部分は固定的な書き方で、公式サイトもこのように書いてあります.むやみに試してはいけません.android:resourceラベルの値はmain/res/xml/path_です.file.xmlファイル(resでxmlフォルダを新規作成し、xmlファイルを新規作成する)
二、res/xmlの下にpath_を新規作成するfile.xmlファイル、ファイル名は勝手に行きますが、前の手順と一致すればいいです.


    
        
        
        
        
        
        
        
        
    


中には6つのラベルがあり、意味が書かれています.必要なラベル定義に従えばいいです.例えば、ラベル、中のpath=""の場合、このラベルはsdカードのルートディレクトリを外挂けてマッピングされます.name属性は何の役にも立たないので、第三者が適用した仮想ディレクトリを惑わして、ファイルの本当のパスを隠します.
三、工具類FileUriPermissionCompat.java
/**
 * @Author:Smuel
 * @DateTime: 2018-08-30 14:43
 * @Description: android 7.0 uri    , 
* ( intent uri file app )
* local path net path
*/ public class FileUriPermissionCompat { private static final String TAG = FileUriPermissionCompat.class.getSimpleName(); // TODO: // AndroidManifest.xml provider authorities private static final String AUTHORITIES = "com.duke.personalkeeper.myFileProvider"; /** * 7.0 * * @return */ public static boolean isNeedAdapt() { //24 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; } public static Uri adaptUriAndGrantPermission(Context context, Intent intent, File file) { Uri uri = adaptUri(context, file); if (uri == null) { return null; } grantUriPermission(context, intent, uri); return uri; } public static Uri adaptUri(Context context, File file) { if (context == null || file == null) { return null; } // , 7.0 , parse() if (file.getPath().startsWith("http")) { return Uri.parse(file.getPath()); } Uri uri = null; try { if (isNeedAdapt()) { // 7.0 // FileProvider content Uri uri = FileProvider.getUriForFile(context, AUTHORITIES, file); } else { // uri = Uri.fromFile(file); } } catch (Exception e) { Log.e(TAG, "authorities value error, so can't convert uri !"); e.printStackTrace(); } return uri; } /** * uri * * @param context * @param intent * @param saveUri uri */ public static void grantUriPermission(Context context, Intent intent, Uri saveUri) { if (!isNeedAdapt()) { return; } if (context == null || intent == null || saveUri == null) { return; } // , if (saveUri.getScheme() != null && saveUri.getScheme().startsWith("http")) { // return; } //1、 ( 、 、 ) -- List resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; if (TextUtils.isEmpty(packageName)) { continue; } context.grantUriPermission(packageName, saveUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } //2、 ( apk ) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } public static void revokeUriPermission(Context context, Intent intent, Uri saveUri) { if (!isNeedAdapt()) { return; } if (context == null || intent == null || saveUri == null) { return; } // , if (saveUri.getScheme() != null && saveUri.getScheme().startsWith("http")) { // return; } try { context.revokeUriPermission(saveUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } catch (Exception e) { e.printStackTrace(); } } }

コアコード
uri = FileProvider.getUriForFile(context, AUTHORITIES, file);

fileとは、他のアプリケーションに露出したいファイルアドレスです.写真を撮って、結果をfileファイルに保存することのたとえです.AUTHERITIESは上記の最初のステップで、android:authorities=「{applicationId}取得はapp/build.gradleのdefaultConfigラベルのapplicationid値です.システムが提供するFileProviderクラスの静的方法でfileアドレスをcontent://で始まる特殊なuriに変換します.変換しない場合は、Uri.fromFile(file)を直接使用して、あなたが得たのはfile:///xxxxxこんなuri.この違いだけです.
変換が完了したら権限が必要です
/**
     *          uri     
     *
     * @param context
     * @param intent
     * @param saveUri     uri
     */
    public static void grantUriPermission(Context context, Intent intent, Uri saveUri) {
        if (!isNeedAdapt()) {
            return;
        }
        if (context == null || intent == null || saveUri == null) {
            return;
        }
        //         ,     
        if (saveUri.getScheme() != null && saveUri.getScheme().startsWith("http")) {
            //     
            return;
        }
        //1、  (    、  、     )  --        
        List resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            if (TextUtils.isEmpty(packageName)) {
                continue;
            }
            context.grantUriPermission(packageName, saveUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
        //2、  (  apk   )
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

中には2つの授権方式があり、複数のテストを経て、同時に使用する必要があることが分かった.1つ目の方法は、forループです.共有する必要があるアプリケーションのパッケージ名がどれなのか分からない場合があるので、可能性のあるサードパーティのアプリケーションを見つけて、すべて許可しました.
その後、apkをインストールするときは、上記の権限だけではだめで、intentを加えなければならないことがわかりました.addFlag方式で再許可しなければなりません.
最後に、以下の点に注意してください.
1、注意7.0のバージョン判定.
2、7.0の権限はsdカードの読み書きを必要とする可能性があり、6.0の読み書きsdカードの権限が必要であることを覚えておいてください.7.0権限のテストに成功しなかった場合は、6.0の権限が適切かどうかを考慮します.
他にはないと言った.これだけ