欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android11文件管理權(quán)限申請詳細(xì)介紹

 更新時間:2021年12月17日 10:48:31   作者:android_cai_niao  
大家好,本篇文章主要講的是Android11文件管理權(quán)限申請詳細(xì)介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽

Android 11文件管理權(quán)限申請

Android 11文件管理權(quán)限申請,為什么需要這個權(quán)限,因為在Android 11后,無法直接在SDcard根目錄寫文件,Android 11之后要使用分區(qū)存儲,但是分區(qū)存儲使用起來很麻煩,所以可以申請文件管理權(quán)限,這樣就可以隨意讀寫SDcard了,寫到根目錄也沒問題。

清單文件聲明如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.dazhou.permissionrequestdemo"
    xmlns:tools="http://schemas.android.com/tools">

	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />

    <application
        android:requestLegacyExternalStorage="true">
       。。。
    </application>

</manifest>

這里除了申請MANAGE_EXTERNAL_STORAGE權(quán)限之外,同時也是要申請WRITE_EXTERNAL_STORAGE權(quán)限的,因為在低于Android11的版本就需要使用WRITE_EXTERNAL_STORAGE權(quán)限,且需要在application節(jié)點添加android:requestLegacyExternalStorage="true",這個屬性用于Android10版本可以免去分區(qū)存儲。在Android11上,申請了MANAGE_EXTERNAL_STORAGE權(quán)限之后就不用申請WRITE_EXTERNAL_STORAGE權(quán)限了,因為擁有MANAGE_EXTERNAL_STORAGE權(quán)限應(yīng)該就能任意讀寫SDCard了。根據(jù)實驗,申請了MANAGE_EXTERNAL_STORAGE權(quán)限之后,再申請WRITE_EXTERNAL_STORAGE也是會彈出權(quán)限申請對話框的,所以,在Android11上還有沒有必要申請WRITE_EXTERNAL_STORAGE權(quán)限,值得思考,但我就懶得去實驗了。

class MainActivity : AppCompatActivity() {

    private lateinit var launcher: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            Log.i("ABCD", "權(quán)限申請結(jié)果:${it.resultCode == Activity.RESULT_OK}")
            checkAndroid11FilePermission(this)
        }

        findViewById<Button>(R.id.button).setOnClickListener {
            checkAndroid11FilePermission(this)
        }

    }

    /** 檢查Android 11或更高版本的文件權(quán)限 */
    private fun checkAndroid11FilePermission(activity: FragmentActivity) {
        // Android 11 (Api 30)或更高版本的寫文件權(quán)限需要特殊申請,需要動態(tài)申請管理所有文件的權(quán)限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (Environment.isExternalStorageManager()) {
                Log.i("ABCD","此手機(jī)是Android 11或更高的版本,且已獲得訪問所有文件權(quán)限")
                // TODO requestOtherPermissions() 申請其他的權(quán)限
            } else {
                Log.i("ABCD","此手機(jī)是Android 11或更高的版本,且沒有訪問所有文件權(quán)限")
                showDialog(activity, """本應(yīng)用需要獲取"訪問所有文件"權(quán)限,請給予此權(quán)限,否則無法使用本應(yīng)用""") {
                    launcher.launch(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
                }
            }
        } else {
            Log.i("ABCD","此手機(jī)版本小于Android 11,版本為:API ${Build.VERSION.SDK_INT},不需要申請文件管理權(quán)限")
            // TODO requestOtherPermissions() 申請其他的權(quán)限
        }
    }

    private fun showDialog(activity: FragmentActivity, message: String, okClick: () -> Unit) {
        AlertDialog.Builder(activity)
            .setTitle("提示")
            .setMessage(message)
            .setPositiveButton("確定") { _, _ -> okClick() }
            .setCancelable(false)
            .show()
    }

}

注:在獲取權(quán)限的結(jié)果時,不能使用it.resultCode == Activity.RESULT_OK來判斷是否獲得權(quán)限,因為這個結(jié)果永遠(yuǎn)為false。

Android 11和低版本的存儲權(quán)限結(jié)合

為了兼容低于Android 11的版本,我們把之前的存儲權(quán)限結(jié)合到一起,如下:

