How to pass Activity to the ViewModel? - java

I have a method, that request permission from user. I placed it in the ViewModel to make it in background, but in order to run it, I have to pass the Activity to the shouldShowRequestPermissionRationale method. How I may do it?

Putting code in ViewModel that somehow requires an android context is not a good idea. The purpose of ViewModel is too separate itself from all the android components. If you will try to force your way by passing activity's context in your viewModel to somehow make it work, then you will leak context if you are not careful.
A good solution would be to realize which code should relies in Activity and which should go in a viewModel. If we are talking about granting permissions, that sounds like something that should definitely reside in the Activity class, as an Activity has API to deal with requesting for permissions and managing the response from the users, i.e. either permission is denied or not.

Related

Best practice to persist android "home"/"main" activity?

I have an android app with one "home" or "main" activity that relies on fragments to accomplish several tasks. This data relies on information retrieved from a server (mine, and presumably a substantial amount by google maps).
I would like to structure my code such that several other activities (ie. preferences) can temporarily take focus before returning to the main activity.
Currently android destroys and recreates the main activity, which means bandwidth is wasted every time.
There are several notable intent flags which 'solve' this problem (Intent.FLAG_ACTIVITY_REORDER_TO_FRONT and Intent.FLAG_ACTIVITY_CLEAR_TOP), however they only appear to be useful when transitioning back to the main activity, which means I have to #override the system behaviour for both onKeyDown() and onBackPressed(). I would really prefer not to do this in case it causes other issues or eventually becomes deprecated.
Is this safe? Or is the better solution to force my application to create a serialization (savedInstanceState) of the main activity and all fragments anytime another activity temporarily takes the foreground?
Using saved instance state is the proper approach here. That will let you persist the information retrieved from the server when the activity gets re-created.
You only need to implement code to save / restore the instance state in the fragment or activity that holds the data. If you want to share that data across all your fragments, you can place it in the activity and add code to save the instance state of the activity. Then you can access the data that's stored in the activity from your fragments with ((MainActivity)getActivity()).getData().
For code to save and restore instance state, take a look at:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html#SaveState
http://developer.android.com/training/basics/activity-lifecycle/recreating.html#RestoreState
If the data you need to persist is really large, you can use a retained fragment instead, as explained here:
http://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject
Another trick for large data objects is to use a singleton class to store the data while the orientation change takes place.

access sharedpreferences in class without passing context

I have a SyncAdapter overloading onPerformSync. In that method, I'd like to access sharedpreferences to get and put settings. As I understand it, for that I need access to a context. The SyncAdapter onPerformSync has a bundle argument, and maybe I could send the context that way.
In a similar problem, I have another base class (not a service or activity) for which I'm also interested in using sharedPreferences. For this, I would either need to pass the context to a method in the class, or instantiate it with the context that is then saved as a private member.
In both of these cases, I understand that keeping and using a context beyond the lifecycle of the activity or service associated with the context can lead to memory leaks.
In my case, my application can begin with either a broadcastreceiver or the main activity. The broadcast receiver starts a background process, and the main activity just starts the main activity. Whichever opens first registers periodic SyncAdapter updates and opens the other class. So if I were to pass the context of the calling activity or service, what happens if either one of them then closes? The SyncAdapter or base class would use an outdated context, and...memory leak? Or would the context revert to whatever remains running?
I also saw the solution to this: (Static way to get 'Context' on Android?), but would that fix anything? I'd then have an activity context, an application context, and a service context. Same problem right? The SyncAdapter may end up holding on to a context that has closed, no?
Based on the first answer here (SharedPreferences application context vs activity context) I'm tempted to go with the application singleton listed in the previous link, but I want to make sure. Thanks
I think what you want to do is to create a Service to manage the SyncAdapter like mentioned here. That way, the Context passed to the Service should be valid while the SyncAdapter is running.
The link shows that you would pass Service.getApplicationContext() to the SyncAdapter constructor. Then you could store that Context as a field in the SyncAdapter and use it when you need to. That Context should be valid for as long as you need it.
When the app and / or the SyncAdapter get GC'd, they should build a new SyncAdapter with a new Context the next time you need it.

Creating GoogleApiClient for multiple activities

