1. Are you ready for the Galaxy S20? Here is everything we know so far!

Where should LocationManager be placed in MVP?

Discussion in 'Android Development' started by twopelu, Oct 29, 2018.

  1. twopelu

    twopelu Lurker
    Thread Starter

    Im refactoring my messy Activity code to a MVP architecture, but Im not sure where to put LocationManager and permission checks...any help please? Thanks, Dani

     


  2. Best Answer:
    Post #7 by Deleted User, Oct 30, 2018 (1 points)
  3. Deleted User

    Deleted User Guest

    The logical place for that would be in the model, which contains the business logic, and database access components.
     
  4. twopelu

    twopelu Lurker
    Thread Starter

    Thanks form your response!

    Thats what I did at first time, the only problem I see is that the Model gets coupled with permissions API of Android SDK and you have to provide methods in all layers of the MVP to show and check permissions, isnt it? Any way to gently solve this?
     
  5. Deleted User

    Deleted User Guest

    Sometimes a consequence of having a layered architecture, is the need for 'pass through' methods. But without seeing your code, I can't really say anything very specific. Can you provide some sample code to illustrate the problems you're having?
     
  6. twopelu

    twopelu Lurker
    Thread Starter

    Yes of course, I don't have the code now at home but I will try to give you a specific example of the problem I'm facing with the MVP:

    LocationManager requires to check location permissions just before calling the method (or supress warning with annotation), so the decision on where to put it in the MVP is not straightforward.

    This code used to be in my Activity and worked fine having the Context and all the SDK Android imports available:

    1. Inside onCreate() method of the Activity I ask for permissions:

    Code (Java):
    1. private void checkPermissions() {
    2.         Log.i(TAG, "ACCESS_FINE_LOCATION check");
    3.         if (ContextCompat.checkSelfPermission(this,
    4.                 Manifest.permission.ACCESS_FINE_LOCATION)
    5.                 != PackageManager.PERMISSION_GRANTED) {
    6.             Log.i(TAG, "ACCESS_FINE_LOCATION request");
    7.             if (ActivityCompat.shouldShowRequestPermissionRationale(this,
    8.                     Manifest.permission.ACCESS_FINE_LOCATION)) {
    9.                 showRequestPermission(REQUEST_CODE_LOCATION);
    10.             } else {
    11.                 ActivityCompat.requestPermissions(this,
    12.                         new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
    13.                         REQUEST_CODE_LOCATION);
    14.             }
    15.         } else {
    16.             Log.i(TAG, "ACCESS_FINE_LOCATION granted");
    17.         }
    18. }
    2. The callback returns the result of the permission check later:

    Code (Java):
    1. @Override
    2.     public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    3.         switch (requestCode) {
    4.             case REQUEST_CODE_LOCATION: {
    5.                 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    6.                     Log.i(TAG, "ACCESS_FINE_LOCATION granted");
    7.  
    8.                     if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
    9.                         if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    10.                             Log.i(TAG, "GPS provider enabled");
    11.                         } else {
    12.                             Log.i(TAG, "GPS provider disabled");
    13.                         }
    14.  
    15.                         Log.i(TAG, "Listening to location updates...");
    16.                         locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
    17.                     }
    18.                 } else {
    19.                     Log.i(TAG, "ACCESS_FINE_LOCATION denied");
    20.                 }
    21.                 return;
    22.             }
    23.         }
    24.     }
    When triying to deocuple things with MVP architecture I decided leaving the permissions-related code in the Activity and moving LocationManager to the Model (is that even a good decision? what other choices are?):

    Code (Java):
    1. if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
    2.            Log.i(TAG, "Listening to location updates...");
    3.            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DISTANCE, locationListener);
    4. }
    To avoid checking permissions in the Model I have to: 1) provide a pass-through methods in the Presenter so that the View can call the requestLocation() of the Model when the permission is granted and 2) either supress warnings (Annotation) or wrap with a try-catch in the requestLocation() call in the Model to avoid compilation error.

    I have considered aadding pass-through methods to check permissions, moving permissions and LocationManager to the Presenter, encapsulate LocationManager with a Helper class and some others options, but none of them feel good to me. It ends up being everything coupled with Android SDK and / or with dirty interfaces for the VMP layers.

    Code (Java):
    1. try {
    2.            Log.i(TAG, "Listening to location updates...");
    3.            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DISTANCE, locationListener);
    4. } catch (SecurityException se) {
    5.            se.printStackTrace();
    6. }
    The decision on where to put the permissions-realated code, how to manage permissions in Presenter and Model and where to put the calls to Android SDK services or managers seems to be a bit arbitrary depending on which article / post you read. Also, some of them say that no Android SDK code or imports can be placed in Presenter or Model in the benefit of testability (or purity), but I find that the result is lots of boilerplate and pass-through methods.

    To be honest, I have not been able to find two articles / posts that are consistent with the approach on how to handle these things in MVP and none of them cover the problem in detail ("it depends"). The Android Developers page does not give any guidance on this either... :-(

    P.S. Thanks for your help and apologies for the long post! ;-)
     
  7. twopelu

    twopelu Lurker
    Thread Starter

  8. Deleted User

    Deleted User Guest

    I'm not really surprised you haven't found much guidance on this, because I've looked for exactly the kind of information you require, and found it lacking. Basically, this isn't an exact science, and there are a multitude of different ways you can structure your code.
    Rather than get hung up on patterns - and honestly, if you're tying yourself in knots trying to massage the code into a prescribed architectural pattern, then that leads me to question if it's the right approach.
    I tend to apply some basic principles when I'm trying to come up with a software architecture:

    - I try to write my code in such a way that it makes testing easy. Testing is a much neglected part of software development, and quite often it's not done properly.
    - Program to the interface. Interfaces are a great way of decoupling your classes, and providing lots of flexibility in your design.
    - Keep things cohesive. That means not mixing a lot of different functionality in the same class. If a class is called DBHelper, then it should only be concerned with database stuff.
    - Aim for loose coupling - that is all about reducing the dependencies between classes. There's a great pattern that can help you with this, it's called 'Dependency Injection'.

    But really, Android apps are heavily UI based, so a lot time your code revolves around Activities, and responding to user input. With the apps I've built, I didn't really feel the need to construct a complicated architecture.

    When you say you moved the LocationManager to the 'model', what do you mean by that? What constitutes the 'model' in your application?
    Maybe if you placed your code in a Github repo we could get some more context around the code fragments you've presented. Because it's a little difficult to visualise the full picture.

    Note: I just saw your most recent post while writing this response. I'll have a look at the article.
     
    twopelu likes this.
  9. twopelu

    twopelu Lurker
    Thread Starter

    Thanks again! Yes, I will try to share the code tomorrow so you can see the whole thing.

    And many thanks for your useful advice also, I totally agree, I think I should be more pragmatic and less purist with this hehe.

    I have a background (+10 years) in Java with similar architecture patterns, in those cases a simple MVC with DI fits perfectly.

    But in this case with Android it all feels a bit akward hehe :-S
     
  10. Deleted User

    Deleted User Guest

    I think some applications fit so naturally with MVC. Web applications in particular were made for that pattern, no question about it.
    But do put your code up on Github, and if I get some time, I'll look over it.
     
  11. twopelu

    twopelu Lurker
    Thread Starter

    The Model in my app is only a class that stores some values in memory, such as the current location and a list of alerts, and encapsulates the calls to LocationManager. Here is where the coupling with Android SDK ocurrs. The Model has a reference to the Presenter to notify changes in data that have to be represented on the View (in my case, the Activity).
     
  12. Deleted User

    Deleted User Guest

    Ah right, I see what you mean. Yes I sometimes found myself passing around references to a Context (Activity) in another class, so it could update the UI. I was never totally comfortable with that approach, but I just lived with it, as I couldn't really see a cleaner way of doing it.
     
    twopelu likes this.
  13. twopelu

    twopelu Lurker
    Thread Starter

Loading...
Similar Threads - Where should LocationManager
  1. MoodyBlues
    Replies:
    7
    Views:
    548
  2. cwr64
    Replies:
    2
    Views:
    214
  3. startac4
    Replies:
    14
    Views:
    530
  4. connor99z
    Replies:
    5
    Views:
    517
  5. spman
    Replies:
    5
    Views:
    527
  6. LibbyChai
    Replies:
    1
    Views:
    400
  7. Tdjohnson7700
    Replies:
    22
    Views:
    4,896
  8. Devaraj Sandberg
    Replies:
    2
    Views:
    387
  9. kobi_d
    Replies:
    8
    Views:
    1,541
  10. Ghulam Mujtaba Jatoi
    Replies:
    0
    Views:
    4,227

Share This Page

Loading...