class MainActivity : AppCompatActivity() {

    private lateinit var storagePermissionLauncher: ActivityResultLauncher<String>
    private lateinit var android11StoragePermissionLauncher: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11或更高的版本
            android11StoragePermissionLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                requestStoragePermission(this)
            }
        } else {
            // Android 10或更低的版本
            storagePermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
                if (isGranted) {
                    Log.i("ABCD", "此手機(jī)是版本低于Android 11,且已獲得存儲權(quán)限")
                    // TODO requestOtherPermissions() 申請其他的權(quán)限
                } else {
                    Log.i("ABCD", "此手機(jī)是版本低于Android 11,且沒有存儲權(quán)限")

                    val desc = if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                        // 權(quán)限被拒絕
                        """本應(yīng)用需要獲取"存儲"權(quán)限,請給予此權(quán)限,否則無法使用本應(yīng)用"""
                    } else {
                        // 權(quán)限被設(shè)置為不再提示
                        """本App需要使用"存儲"權(quán)限,您需要到設(shè)置中打開此權(quán)限,否則無法使用本app"""
                    }
                    showDialog(this, desc) {
                        storagePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    }
                }
            }
        }

        findViewById<Button>(R.id.button).setOnClickListener {
            requestStoragePermission(this)
        }
    }

    /** 請求存儲權(quán)限 */
    private fun requestStoragePermission(activity: FragmentActivity) {
        Log.i("ABCD", "當(dāng)前手機(jī)版本:API ${Build.VERSION.SDK_INT}")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11 (Api 30)或更高版本的寫文件權(quán)限需要特殊申請,需要動態(tài)申請管理所有文件的權(quán)限
            if (Environment.isExternalStorageManager()) {
                Log.i("ABCD","此手機(jī)是Android 11或更高的版本,且已獲得訪問所有文件權(quán)限")
                // TODO requestOtherPermissions() 申請其他的權(quán)限
            } else {
                Log.i("ABCD","此手機(jī)是Android 11或更高的版本,且沒有訪問所有文件權(quán)限")
                showDialog(activity, """本應(yīng)用需要獲取"訪問所有文件"權(quán)限,請給予此權(quán)限,否則無法使用本應(yīng)用""") {
                    android11StoragePermissionLauncher.launch(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
                }
            }
        } else {
            // Android 10或更低的版本,申請存儲權(quán)限
            Log.i("ABCD","此手機(jī)是版本低于Android 11,開始申請存儲權(quán)限")
            storagePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
    }

    private fun showDialog(activity: FragmentActivity, message: String, okClick: () -> Unit) {
        AlertDialog.Builder(activity)
            .setTitle("提示")
            .setMessage(message)
            .setPositiveButton("確定") { _, _ -> okClick() }
            .setCancelable(false)
            .show()
    }

}

工具類封裝

object StoragePermissionUtil {

    private lateinit var storagePermissionLauncher: ActivityResultLauncher<String>
    private lateinit var android11StoragePermissionLauncher: ActivityResultLauncher<Intent>
    private lateinit var resultCallback: () -> Unit

