I am working on an app where I need to bind to a database via IBinder. I planned on putting any framework initialization in my Application subclass since that kind of stuff isn't presentation related and I know that the Application will be instantiated once per app.
public class MyApplication extends MultiDexApplication {
public void onCreate() {
super.onCreate();
// Bind to the db server
Intent intent = new Intent(getBaseContext(), DB.BIND_ADDRESS);
super.bindService(intent,
new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name,
IBinder service) {
DB.start(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
DB.shutdown();
}
},
Context.BIND_AUTO_CREATE
);
}
}
The problem that I run into is that the call back to my ServiceConnection.onServiceConnected() isn't performed until my activity has started and that's a problem since I need the database available for the activity to display the data. I currently see this behavior.
myApplication.onCreate()
myActivity.onCreate()
myActivity.onStart()
serviceConnection.onServiceConnected()
This is a problem since the database isn't yet connected when the onStart() is invoked on my activity.
I would rather not have to move this infrastructure initialization in the activities. So I have two questions.
Is there a way to block the application.onCreate to wait until
the onServiceConnected() has been invoked? This being single
threaded I don't see how.
Is there a way to tell android not to invoke any onStart() on any
activities prior to my application having completed its
initialization such that I have the following startup sequence
This
myApplication.onCreate()
serviceConnection.onServiceConnected()
myActivity.onCreate()
myActivity.onStart()
or
myApplication.onCreate()
myActivity.onCreate()
serviceConnection.onServiceConnected()
myActivity.onStart()
You'll need to rewrite your code to work with the Android framework. There is no way to wait in onCreate- all the code happens on a single thread, it won't even attempt to start your service until onCreate is finished. I suggest you use onResume or onServiceCreated itself to load the data.
There is no way to do like that.The best solution is to show some type of loading dialog until it connected and fetch from the database
Related
I am currently developing an Application for Android. One of the requirements is extensive logging about how the application is used. More specifically there should be logging about when the user closes the app. This logging consists of a server interaction. With respect to that specific requirement I stumbled onto:
Detect Application Exit(1) and Detect application Exit (2)
Both questions have an accepted answer relying on Service#onTaskRemoved(Intent).
In my case however this solution does not seem to work, i.e. AsyncTasks that are started in this method are only occasionally executed. More specifically, the onPreExecute is executed always but the doInBackground is not. I tested this on a Nexus 5 with Android 6 (Marshmallow) installed.
public class SomeService extends Service {
#Override
public IBinder onBind( Intent aIntent ) {
return null;
}
#Override
public void onTaskRemoved(Intent aRootIntent ) {
new DoSomethingTask().executeOnExecutor( Asyntask.THREAD_POOL_EXECUTOR );
}
private static final class DoSomethingTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
Log.e( DoSomethingTask.class.getName(), "This is executed always");
}
#Override
protected Void doInBackground( Void... aParams ) {
Log.e( DoSomethingTask.class.getName(), "This appears to be executed only sometimes... ");
// here an actual call to a Rest API should be made to inform the server that the user has closed the application.
}
#Override
protected void onCancelled( Void result ) {
super.onCancelled( result );
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
#Override
protected void onCancelled() {
super.onCancelled();
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
}
}
Here is an overview of everything I tried in addition to the above code sample:
I have tried various onStartCommand options (START_STICKY, START_NOT_STICKY, etc.) without success.
I have also tried restarting the service in the onTaskRemoved method and then executing the AsyncTask in the onStartCommand.
Starting an IntentService in the onTaskRemoved method (which starts the AsyncTask in its onHandleIntent method) solves the problem neither.
using a BroadcastReceiver in combination with a local broadcast (LocalBroadcastManager#sendBroadcast) does also not work (I double checked that the broadcast receiver is effectively registered as receiver for the sent broadcast).
EDIT:
I have also taken a look at the callbacks in the Application class:
- onTerminate : this method is only invoked in emulated environments and hence useless
- onTrimMemory(int) : this method can be used for detecting when the app goes to the background, but it has no distinct case for when the app exits.
I could keep an activity stack (which would be updated in Activity#onPause(), etc.). But this requires quite a lot of work in every single Activity instead of the above Service approach which only involves interference at a single place.
First of all: in Android you cannot guarantee execution for your requirement. Period. The system is free to gc your classes or kill your process at any time. Also the Android concept does not really have the concept of "closing app" actions the same way websites don't have it. So before you continue reading I urge you to rethink your requirements.
That being said. Here are some tips:
My understanding of Service#onTaskRemoved(Intent) is that it is only executed if you kill the app through task switcher, so I don't know if this is useful to you. In your instance I would keep a activity ref counter in the application object (+1 for every onResume(), -1 for every onPause() of any activity). With this you can check if your user has active UIs. Usually if you pressed back on the last activity that comes as close to the paradigm "closing" an app. Then just start your task at that point from the application object (this will probably be the last to get gc) or if that doesn't work try an unbound service the most uncoupled component you can generate.
Another, very very bad solution is overriding the finalize() method in an object (e.g. your activity). There are only very, very few reasons to use it since it will trigger an additional gc cycle and your code will be run on the main thread, but it is a way to execute code if the object is about to be gc'ed. Therefore it is discouraged to use by the android team, only use it if you have a gun up your head.
I have implemented a simple Android Service that, by default, is deployed within the same process as my app / apk. I want the Service running concurrently with each Activity. To make that happen, in each Activity.onStart() and Activity.onStop() implementation, I have logic that invokes Activity.bindService() and Activity.unbindService(), respectively.
Well, all of this works fine, but it feels awkward. Is there any other way to make sure the Service is continuously running and bound to all Activities without having to re-invoke Activity.bindService() and Activity.unbindService() for each Activity? Should the Service in this case be declared as a stand-alone process?
Also, my Service starts a separate thread, but never stops it. Should my code stop the thread? Is there a chance the thread could be orphaned? Starting / stopping the thread with OnUnbind / OnRebind seems like overkill.
Create a base Activity and call bindService in onStart, unbindService in onStop.
public class BaseActivity extends Activity {
#Override
public void onStart() {
// ...
bindService(intent, serviceConnection, flags);
}
#Override
public void onStop() {
// ....
unbindService(serviceConnection);
}
}
This will make sure every activity that extends base is bound to the service.
When last activity is unbound from the service, it will be stopped. If you want to avoid that, call startService first, and then bind to it. This will prevent service from stopping even if you don't have running activities.
Should the Service in this case be declared as a stand-alone process?
In your case, you don't need a separate process for your service.
Also, my Service starts a separate thread, but never stops it. Should my code stop the thread?
If you want to stop your service, you should stop your thread because thread is a GC root, and all objects accessible from it will remain in memory. So, infinite thread that is not used is a memory leak.
You can implement threading different ways depending on your requirements. You can either implement a regular thread in your Service, or a ThreadPoolExecutor or a Handler. Pick a solution that fits to your needs.
You can start your Service in your custom Application class. This way the service will be started only when your application is started.
For example:
public class MainApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
starService();
}
public void starService() {
Intent i = new Intent(this, YourService.class);
this.startService(i);
}
}
While the other answers ere good, you might want to ask this:
"Does this service needs to keep on running while the application is not, and will not run?"
If so: create as an independant serviceIf not: extend a helper class that implements the bind/unbind and have Activities extend that.
Intro
I am using the library, SQLCipher in my Android project, which allows me to access a pre-encrypted SQLite v3 database from within my application.
The only downside is that there is currently a lot of overhead when creating a new database connection (getReadableDatabase() and getWritableDatabase()calls), due to all the encryption stuff that goes on every time the database is opened. These calls are currently slowing down my application significantly.
What I am trying to achieve
So, I am seeking to minimise the number of times that I needs to make these calls, by holding a single active connection to my database across all of my activities.
How I intend to achieve this
Instantiate connection to database upon application start
For each activity, maintain a special flag
Whenever an activity is switched to another (via an intent), this boolean flag is set true
Each activity's onDestroy() method will close the application's connection to the database, unless that activity's flag is true (i.e., application isn't being destroyed, we are simply moving to a different activity)
An example
public class ExampleActivity extends Activity {
// Used to determine whether we are destroying the activity due to an intent.
private boolean isIntent = false;
public void someMethod() {
isIntent = true;
Intent intent = new Intent(this, SomeOtherActivity.class);
startActivity(intent);
finish();
}
#Override
public void onDestroy() {
super.onDestroy();
if (!isIntent)
// We haven't started another activity, so we should close the open
// database connection.
DatabaseHelper.close();
}
}
Questions
Are there any issues to this approach that I haven't considered? I haven't seen it done before, so I am wary.
Is there a better way of achieving the desired result?
You can create a singleton class around your subclass of the SQLCipher-based SQLiteOpenHelper. Within the SQLiteOpenHelper, calls to getWritableDatabase() internally cache the returned database object, so key derivation is not occurring each time that method is called.
I'm having some problems figuring out how to properly organize a particular bit of android code.
This is the architecture of the code: Inside of an activity's onCreate, addService does some work via bindService, and getServices can be run only once the onServiceConnected methods have successfully completed:
public class MyClass{
List<IBinder> binders = new ArrayList<IBinder>;
int stillSettingUp = 0;
public void addService(Class<?> cls) {
//Adds a binder via bindService
ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
//Callback for service being successfully started
binders.add(service);
stillSettingUp--;
}
};
//Increment count of the number of services being set up
stillSettingUp++;
Intent intent = new Intent(context, cls);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
public List<IBinder> getServices(){
while (stillSettingUp != 0) {
Log.w("", "Waiting for services to successfully connect... " + stillSettingUp);
Thread.sleep(1000);
}
return binders;
}
}
Here is the hitch: the second method requires the onServiceConnected functions to complete. The onServiceConnected functions can't execute until the entire onCreate function completes (since they are events that are tacked onto the end of the main loop, and can't be executed until the current event finished), and so the system deadlocks.
Is there a way to force the other events on the UI thread to process, or a better way to orchestrate the code? I'm trying to avoid running an AsyncTask every time I call these two pieces of code together, as this requires exposing threading requirements to the calling code. This is difficult, however, since you can't force the service connection callbacks to execute in their own thread. Any suggestions are welcome.
It looks like what you need is to execute your 3rd function on the UI thread as soon as both your 1st and 2nd functions have completed. So why not to use AsyncTask and put your 1st and 2nd routines in doInBackground() while putting your 3rd routine in onPostExecute()
Here are my takeaways from my question:
1) If you ever have to depend on data from an Android callback, you should not block, since Android callbacks aren't posted to a separate thread, as in other programming paradigms. You should instead gracefully move past the point where you needed the data, possibly reattempting the data access in e.g., a polling thread.
2) You can also pass in a runnable to be executed after the service is connected. This could get very messy, however.
3) DON'T USE TOO MANY SERVICES. It's typically much easier to just use one or two services than it is to use a bunch of services that talk with one another. I rewrote this set of code, and it's 20x more maintainable now that I'm not dealing with bound services constantly.
I have an application that uses a Service to fetch data in the background both while the application is running and when it's not.
When it is not running i would like to show a notification when there is new data, but not when the app is running.
How do i determine in my service whether the app is running or not?
I think you want to check whether a certain activity is shown. If that is true, I would use the Activity.onCreate() method to set a flag in the application instance, i.e. extend the class Application with a field "uiRunning" and check this field in your service. onDestroy() should be used to unflag the attribute. Don't forget to use your Application class also in the Manifest.xml
I would agree with the use of onCreate()/onDestroy() for a single Activity application, though an Application with multiple activities would be better off using Application.onCreate()/onTerminate() in order to avoid triggering the uiRunning state when switching activities.
This is dead easy. You use a named Mutex.
Put this in the application you want to check:
bool createdNew;
Mutex mutex = new Mutex(true, #"Global\YourAppNameHere", out createdNew);
if (createdNew)
{
var app = new YourProcess();
app.run();
mutex.Close();
}
Put this in the application that checks to make sure the other app is running:
bool createdNew;
Mutex mutex = new Mutex(true, #"Global\YourAppNameHere", out createdNew);
if (createdNew)
{
Console.WriteLine("App not running");
mutex.Close();
} else {
Console.WriteLine("App is running");
}
Another option is to implement a listener pattern and have your service manage a list of listeners with methods on your service interface for addListener() and removeListener(). Your activity can add itself as a listener after it connects to the service and remove itself onStop() (i.e. when the app is no longer visible to the user or has shutdown completely).
In your service, check the count of listeners. If there are no listeners then you know you should create your notification.
Another way to accomplish is to de-couple your data receiver to a 'service' which will always run in the background. you can have your application bind to the service and will display the data fetched by the service.
The problem with having the application in background is that Android will kill the application once it gets too old. Its always better to have such background running application as service rather then activity.
What i did do was to use a flag in my service, that the root activity sets and clears on onStart/onStop. This works pretty well.
This is how I did it and is working flawlessly with just a few lines of code:
In extended App class:
public static boolean isAppInFront = false;
In you main activity:
#Override
public void onStart() {
super.onStart();
MyApplication.isAppInFront = true;
}
#Override
public void onStop() {
super.onStop();
if (isFinishing())
MyApplication.isAppInFront = false;
}