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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...