I am developing an android app with Google+ API. I am having multiple activities which each require one instance of GoogleApiClient.
As I understand from this post it is possible to call the same instance of GoogleApiClient for each activity. My question is how do we create copies of the GoogleApiClient specifically?
Do we build one again with the .addApi(), .addscope() and implement onConnected method and OnConnectedFailedListener method again? Because it seems repetitive and inefficient. And wouldn't implementing these methods override the same methods from other activities too?
It's not expensive to create multiple instances of GoogleApiClient. In fact it will help with efficiency if you use more than just one API. Only the services you specifically request will be spooled up. So if one activity uses Plus and another uses Drive, the Plus service doesn't have to be spooled up when you're on the Drive activity.
To be clear, it is recommended that you create a separate instance of GoogleApiClient for each Activity, Fragment, Loader, Service, or Application that you create (maybe even some others that I forgot too).
If you really don't want to do that, use the application context instead of an activity or fragment to create the GoogleApiClient and hold a reference to it in an Application object.
I have just had this same dilema. To get round this I used the BaseGameUtil... not sure if your using that but if you are then it is simple you can just have each activity extend the BaseGameActivity, add the required methods and then create a GoogleApiClient obj and getApiClient which will then give you the means to use the GoogleApiClient in your second activity.
mGoogleApiClient = getApiClient();
If your not using the BaseGameUtil then i think you would have to create it like you do above which is a pain, at least the basegameutil does it for you, plus you can always change whats in the BGU as they are more examples than libraries.
Hope this helps.

Android: Creating a class which handles all Bluetooth related operations

I am trying to write an Android application which uses Bluetooth but ran into some problems. I succeeded in getting things working by following the guide on Android Developers portal. But i want to organize my code a bit and move everything related to Bluetooth to a separate class/src file. I run into a problem already when trying to turn on Bluetooth. As per above mentioned guide this is done with:
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
However my class is not an activity and startActivityForResult is not defined. I can pass my main activity's context to my Bluetooth class and call startActivityForResult on that. This works. But result is then returned to my main activity and again I have to write code into it, instead of my Bluetooth dedicated class.
Alternatively I can make my Bluetooth class extend the Activity class. But then startActivityForResult returns a nullPointer exception (I take it because my "Activity" is not initialized).
I am completely new in Android app development so I am hoping for some pointers about what to look at to help me solve my problem. I would really like to have everything related to Bluetooth in one class/src file so that I can reuse it in any future apps.
All ideas in how to achieve that will be greatly appreciated.
Thank you.
Composition, not inheritance.
Pass the Activity to your BluetoothGodClass as a contructor, store it in an instance variable, and use that to call the respective method. BUT.
What do you really need to do? Does the UI need to control bluetooth? Create a method turnOnBluetooth(Activity activity) and use that. Do you really need to receive the specific result of the activity you called? If not, use a Context or a BroadcastReceiver.

What is the difference between the Android constructor and onCreate()?

I'm a little confused by the difference between Java and Android Java. Let's say I have an Activity class AndroidX. There is no main function and there is no AndroidX() constructor as we know it. I realize that onCreate() most probably initializes the AndroidX Activity, but why is there no main? What's the difference?
Consider that your activities are many *main*s and your manifest directs the execution to one of them.
Also consider that the constructor as we know it before is hidden and now it is always called onCreate()
Fair enough to keep going?
This graphic may help some.
http://developer.android.com/images/activity_lifecycle.png
In the Activity documentation they elaborate on what each function is meant for (i.e. onCreate(), onResume(), etc).
http://developer.android.com/reference/android/app/Activity.html
There is no "main" because that assumes that your app is either running or not running. But on android there are many other possible states your app could be in paused, stopped, started, etc...
Check out this link for an excellent overview of the Android Activity lifecycle.
How onCreate works is described in the Activity page of the Android Developer Reference. Specifically here:
onCreate(Bundle) is where you initialize your activity. Most importantly, here you will usually call setContentView(int) with a layout resource defining your UI, and using findViewById(int) to retrieve the widgets in that UI that you need to interact with programmatically.
In a sense you can consider this method the constructor for your Activity, as the initialization is handled there (see the Activity Lifecycle).
As for main, consider it hidden from you. Generally what you do is register listeners for UI elements such as buttons or text fields, then act on input from those UI elements. These listeners handle calls to your methods which might manipulate data or change how the UI displays.

Categories