Android許可權禁止及友好提示用戶開通必要許可權

来源:https://www.cnblogs.com/dingxiansen/archive/2019/04/08/10670707.html
-Advertisement-
Play Games

Android許可權 Android安全架構規定:預設情況下,任何應用都沒有許可權執行對其他應用、操作系統或用戶有不利影響的任何操作。這包括讀寫用戶的私有數據(聯繫人,簡訊,相冊,位置)、讀寫其他應用的文件、執行網路訪問、使設備保持喚醒狀態等等。 如果是一些正常的許可權(非高危許可權),比如網路訪問等在應用 ...


Android許可權
Android安全架構規定:預設情況下,任何應用都沒有許可權執行對其他應用、操作系統或用戶有不利影響的任何操作。這包括讀寫用戶的私有數據(聯繫人,簡訊,相冊,位置)、讀寫其他應用的文件、執行網路訪問、使設備保持喚醒狀態等等。

如果是一些正常的許可權(非高危許可權),比如網路訪問等在應用清單文件(AndroidManifest.xml)中配置,系統會自動授予,
但是如果有一些高危許可權,位置,文件存儲,簡訊等這個時候系統會要求用戶授予許可權,Android 發出許可權請求的方式取決於系統版本:
1、如果設備運行的是Android 6.0(Marshmallow,API 23)或更高版本,並且應用的targetSdkVersion是23或更高版本,則應用將在運行時向用戶請求許可權(Runtime Permissions)。用戶可隨時撤銷許可權,因此應用每次運行時都應該檢查自身是否具備所需的許可權。
2、如果設備運行的是Android 5.1(LOLLIPOP_MR1,API 22)或更低版本,並且應用的targetSdkVersion是22或更低版本,則系統在用戶安裝應用時就要求用戶授予許可權。如果更新應用時又新增了許可權,系統會在用戶更新應用時要求授予該許可權。用戶一旦安裝應用,他們撤銷許可權的唯一方式是卸載應用。

如果我們程式中某些功能,發佈一些圖片等操作,這個時候避免不了要訪問用戶設備的圖片,但是用戶開始的時候禁止了,用戶並不知道,這個時候訪問就會有問題了,那麼怎樣去提示用戶並且引導用戶去授予這些許可權呢,看下麵的效果(說的再多都不如圖來的實際)

下麵就開始擼碼了

private void getpermission() {
        //兩個日曆許可權和一個數據讀寫許可權
        String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}; //
        PermissionsUtils.showSystemSetting = true;//是否支持顯示系統設置許可權設置視窗跳轉
        //這裡的this不是上下文,是Activity對象!
        PermissionsUtils.getInstance().chekPermissions(this, permissions, permissionsResult);
    }

首先在頁面Activity啟動之後調用這個方法(註意:數組中的許可權可以自己配置,這裡我寫了四個)

許可權監聽介面對象

  //創建監聽許可權的介面對象
    PermissionsUtils.IPermissionsResult permissionsResult = new PermissionsUtils.IPermissionsResult() {
        @Override
        public void passPermissons() {
//許可權通過執行的方法
            //許可權通過驗證
        }

        @Override
        public void forbitPermissons() {
//這是沒有通過許可權的時候提示的內容,自定義即可
            Toast.makeText(mContext, "您沒有允許部分許可權,可能會導致部分功能不能正常使用,如需正常使用  請允許許可權", Toast.LENGTH_SHORT).show();
            finish();
//            Tool.exitApp();
        }
    };

還需要在activity中重寫一個方法

  @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //就多一個參數this
        PermissionsUtils.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }

許可權以及彈窗設置許可權工具類PermissionsUtils.java

/**
 * 許可權工具類
 */
public class PermissionsUtils {

    private final int mRequestCode = 100;//許可權請求碼
    public static boolean showSystemSetting = true;

    private PermissionsUtils() {
    }

    private static PermissionsUtils permissionsUtils;
    private IPermissionsResult mPermissionsResult;

    public static PermissionsUtils getInstance() {
        if (permissionsUtils == null) {
            permissionsUtils = new PermissionsUtils();
        }
        return permissionsUtils;
    }

    public void chekPermissions(Activity context, String[] permissions, @NonNull IPermissionsResult permissionsResult) {
        mPermissionsResult = permissionsResult;
        if (Build.VERSION.SDK_INT < 23) {
            //6.0才用動態許可權
            permissionsResult.passPermissons();
            return;
        }

        //創建一個mPermissionList,逐個判斷哪些許可權未授予,未授予的許可權存儲到mPerrrmissionList中
        List<String> mPermissionList = new ArrayList<>();
        //逐個判斷你要的許可權是否已經通過
        for (int i = 0; i < permissions.length; i++) {
            if (ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(permissions[i]);//添加還未授予的許可權
            }
        }
        //申請許可權
        if (mPermissionList.size() > 0) {//有許可權沒有通過,需要申請
            ActivityCompat.requestPermissions(context, permissions, mRequestCode);
        } else {
            //說明許可權都已經通過,可以做你想做的事情去
            permissionsResult.passPermissons();
            return;
        }
    }

