android 一个字符串分两行显示_重新梳理Android权限管理
什么是Android權(quán)限?
權(quán)限(Permission),顧名思義是一種對信息訪問的申請。Android的權(quán)限有上百種,例如應(yīng)用程序嘗試調(diào)用撥號權(quán)限、調(diào)用攝像頭權(quán)限、調(diào)用讀取短信權(quán)限、調(diào)用讀取通訊錄權(quán)限等等。對于這些權(quán)限,Android將其按照危險(xiǎn)等級進(jìn)行了劃分分組,分成如下的三種類別:
- 正常權(quán)限(PROTECTION_NORMAL):指的是應(yīng)用程序需要訪問的一些數(shù)據(jù)資源,但并不涉及到用戶的隱私或者對其他應(yīng)用程序無害。例如設(shè)置鬧鐘就是屬于正常權(quán)限。Android在處理正常權(quán)限時(shí)并不會(huì)提示用戶,而用戶也沒有辦法取消這些正常權(quán)限
- 簽名權(quán)限(PROTECTION_SIGNATURE):指的是Android在安裝時(shí)授予應(yīng)用程序的權(quán)限,利用簽名權(quán)限,兩個(gè)簽名相同的應(yīng)用程序就可以進(jìn)行安全的數(shù)據(jù)共享。
- 危險(xiǎn)權(quán)限(PROTECTION_DANGEROUS ):指的是直接觸碰到用戶隱私或者影響其他程序操作的權(quán)限,對于這一類的權(quán)限,Android會(huì)以彈窗的方式向用戶進(jìn)行問詢,應(yīng)用程序必須要經(jīng)過用戶的授權(quán)后才可以進(jìn)行相應(yīng)的行為。
以危險(xiǎn)權(quán)限為例,Android規(guī)定了如下的權(quán)限必須請求用戶的許可。
Android權(quán)限獲取的方式
對于程序中申請的權(quán)限,都應(yīng)該在AndroidManifest.XML文件中進(jìn)行注冊,否則申請的權(quán)限將無法發(fā)揮作用。下圖中的AndroidManifest文件中添加了打電話和攝像頭的權(quán)限。
Android權(quán)限獲取可以分成兩個(gè)階段,在Android 6.0之前,所申請的權(quán)限只要在AndroidManifest文件中列舉就可以了,并會(huì)在程序安裝時(shí)全部顯示在安裝頁面上,這個(gè)過程并不區(qū)分權(quán)限是否為常規(guī)權(quán)限還是正常權(quán)限。這種方式是造成早期Android系統(tǒng)在隱私性做的不好的直接原因,因?yàn)橛脩粼诎惭b應(yīng)用程序時(shí),很多時(shí)候并不會(huì)去仔細(xì)查看程序彈出的方框到底包含了哪些危險(xiǎn)的權(quán)限,為了盡快的進(jìn)入程序首頁,一般都會(huì)同意全部彈出的權(quán)限,這就給了很多流氓程序肆意發(fā)揮的入口。下圖展示了Android 5.0安裝界面的部分危險(xiǎn)權(quán)限截圖。
Google顯然也注意到了這一點(diǎn),于是在Android 6.0中推出了一種運(yùn)行時(shí)權(quán)限管理機(jī)制,這種機(jī)制對原有的權(quán)限處理方式進(jìn)行了很大程度的改善:應(yīng)用程序安裝后,點(diǎn)開程序時(shí),不再是列出程序申請的所有權(quán)限,而是將部分危險(xiǎn)權(quán)限與應(yīng)用本身的功能相關(guān)聯(lián)。例如相機(jī)應(yīng)用,只有當(dāng)用戶點(diǎn)擊拍照按鈕時(shí),系統(tǒng)就會(huì)彈出申請攝像頭的權(quán)限,這種方式將用戶的注意力集中到了當(dāng)下的操作上,使得用戶有足夠的時(shí)間和意愿去判定是否同意程序的權(quán)限申請,并且用戶隨時(shí)可以在設(shè)置中關(guān)掉授予程序的危險(xiǎn)權(quán)限,從而極大程度上避免了對危險(xiǎn)權(quán)限的放行,保護(hù)了用戶的隱私。
Android 6.0之后的運(yùn)行時(shí)權(quán)限處理機(jī)制很好的解決了危險(xiǎn)權(quán)限的獲取問題,它具有如下的兩個(gè)行為:
- 如果應(yīng)用程序在當(dāng)前的權(quán)限組(一組權(quán)限的集合)中沒有任何權(quán)限,那么在請求權(quán)限時(shí),系統(tǒng)會(huì)顯示該權(quán)限組的請求對話框,例如程序請求CALL_PHONE權(quán)限,那么Android將彈出CALL權(quán)限對話框顯示應(yīng)用希望撥打電話功能。
- 如果一個(gè)權(quán)限組中的任意一個(gè)權(quán)限被授權(quán),那么該權(quán)限組中的其他權(quán)限都會(huì)被Android默認(rèn)授權(quán)。例如上面的CALL_PHONE權(quán)限被允許,那么PHONE權(quán)限組中的其它權(quán)限,例如READ_PHONE_NUMBERS讀取電話號碼的權(quán)限就會(huì)默認(rèn)被授權(quán),并且不會(huì)向用戶彈框顯示權(quán)限申請過程。
運(yùn)行時(shí)權(quán)限處理機(jī)制中的第二點(diǎn)的特性并不被Google推崇,Google認(rèn)為后續(xù)的Android版本中這個(gè)特征可能會(huì)發(fā)生變化,并建議開發(fā)者應(yīng)明確指出所需要的每一個(gè)權(quán)限。
Android實(shí)現(xiàn)權(quán)限管理
關(guān)于Android權(quán)限更詳細(xì)的介紹可以在官方的Android Developer指南中查閱。重點(diǎn)是如何在實(shí)踐中學(xué)會(huì)使用Android權(quán)限,后半部分將會(huì)以代碼和流程圖的方式展示Android權(quán)限管理。
Android權(quán)限處理可以分解為三個(gè)部分:
從代碼層面考慮,Android提供了一個(gè)requestPermissions()的調(diào)用方法來請求相應(yīng)權(quán)限,這個(gè)方法接受目標(biāo)Activity、 需要請求授權(quán)的權(quán)限組和識別權(quán)限請求的請求代碼作為參數(shù)傳遞,并且它是一個(gè)異步的方法,并返回產(chǎn)生的結(jié)果。
權(quán)限獲取的一般過程就是遵循上面的三個(gè)步驟進(jìn)行的,但是千萬不要忘記了所申請的權(quán)限一定要在AndroidManifest.xml中注冊,不然就準(zhǔn)備嘗嘗異常拋出鐵拳的力量吧。
當(dāng)然,更清晰明了的是用流程圖來展示權(quán)限申請和授權(quán)的過程。
單個(gè)權(quán)限的獲取過程
下面以獲取打電話的權(quán)限為例,通過代碼實(shí)現(xiàn)的方式來解釋這個(gè)流程的具體做法。以下面一個(gè)Demo的頁面為測試對象,只要點(diǎn)擊獲取電話權(quán)限按鈕,就會(huì)彈出權(quán)限提示窗,然后允許該請求,就可以實(shí)現(xiàn)跳轉(zhuǎn)到撥號頁面進(jìn)行通話的功能。
第一部分是檢測權(quán)限部分。點(diǎn)擊獲取電話權(quán)限按鈕,就會(huì)調(diào)用程序中的callPermission()這個(gè)方法,在callPermission中調(diào)用checkSelfPermission的方法進(jìn)行權(quán)限檢測,實(shí)參是當(dāng)前的Activity對象和對應(yīng)的權(quán)限,這個(gè)方法返回一個(gè)int類型的值,其中若權(quán)限允許則返回值為0的PERMISSION_GRANTED,否則返回值為-1的PERMISSION_DENIED,當(dāng)權(quán)限已經(jīng)被允許的情況下,直接調(diào)用else語句中的callPhone()方法,意味著直接可以撥打電話了。
當(dāng)權(quán)限檢測為未允許的情況下,進(jìn)入請求權(quán)限狀態(tài),即if語句中的requestPermissions這個(gè)方法,這個(gè)方法會(huì)創(chuàng)建一個(gè)字符串?dāng)?shù)組,將請求的權(quán)限同一放入這個(gè)數(shù)組中,最后一個(gè)參數(shù)是一個(gè)int類型的requestCode,該值在后續(xù)的處理權(quán)限中發(fā)揮作用,并且這個(gè)值不一定取1,只要這個(gè)值大于等于0即可。為了方便起見,這里取1作為請求碼。
@Overridepublic void onClick(View view) {switch (view.getId()){case R.id.getCallPermission:Toast.makeText(MainActivity.this, "獲取打電話權(quán)限", Toast.LENGTH_SHORT).show();callPermission();break;case R.id.getCameraPermission:Toast.makeText(MainActivity.this, "轉(zhuǎn)至第二個(gè)頁面", Toast.LENGTH_SHORT).show();Intent intent = new Intent(this, SecondActivity.class);startActivity(intent);default:break;}}/*** 查詢app是否有相關(guān)權(quán)限* 如果有就直接調(diào)用寫的方法* 沒有的話就需要申請權(quán)限*/private void callPermission(){if(ActivityCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){// 說明沒有該權(quán)限,就需要申請權(quán)限ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE}, 1);}else {callPhone();}}當(dāng)用戶點(diǎn)擊了權(quán)限的彈窗后,Android會(huì)調(diào)用下面的onRequestPermissionsResult的方法,這個(gè)方法接受從requestPermissions()方法傳遞的requestCode、權(quán)限字符串?dāng)?shù)組和用戶響應(yīng)數(shù)組這三種作為參數(shù),用戶響應(yīng)數(shù)組中的元素個(gè)數(shù)應(yīng)與申請的權(quán)限字符串?dāng)?shù)組中元素個(gè)數(shù)保持一致。requestCode的作用是作為請求權(quán)限時(shí)權(quán)限處理成功的一種標(biāo)識,只有這個(gè)標(biāo)識匹配正確了,才能進(jìn)一步的核對用戶響應(yīng)數(shù)組中的元素是否與PERMISSION_GRANTED相等,從而驗(yàn)證權(quán)限是否真正的被用戶所允許。所以上一步的requestCode在這里發(fā)揮了作用。應(yīng)當(dāng)注意的是,由于這個(gè)實(shí)例只用了一個(gè)權(quán)限,所以應(yīng)該通過索引的方式來獲取用戶響應(yīng)數(shù)組中的第一個(gè)元素grantResult[0]。
/*** 權(quán)限申請的回調(diào)結(jié)果* @param requestCode 請求碼* @param permissions 請求權(quán)限* @param grantResults 授權(quán)結(jié)果,是一個(gè)int型數(shù)組,若有多個(gè)授權(quán),則依次讀取*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if(requestCode == 1){if(grantResults[0] == PackageManager.PERMISSION_GRANTED){callPhone();}else {Toast.makeText(this, "權(quán)限未授權(quán)!", Toast.LENGTH_SHORT).show();}}}/*** 打電話,注意異常處理,不然會(huì)報(bào)錯(cuò)*/private void callPhone(){try{Intent intent = new Intent(Intent.ACTION_CALL);Uri uri = Uri.parse("tel:" + 10086);intent.setData(uri);startActivity(intent);}catch (SecurityException e){e.printStackTrace();}}對于單個(gè)的權(quán)限而言,上述的流程就可以完成權(quán)限獲取的全部操作,在手機(jī)端運(yùn)行程序,點(diǎn)擊獲取電話權(quán)限后就會(huì)彈出權(quán)限窗口,點(diǎn)擊允許后轉(zhuǎn)到電話撥打的界面。
那么如果想一次性申請多個(gè)權(quán)限,該如何處理這種需求?
多個(gè)權(quán)限的獲取過程
假設(shè)需要一個(gè)按鈕來獲取兩個(gè)權(quán)限:打電話權(quán)限和攝像頭權(quán)限。處理的方式和上面的大同小異,如果你注意到上述請求權(quán)限和處理權(quán)限響應(yīng)的方法中,它們都是接收一個(gè)權(quán)限字符串?dāng)?shù)組和用戶響應(yīng)字符串?dāng)?shù)組,那么問題就很好解決了。思路如下:
- 構(gòu)建一個(gè)申請權(quán)限的ArrayList
- 檢測權(quán)限,并將沒有被授予允許的權(quán)限通通add到ArrayList中
- 轉(zhuǎn)換ArrayList變?yōu)閞equestPermissions的參數(shù)
- 依次讀取用戶響應(yīng)數(shù)組中的grantCode,判斷是否授權(quán)
- 授權(quán)過程結(jié)束
下面的代碼展示了如何一鍵處理兩個(gè)權(quán)限的過程。
private void callAllPermissions(){List<String> permissionsList = new ArrayList<>();if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)!= PackageManager.PERMISSION_GRANTED){permissionsList.add(Manifest.permission.CALL_PHONE);}if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){permissionsList.add(Manifest.permission.CAMERA);}//不為空,說明有需要授權(quán)的部分if(!permissionsList.isEmpty()){ActivityCompat.requestPermissions(this,permissionsList.toArray(new String[permissionsList.size()]), 1);}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:int resultLength = grantResults.length;//說明回調(diào)成功了,權(quán)限授權(quán)被允許if(resultLength > 0){for(int grantCode : grantResults){if(grantCode == PackageManager.PERMISSION_GRANTED){Toast.makeText(this, "授權(quán)成功", Toast.LENGTH_SHORT).show();}else{Toast.makeText(this, "授權(quán)失敗", Toast.LENGTH_SHORT).show();}}}break;default:break;}}上述的過程完成后,程序所需要的權(quán)限得到了滿足,便可以繼續(xù)的進(jìn)行后續(xù)的業(yè)務(wù)邏輯。但是仍然要提醒一點(diǎn),Android 6.0以后,權(quán)限是可以由用戶手動(dòng)關(guān)閉的,并不是永久授權(quán),這意味著今天的授權(quán)成功并不代表著明天就不需要授權(quán)了,因此權(quán)限的檢查是必須要有的一個(gè)步驟。
總結(jié)
在以前學(xué)習(xí)Android的時(shí)候接觸過權(quán)限處理,所以這次結(jié)合業(yè)務(wù)上遇到權(quán)限處理的問題,借助Android Developer的指南,對Android 6.0后的權(quán)限問題進(jìn)行了一次重新的梳理。通過實(shí)例和流程圖來展示Android對于危險(xiǎn)權(quán)限的獲取過程和一些應(yīng)該注意的地方。同時(shí)也應(yīng)該時(shí)刻的關(guān)注官網(wǎng)的指南,因?yàn)闄?quán)限問題可能隨著版本的更迭而發(fā)生一些調(diào)整或改變,不然很容易出現(xiàn)代碼一樣但出現(xiàn)異常的情況。
更多文章可以在公眾號追風(fēng)棧Binary中查看,如果能幫助到你一點(diǎn)點(diǎn),那就太好了~
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的android 一个字符串分两行显示_重新梳理Android权限管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ES aggregation详解
- 下一篇: android 禁用dlsym_Andr