2018-05-07

【Android Studio】執行時期為 APP 取得權限(授權)

參考資料 ----
Request App Permissions


在執行時期取得權限,是自 Marshmallow(6.0, API23) 加入的功能,為使用者提供更多保護;回想一下,您在安裝 APP 時,會仔細看 APP 要求取得哪些權限嗎?自 Android6.0(含) 起,在 APP 第一次執行時,會提示使用者,您的 APP 需要取得哪些權限,並必須得使用者允許。

所以在 Android6.0(含) 以上的裝置,如果沒有撰寫相關的程式碼,為 APP 執行時期取得權限,嚴重時甚至 APPcrash 掉!

AndroidManifest.xml (宣告 APP 必須取得的權限)
  1.  
  2. <!-- 要求取得相機權限 -->
  3. <uses-permission android:name="android.permission.CAMERA"/>
  4.  
  5. ...
  6. ...
  7.  
  8. <application
  9. ...
  10. ...
  11.  

編輯 build.gradle(Module: app)
  1.  
  2. dependencies {
  3. ...
  4. ...
  5.  
  6. implementation 'com.android.support:design:27.1.1' // Snackbar 需要
  7. }
  8.  


activity_main.xml (記得要給 layout ID,不然 Snackbar 不會顯示)
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <android.support.constraint.ConstraintLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. xmlns:app="http://schemas.android.com/apk/res-auto"
  6. xmlns:tools="http://schemas.android.com/tools"
  7. android:id="@+id/main_layout"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. tools:context=".MainActivity">
  11.  
  12. <Button
  13. android:layout_width="wrap_content"
  14. android:layout_height="wrap_content"
  15. android:text="開啟相機"
  16. app:layout_constraintBottom_toBottomOf="parent"
  17. app:layout_constraintLeft_toLeftOf="parent"
  18. app:layout_constraintRight_toRightOf="parent"
  19. app:layout_constraintTop_toTopOf="parent"
  20. android:onClick="showCameraPreview"/>
  21.  
  22. </android.support.constraint.ConstraintLayout>
  23.  

Mainactivity.java
  1.  
  2. public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback
  3. {
  4. private static final int PERMISSION_REQUEST_CAMERA = 0;
  5. private View mLayout;
  6.  
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState)
  9. {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_main);
  12.  
  13. mLayout = findViewById(R.id.main_layout);
  14. }
  15.  
  16. public void showCameraPreview(View v)
  17. {
  18. if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)
  19. {
  20. Snackbar.make(mLayout, "已取得相機權限, 開始預覽", Snackbar.LENGTH_SHORT).show();
  21. startCamera();
  22. }
  23. else
  24. {
  25. requestCameraPermission();
  26. }
  27. }
  28.  
  29. private void startCamera()
  30. {
  31. // 開啟相機, 在此寫您自己的程式
  32. }
  33.  
  34. private void requestCameraPermission()
  35. {
  36. if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA))
  37. {
  38. Snackbar.make(mLayout, "需要取得相機權限", Snackbar.LENGTH_INDEFINITE)
  39. .setAction("OK", new View.OnClickListener()
  40. {
  41. @Override
  42. public void onClick(View view)
  43. {
  44. ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
  45. }
  46. })
  47. .show();
  48. }
  49. else
  50. {
  51. Snackbar.make(mLayout, "無法開啟相機,可能有其他 APP 正在使用中 或 本 APP 尚未取得授權", Snackbar.LENGTH_SHORT).show();
  52. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
  53. }
  54. }
  55.  
  56. @Override
  57. public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
  58. {
  59. if (requestCode == PERMISSION_REQUEST_CAMERA)
  60. {
  61. if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
  62. {
  63. Snackbar.make(mLayout, "已取得相機權限, 開始預覽", Snackbar.LENGTH_SHORT)
  64. .show();
  65. startCamera();
  66. }
  67. else
  68. {
  69. Snackbar.make(mLayout, "請求相機權限被拒", Snackbar.LENGTH_SHORT)
  70. .show();
  71. }
  72. }
  73. }
  74. }
  75.  


APP 安裝到實體裝置後,先關閉不執行,到 Android 的 "設定" 進一步觀察:

安裝在 KitKat4.4(API19),就已經取得權限



安裝在 Oreo8.0(API26),尚未取得權限



執行 APP,點擊 "開啟相機" 鈕,會出現請求授權的畫面



選取 "拒絕",就會跳出 "請求相機權限被拒" 的 Snackbar



再按一次 "開啟相機",這次 Snackbar 會提示您 APP 需要取得相機權限,選取 "OK"



打勾 "不要再詢問",並再次拒絕



這麼一來,就再也不會出現請求授權的畫面了,只能到 "設定" → 應用程式與通知應用程式資訊 → 找到 APP → 點擊 "權限" 去手動開啟授權

或是將 APP 移除再重新安裝了



若是在 請求授權畫面選擇 "允許" 或 手動進 "設定" 開啟授權 後,執行 APP 點擊 "開啟相機" 鈕,就會跳出已取得授權的 Snackbar




相關筆記 ----
Snackbar -- 比 Toast 更多功能的 跳出式訊息