بررسی Runtime Permission اندروید با Annotation
در این مقاله قصد داریم تا با استفاده از Annotation Processing, دسترسی به Runtime Permission ها را بررسی کنیم.
Runtime permissions
برای دسترسی به Resource ها در اندروید, باید مجوز دسترسی به آن را بررسی کنیم. در واقع این مجوز ها را در فایل AndroidManifest.xml مشخص میکنیم. اندروید, از نسخه ۶ به بعد, این امکان را به کاربران داده است تا دسترسی به برخی از مجوز ها را لغو نماید. با استفاده از این امکان, میتوانیم از فعالیت های غیر قابل انتظار برنامه جلوگیری کنیم. برای مثال یک برنامه به سرویس پیامک ها دسترسی دارد. اگر این دسترسی مطابق با اهداف استفاده از برنامه نباشد, کاربر میتواند مجوز ذکر شده را لغو نماید. به این ترتیب دیگر برنامه از سرویس پیامک ها نمیتواند استفاده کند.
ممکن است کاربر مجوزی را که مورد نیاز بخشی از برنامه است در خلال استفاده از برنامه لغو نماید. بنابراین این مجوز ها، از نوع Runtime Permission ها هستند. برنامه نویس باید پیش از استفاده از منابع اندروید، مجوز دسترسی به آنها را بررسی نماید و در صورت صدور مجوز از سوی کاربر از آن منبع استفاده کند. در غیر این صورت برنامه با خطا مواجه و به صورت غیر قابل پیشبینی متوقف می شود. یکی از ابزار هایی که با استفاده از Annotation Processing مجوز استفاده از منابع را بررسی می کند، Permision Dispatcher است.
پیاده سازی
ابتدا Repository دریافت Dependency را به build.gradle (project) اضافه میکنیم:
allprojects { repositories { .... maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' } .... } }
سپس Dependency مورد نیاز را به build.gradle (module: app) اضافه میکنیم:
implementation("com.github.hotchemi:permissionsdispatcher:2.4.0") { // if you don't use android.app.Fragment you can exclude support for them exclude module: "support-v13" } annotationProcessor "com.github.hotchemi:permissionsdispatcher-processor:2.4.0"
در AndroidManifest.xml مجوز های مورد نیاز را مشخص میکنیم:
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
در این مقاله قصد داریم تا از مجوز دوربین و دسترسی به حافظه داخلی استفاده کنیم. در گام اول باید RuntimePermission@ را به کلاس پروژه اضافه کنیم:
@RuntimePermissions public class MainActivity extends AppCompatActivity {
اکنون باید متد هایی را که از Runtime Permission ها استفاده میکنند را مشخص کنیم و NeedPermission@ را به آن اضافه کنیم:
@NeedsPermission(Manifest.permission.CAMERA) public void useCamera() { System.out.println("Show camera"); } @NeedsPermission({Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}) public void useStorage() { System.out.println("Read or write "); }
با استفاده از این Annotation مشخص میکنیم که این متد ها از چه Runtime Permssion هایی استفاده میکنند. متغیر های ارسالی به آن میتوانند به صورت مفرد و یا آرایه باشند. یک بار پروژه را Build میکنیم تا با استفاده از Annotation Procesing, کد های مورد نیاز برای دسترسی به این مجوز ها ایجاد گردد. دو Button ایجاد میکنیم و با استفاده از ButterKnife به آنها دسترسی پیدا میکنیم:
@OnClick(R.id.camera) public void cameraPermission() { MainActivityPermissionsDispatcher.useCameraWithCheck(this); } @OnClick(R.id.storage) public void storage() { MainActivityPermissionsDispatcher.useStorageWithCheck(this); }
بعد از Build کردن پروژه, یک کلاس با نام MainActivityPermissionDispatcher ایجاد شده است. در واقع یک کلاس جدید ایجاد میشود که اول نام آن با نام کلاسی که در آن از Annotation استفاده شده است, یکسان است. سپس متد متناظر با آن را فراخوانی میکنیم. با هربار فراخوانی این متد ها, متدی که برای آن از NeedPermission@ استفاده کردهایم, فراخوانی میشود.
وقتی کاربر در اولین مرحله مجوز دسترسی را صادر نکند, در مرحله بعد یک پیغام برای نیاز برنامه به این مجوز نمایش داده میشود. این پیام ها با استفاده از OnShowRationale@ ایجاد و متناظر با مجوز نمایش داده میشود:
@OnShowRationale(Manifest.permission.CAMERA) public void showCameraAlert(PermissionRequest permissionRequest) { showDialog("need camera permission", permissionRequest); } private AlertDialog dialog; private AlertDialog showDialog(String message, PermissionRequest permissionRequest) { if (dialog!=null) dialog.cancel(); return new AlertDialog.Builder(this) .setPositiveButton("Allow", (dialogInterface, i) -> permissionRequest.proceed()) .setNegativeButton("Not now", (dialogInterface, i) -> permissionRequest.cancel()) .setMessage(message).show(); } @OnShowRationale({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}) public void showStorageAlert(PermissionRequest permissionRequest) { showDialog("need storage permission", permissionRequest); }
همچنین اگر کاربر دسترسی به مجوز را رد کند و یا Never Ask Again را انتخاب کند نیز میتوانیم پیام هایی متناسب با مجوز نمایش دهیم:
@OnPermissionDenied(Manifest.permission.CAMERA) public void cameraDeny() { System.out.println("Camera Permission denied"); } @OnPermissionDenied({Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}) public void storageDeny() { System.out.println("Storage Permission denied"); } @OnNeverAskAgain(Manifest.permission.CAMERA) public void neverAskCamera() { System.out.println("Set camera permission from setting"); } @OnNeverAskAgain({Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}) public void neverAskStorage() { System.out.println("set storage permission from setting"); }
همانطور که در این مقاله اشاره شد, میتوانیم با استفاده از Annotation Processing, بررسی Runtime Permission ها را انجام دهیم. این سبک از کدنویسی, کد ها را مرتب تر و خوانایی برنامه را افزایش میدهد.
با ما همراه باشید.
مطالب زیر را حتما مطالعه کنید
آموزش Gradle – اهمیت Project Automation
درک مفهوم کدنویسی تمیز در اندروید
5 هک ساده برای کاهش سایز فایل APK
آشنایی با RecyclerView در اندروید
Open/Closed Principle در قوانین Solid
توابع در زبان برنامه نویسی Kotlin
2 Comments
Join the discussion and tell us your opinion.
دیدگاهتان را بنویسید لغو پاسخ
برای نوشتن دیدگاه باید وارد بشوید.
سلام. من در این قسمت به مشکل برخورد کردم” Dependency مورد نیاز را به build.gradle (module: app) اضافه میکنیم:”
و برنامه خطا میده میشه راهنماییی کنید.
تنظیمات پروژه من به این صورت هست.
compileSdkVersion 27
minSdkVersion 17
targetSdkVersion 27
implementation ‘com.android.support:appcompat-v7:27.1.1’
ممنون از همراهیتون دوست عزیز.
در این بخش باید منبعی که dependency باید از اون دانلود بشه مشخص کنین. اگر پروژه شما چند module داشته باشه و فقط بخواین از این library در ماژول مشخص استفاده کنین٬ میتونین repositories در همون gradle فایل مربوط به module تعریف کنین. اما اگر در برنامه فقط یک module دارید و یا میخواین در تمام module ها ازش استفاده کنین٬ میتونین در build.gradle (projec) اونو قرار بدین. وقتی به repository ها
maven { url ‘http://oss.jfrog.org/artifactory/oss-snapshot-local/’ }
اضافه میکنین٬ عملا مسیر وجود artifact هارو براش مشخص کردین که از اونجا دریافت کنه. اگر موقع sync خطایی میده اونو بفرمایین تا راهنماییتون کنم