What is the best way to check run-time permissions using the MVP architecture?

I am developing an Android application in which I have to request permissions at runtime. I am wondering how best to implement this using the Model-View-Presenter architecture.

My initial thought was that the host would call the component responsible for permissions (e.g. PermissionHandler ) and update the view accordingly.

The problem is that the code for checking permissions is closely related to the Activity class. Here are some of the methods that require action or context:

  • ContextCompat.checkSelfPermission()
  • ActivityCompat.shouldShowRequestPermissionRationale()
  • ActivityCompat.requestPermissions()
  • onRequestPermissionsResult() (callback)

This means that I would have to pass the activity object to the presenter, which I did not like, because I heard that keeping the presenter for free from Android code is good for testing.

In this regard, I then thought about how to handle permissions at the presentation level (in action), but then I assume that it would hurt the goal to leave an opinion that is responsible only for updating the user interface, without business logic.

I am not sure what would be the best approach to solving the problem in order to keep the code as untied and supported as possible. Any ideas?

+5
source share
2 answers

What would I do:

The view will be implemented:

 public Activity getViewActivity(); 

Lead implements:

 public void requestPermissions(); public void onPermissionsResult(); 

Inside the requestPermissions facilitator will do: getViewActivity().checkSelfPermission; getViewActivity.requestPermissions(); etc. getViewActivity().checkSelfPermission; getViewActivity.requestPermissions(); etc.

The view will call inside the onRequestPermissionsResult on presenter.onPermissionsResult();

In this case, all the logic will be implemented inside the presenter.

In my opinion, your host is disabled: it will not depend on any implementation of the view (it will depend only on the view interface).

"I heard that keeping the presenter free from Android code is good for testing." I do not understand this part. If the code is good, it can be tested without any problems.

+7
source

If you still want to cheat with access rights / requests, you still create something like PermissionHandler , but refer only to it in your view class. For instance -

Interface:

 public interface PermissionsHandler { boolean checkHasPermission(AppCompatActivity activity, String permission); void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode); } 

Production implementation:

 public class PermissionsHandlerAndroid implements PermissionsHandler { @Override public boolean checkHasPermission(AppCompatActivity activity, String permission) { return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED; } @Override public void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode){ ActivityCompat.requestPermissions(activity, permissions, requestCode); } } 

A dedicated class (for example, to check and make sure that your activity correctly processes onRequestPermissionsResult )

 public class PermissionsHandlerMocked implements PermissionsHandler { @Override public boolean checkHasPermission(AppCompatActivity activity, String permission) { return false; } @Override public void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode){ int[] grantResults = new int[permissions.length]; for (int i = 0; i < permissions.length; i++) { grantResults[i] = PackageManager.PERMISSION_GRANTED } activity.onRequestPermissionResult(requestCode, permissions, grantResults); } } 

Then in your activity:

 PermissionsHandler permissionsHandler; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); permissionsHandler = Injection.providePermissionsHandler(); //or however you choose to inject your production vs mocked handler. } //method from your view interface, to be called by your presenter @Override void requestLocationPermission() { permissionsHandler.requestPermision((AppCompatActivity) this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE_LOCATION}; } 

fobo66 , you can always force a view to implement much more general methods such as checkLocationPermissionGranted() and requestLocationPermission() . Then your implementation of the view can refer to the activity as necessary, and your host will never have to touch the link to the action.

+1
source

Source: https://habr.com/ru/post/1260894/


All Articles