Trong lập trình Android nói riêng hay lập trình mobile nói chung khi mà bạn muốn tương tác gì đó từ thiết bị với bên ngoài , hoặc bạn muốn can thiệp vào sâu trong hệ thống của thiết bị thì bắt buộc bạn phải xin quyền người dùng mới được chứ bạn không thể nào tự động làm tất cả mọi thứ đâu nhé.
Trước đây android ở phiên bản nào đó mà ứng dụng có thể tự đông gửi tin nhắn đi mà không hiện thông báo lên cho người dùng, mình nhớ lúc đó rất nhiều người bị mất tiền oan ở các đầu số 87xx, 1 tin nhắn đến 15.000đ gì đó đấy chứ.
Và để bạn có thể gửi tin nhắn đi được bắt buộc bạn phải xin cấp quyền trong file AndroidMainifest.xml thì mới được, ở bài 6 mình có nói qua rồi bạn nên xem lại tí nhé để học bài này cho nó dễ.
Và kết thúc bài này chúng ta sẽ đi vào thực hành tiếp theo bài thực hành làm ứng dụng danh bạ, bữa trước chung ta chỉ dừng lại ở việc tạo danh bạ thôi đúng không nào, thì tiếp theo chúng ta sẽ làm có nó có thể gọi điện, nhắn tin được… các bạn quan tâm thì theo dõi ở blog nhé.
Nội dung
Vậy trong android có những quyền nào?
Trong android có 2 loại quyền chính đó là Permission thường và Permission nguy hiểm, nếu từ phiên bản android 5.0 trở về trước thì thực chất 2 thằng này sẽ không khác nhau là bao nhiêu bởi vì nó đều được khai báo – xin quyền trong AndroidManifest.xml, tuy nhiên từ bản android 6.0 thì các lập trình viên phải xin quyền thằng này cả trong AndroidManifest và cả khi ứng dụng khởi chạy lên đối với những Permission nguy hiểm.
Permission thường
Là những Permission đơn giản, không can thiệp sâu vào trong hệ thống và bạn chỉ cần khai báo xin cấp quyền trong file AndroidManifest.xml, khi lập trình bạn sẽ không phải xin cấp quyền lần nào nữa.
Khi người dùng tải ứng dụng về bạn sẽ thấy google thông báo các quyền này lên bảo người dùng đồng ý và từ này về sau ứng dụng sẽ không hỏi thêm gì nữa, nó bao gồm các quyền như sau:
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS android.permission.ACCESS_NETWORK_STATE android.permission.ACCESS_NOTIFICATION_POLICY android.permission.ACCESS_WIFI_STATE android.permission.ACCESS_WIMAX_STATE android.permission.BLUETOOTH android.permission.BLUETOOTH_ADMIN android.permission.BROADCAST_STICKY android.permission.CHANGE_NETWORK_STATE android.permission.CHANGE_WIFI_MULTICAST_STATE android.permission.CHANGE_WIFI_STATE android.permission.CHANGE_WIMAX_STATE android.permission.DISABLE_KEYGUARD android.permission.EXPAND_STATUS_BAR android.permission.FLASHLIGHT android.permission.GET_ACCOUNTS android.permission.GET_PACKAGE_SIZE android.permission.INTERNET android.permission.KILL_BACKGROUND_PROCESSES android.permission.MODIFY_AUDIO_SETTINGS android.permission.NFC android.permission.READ_SYNC_SETTINGS android.permission.READ_SYNC_STATS android.permission.RECEIVE_BOOT_COMPLETED android.permission.REORDER_TASKS android.permission.REQUEST_INSTALL_PACKAGES android.permission.SET_TIME_ZONE android.permission.SET_WALLPAPER android.permission.SET_WALLPAPER_HINTS android.permission.SUBSCRIBED_FEEDS_READ android.permission.TRANSMIT_IR android.permission.USE_FINGERPRINT android.permission.VIBRATE android.permission.WAKE_LOCK android.permission.WRITE_SYNC_SETTINGS com.android.alarm.permission.SET_ALARM com.android.launcher.permission.INSTALL_SHORTCUT com.android.launcher.permission.UNINSTALL_SHORTCUT
Permission nguy hiểm
Là những quyền thường can thiệp sâu vào hệ thống điện thoại Android như: đọc danh bạ, đọc tập tin, tải file… không đâu xa bạn thử tải phần mềm Zalo về thử xem, nó sẽ xin quyền đọc danh bạ của bạn để lấy ra các số điện thoại và từ đó gợi ý cho bạn những người quen của bạn.Nếu người không biết về lập trình sẽ thấy nó ghê gớm nhưng bản chất nó là như vậy, rất là đơn giản.
Thì những quyền này cũng phải khai báo hết trong AndroidManifest như trên thôi tuy nhiên từ android 6.0 trở đi bạn phải xin thêm quyền nó khi ứng dụng khởi chạy nữa.Nếu không xin quyền được thì khi bạn làm gì đó đụng đến thì sẽ xảy ra lỗi ngay.
Ví dụ download tấm ảnh về lưu vào thẻ nhớ/máy là phải xin quyền ghi file (WRITE_EXTERNAL_STORAGE).
Chi tiết bạn đọc thêm ở bài viết xin quyền Permisson android trên Marshmallow 6.0 tại blog mình nhé.
Vậy những quyền nào là quyền nguy hiểm bạn nhìn xuống dưới đây nhé:
Xin quyền trong android như thế nào?
Từ android 5.0 trở xuống
Chỉ đơn giản là bạn sẽ đoán xem ứng dụng của bạn sẽ dụng đến quyền gì mà biết để bạn thêm vào trong file AndroidManifest thôi chứ chẳng có gì khó khăn cả.
Ví dụ bây giờ bạn làm một ứng dụng nghe nhạc online thì sẽ biết ngay là bạn phải xin quyền kết nối internet và quyền ghi và đọc file để trường hợp bạn hiển thị những bài hát trong điện thoại lên hoặc là khi tải bài hát xuống thiết bị.Vậy bạn sẽ xin quyền như sau:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cungxunu.cunghoangdao.cheng.webviewdemo"> <!--Xin quyền kết nối internet--> <uses-permission android:name="android.permission.INTERNET"/> <!--Xin quyền đọc file--> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!--Xin quyền ghi file--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <applicatione android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </applicatione> </manifest>
Nếu như bây giờ bạn không khai báo quyền truy cập internet thì khi ứng dụng bạn tiến hành tải app thì sẽ xảy ra một lỗi như sau, tương tự các quyền khác cũng thông báo dạng như vậy, lúc này ứng dụng sẽ bị crash ngay lập tức.
marshmallow W/System.err: java.lang.SecurityException: Permission denied (missing INTERNET permission?) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.net.InetAddress.lookupHostByName(InetAddress.java:451) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.net.InetAddress.getAllByName(InetAddress.java:215) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:367) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:295) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382) 09-01 20:03:27.034 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:106) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.android.okhttp.internal.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.cheng.permissonandroidmarshmallow.MainActivity$ImageLoadTask.doInBackground(MainActivity.java:96) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at com.cheng.permissonandroidmarshmallow.MainActivity$ImageLoadTask.doInBackground(MainActivity.java:80) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:288) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.lang.Thread.run(Thread.java:818) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at libcore.io.Posix.android_getaddrinfo(Native Method) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: at java.net.InetAddress.lookupHostByName(InetAddress.java:438) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: ... 19 more 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: Caused by: android.system.ErrnoException: android_getaddrinfo failed: EACCES (Permission denied) 09-01 20:03:27.044 7053-8007/com.cheng.permissonandroidmarshmallow W/System.err: ... 22 more
Vậy thôi, như thế là ứng dụng bạn có thể thoải mái dùng rồi dù là quyền bình thường hay quyền nguy hiểm thì với Android Lolipop 5.0 trở xuống bạn chỉ cần khi báo vậy là xong, còn nếu bạn muốn ứng dụng bạn chạy được trên máy android 6.0 trở lên thì bạn phải xem tiếp ở phía dưới.
Từ android 6.0 trở lên
Ở ví dụ trên có 2 quyền nằm trong quyền nguy hiểm đó là quyền đọc và ghi file chính vì thế khi chạy ứng dụng trên thiết bị android 6.0 Marshmallow trở lên sẽ xảy ra lỗi nếu như bạn chỉ xin cấp quyền ở trong file AndroidManifest mà thay vào đó bạn phải xin lại quyền trong lúc run time nghĩa là khi ứng dụng khởi chạy và chỉ cần xin 1 lần duy nhất thôi nhé các bạn.
Để xin quyền khi run time cho android 6.0 bạn sẽ thêm chi tiết bài hướng dẫn của mình ở đây vì nó cũng khá là dài luôn đó, không khó lắm nên các bạn cứ iên tâm.Quyền này sẽ có dạng thông báo như sau khi các bạn khởi động app:
Về quyền thì cơ bản chỉ có vậy thôi, trong video bên dưới mình sẽ nói rõ hơn tí cho các bạn hiểu, và mọi ý kiến thắc mắc xin các bạn cứ comment bên dưới blog mình nhé.
Video giới thiệu Permission trong android
Chúc các bạn học tập vui vẽ!
Xem thêm