    /**
     * 需求:
     * androidx.activity,1.2.0 或更高版本。
     * androidx.fragment,1.3.0 或更高版本。
     * 示例如下:
     * implementation "androidx.activity:activity-ktx:1.3.0"
     * implementation "androidx.fragment:fragment-ktx:1.3.6"
     */
    fun registerForActivityResult(activity: FragmentActivity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11或更高的版本
            android11StoragePermissionLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                requestStoragePermission(activity, resultCallback)
            }
        } else {
            // Android 10或更低的版本
            storagePermissionLauncher = activity.registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
                if (isGranted) {
                    Log.i("ABCD", "此手機(jī)是版本低于Android 11,且已獲得存儲權(quán)限")
                    resultCallback()
                } else {
                    Log.i("ABCD", "此手機(jī)是版本低于Android 11,且沒有存儲權(quán)限")

                    val desc = if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                        // 權(quán)限被拒絕
                        """本應(yīng)用需要獲取"存儲"權(quán)限,請給予此權(quán)限,否則無法使用本應(yīng)用"""
                    } else {
                        // 權(quán)限被設(shè)置為不再提示
                        """本App需要使用"存儲"權(quán)限,您需要到設(shè)置中打開此權(quán)限,否則無法使用本app"""
                    }
                    showDialog(activity, desc) {
                        storagePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    }
                }
            }
        }
    }

    /** 請求存儲權(quán)限 */
    fun requestStoragePermission(activity: FragmentActivity, resultCallback: () -> Unit) {
        this.resultCallback = resultCallback
        Log.i("ABCD", "當(dāng)前手機(jī)版本:API ${Build.VERSION.SDK_INT}")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11 (Api 30)或更高版本的寫文件權(quán)限需要特殊申請,需要動態(tài)申請管理所有文件的權(quán)限
            if (Environment.isExternalStorageManager()) {
                Log.i("ABCD","此手機(jī)是Android 11或更高的版本,且已獲得訪問所有文件權(quán)限")
                resultCallback()
            } else {
                Log.i("ABCD","此手機(jī)是Android 11或更高的版本,且沒有訪問所有文件權(quán)限")
                showDialog(activity, """本應(yīng)用需要獲取"訪問所有文件"權(quán)限,請給予此權(quán)限,否則無法使用本應(yīng)用""") {
                    android11StoragePermissionLauncher.launch(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
                }
            }
        } else {
            // Android 10或更低的版本,申請存儲權(quán)限
            Log.i("ABCD","此手機(jī)是版本低于Android 11,開始申請存儲權(quán)限")
            storagePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
    }

    private fun showDialog(activity: FragmentActivity, message: String, okClick: () -> Unit) {
        AlertDialog.Builder(activity)
                .setTitle("提示")
                .setMessage(message)
                .setPositiveButton("確定") { _, _ -> okClick() }
                .setCancelable(false)
                .show()
    }

}
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        StoragePermissionUtil.registerForActivityResult(this)

        findViewById<Button>(R.id.button).setOnClickListener {
            StoragePermissionUtil.requestStoragePermission(this) {
                Log.i("ABCD", "拿到存儲權(quán)限羅,開心^_^")
            }
        }
    }

}

Android 11申請管理所有文件權(quán)限的Bug

在申請權(quán)限的時候,會彈出系統(tǒng)授權(quán)界面,當(dāng)我們打開到如下界面后:

在這里插入圖片描述

此時,我們把權(quán)限打開,然后返回到我們Activity是正常的。但是,如果在此界面,我們打開權(quán)限后,再關(guān)閉,此后不管你是要再開或者不開,當(dāng)你返回Activity的時候,整個App會瞬間重啟,而且它會自動創(chuàng)建Activity,而且奇怪的時候,它會自動把結(jié)果回調(diào)到新Activity中注冊的監(jiān)聽器里,而在新Activity中,我們還沒有點擊按鈕申請權(quán)限呢,所以StoragePermissionUtil.requestStoragePermission(this)代碼就沒有被執(zhí)行到,則StoragePermissionUtil中的resultCallback變量就是未初始化的,所以授權(quán)結(jié)果就沒辦法返回到Activity中了,而且由于resultCallback沒初始化就使用,就會拋出屬性未初始化的異常。這屬于系統(tǒng)Bug吧感覺,也沒有什么好的解決方案了,在我的項目中,需要程序一運行就自動調(diào)用申請權(quán)限的函數(shù),這種情況沒有辦法能很好的解決,比如可以把resultCallback在registerForActivityResult中進(jìn)行傳遞,這樣能保證不會出現(xiàn)屬性未初始化的異常,但是按上面的操作,當(dāng)出現(xiàn)App重啟時,會收到兩次回調(diào)結(jié)果,一次回調(diào)結(jié)果是重啟前調(diào)用的申請回調(diào)到重啟后的注冊回調(diào)中,一次是重啟后再一次申請權(quán)限所以也能獲得一次回調(diào)。所以,這個Bug可以不管它羅,如果有用戶非要這樣操作,那就只能讓App崩潰了,管不了那么多了。

到此這篇關(guān)于Android11文件管理權(quán)限申請詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Android11文件管理權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論