    //請求許可權後回調的方法 //參數: requestCode  是我們自己定義的許可權請求碼
    // 參數: permissions  是我們請求的許可權名稱數組
    // 參數: grantResults 是我們在彈出頁面後是否允許許可權的標識數組,數組的長度對應的是許可權名稱數組的長度,數組的數據0表示允許許可權,-1表示我們點擊了禁止許可權
    public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean hasPermissionDismiss = false;
        //有許可權沒有通過
        if (mRequestCode == requestCode) {
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] == -1) {
                    hasPermissionDismiss = true;
                }
            }
            //如果有許可權沒有被允許
            if (hasPermissionDismiss) {
                if (showSystemSetting) {
                    showSystemPermissionsSettingDialog(context);//跳轉到系統設置許可權頁面,或者直接關閉頁面,不讓他繼續訪問
                } else {
                    mPermissionsResult.forbitPermissons();
                }
            } else {
                //全部許可權通過,可以進行下一步操作。。。
                mPermissionsResult.passPermissons();
            }
        }
    }

    /**
     * 不再提示許可權時的展示對話框
     */
    AlertDialog mPermissionDialog;

    private void showSystemPermissionsSettingDialog(final Activity context) {
        final String mPackName = context.getPackageName();
        if (mPermissionDialog == null) {
            mPermissionDialog = new AlertDialog.Builder(context).setMessage("已禁用許可權,請手動授予").setPositiveButton("設置", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    cancelPermissionDialog();
                    Uri packageURI = Uri.parse("package:" + mPackName);
                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                    context.startActivity(intent);
                    context.finish();
                }
            }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //關閉頁面或者做其他操作
                    cancelPermissionDialog();
                    //mContext.finish();
                    mPermissionsResult.forbitPermissons();
                }
            }).create();
        }
        mPermissionDialog.show();
        //放在show()之後,不然有些屬性是沒有效果的,比如height和width
        //以下代碼設置解決彈窗不居中問題,一側有邊距,一側沒有
        Window dialogWindow = mPermissionDialog.getWindow();
        WindowManager m = context.getWindowManager();
        Display d = m.getDefaultDisplay(); // 獲取屏幕寬、高
        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 獲取對話框當前的參數值
        // 設置寬度
        p.width = (int) (d.getWidth() * 0.95); // 寬度設置為屏幕的0.95
        p.gravity = Gravity.CENTER;//設置位置
        //p.alpha = 0.8f;//設置透明度
        dialogWindow.setAttributes(p);

    }

    //關閉對話框
    private void cancelPermissionDialog() {
        if (mPermissionDialog != null) {
            mPermissionDialog.cancel();
            mPermissionDialog = null;
        }
    }

    public interface IPermissionsResult {
        void passPermissons();

        void forbitPermissons();
    }
}

以上這些代碼就可以實現gif圖的效果,當然可以自定義任意效果
如果有問題請請聯繫[email protected],一起交流,共同進步

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • mysql排序問題(對字元串類型數據進行排序)對普通數字字元串欄位排序:select * from qq ORDER BY score*1 DESC,time*1 ASC 一、在mysql操作中我們經常需要對數據進行類型轉換。此時我們應該使用的是cast()或convert()。二、兩者的對比相同點 ...
  • 1.系統要通過嚴格的ACID測試,ACID表示原子性/一致性/隔離性/持久性原子性:一個事務必須被視為一個不可分割的最小工作單元一致性:資料庫總是從一個一致性的狀態轉換到另外一個一致性的狀態隔離性:通常來說一個事務所做的修改在最終提交以前對其他事務是不可見的持久性:一旦事務提交,則其所做的修改就會永 ...
  • 一、Hadoop的數據壓縮 1.概述 在進行MR程式的過程中,在Mapper和Reducer端會發生大量的數據傳輸和磁碟IO,如果在這個過程中對數據進行壓縮處理,可以有效的減少底層存儲(HDFS)讀寫的位元組數,,並且通過減少Map和Reduce階段數據的輸入輸出來提升MR程式的速度,提高了網路帶寬和 ...
  • AWZ愛偽裝 是一款通用的一鍵新機軟體,主要用於對應用偽裝設備參數和清理應用數據,它功能強大,設置豐富,且擁有完整的隨機參數設置、全息備份、虛擬定位功能;支持蘋果iOS越獄設備,不支持安卓系統;暫時支持ios7、8、9、10、11越獄系統,暫時不支持ios11.4之後的越獄(含ios11.4越獄系統 ...
  • 實際上我們通常是使用WebView控制項對本地html進行讀取,這樣就可以體會類似web app和安卓原生混合開發的樂趣了。在讀取本地html並展示在前臺的時候,並不需要在Androidmenifast.xml文件當中設置相應的網路許可權,也不需要設置https協議,因為安卓手機的本地伺服器應該都是基於 ...
  • 文章大綱 一、greenDao簡介二、greenDao實戰三、項目源碼下載四、參考文章 一、greenDao簡介 1. 什麼是greenDao GreenDAO是一個開源的Android ORM(“對象/關係映射”),通過ORM(稱為“對象/關係映射”),在我們資料庫開發過程中節省了開發時間。 2. ...
  • 方法如下: 因為在用WebView控制項查看安卓內置網頁的時候,必須創建這個資源文件夾,將網頁放置在這個目錄之下,預設是沒有assets這個目錄的,這樣才可以實現網頁代碼html.css.javascript與Android native的交互,所以我們來看一看怎麼做。很簡單,但不知道就做不來。讀取本 ...
  • 導入 #import <objc/runtime.h> unsigned int count; Method *methods = class_copyMethodList([UIAlertAction class], &count); for (int i = 0; i < count; i++) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...