I have a VOIP
Application, I need to login the application in background on device bootup.
Currently the init to my application is done on UI
Active(onCreate()
).
I have the following things in my mind, can anyone help and clear my doubts.
- The service design is must to achieve this task??
- Which
Service Remote(AIDL)
or Local Service and why?
- How does the
UI
and Service
interaction happens?
- After
UI
is active who gets the Call- Backs? UI
or Service
?
- Should i make
Service
as my Controller
i.e Service
to UI
data Pass Vice-versa?
Sample App: Skype.
So there are many ways to achieve what you want, it is a matter of what fits your style and design better. Hopefully you will find this information useful.
For the application to login in the background on startup there are a few option. The first thing you will need is a BroadcastReceiver which is defined as a receiver in the manifest. Have the BroadcastReceiver catch the ACTION_BOOT_COMPLETED intent. From here you can launch your Service. This leads to #2.
If all you are doing are RESTful calls then really an IntentService would be ideal. The difference between an IntentService and a Service is simple: An IntentService runs off of the main thread, executes it's 'code' and dies. A Service, however runs on the main thread (this is an important fact) and is long running so it has to be told to stopSelf(). To take matters further, a Service is also less likely to be killed compared to an Activity (application components are killed to make room in memory for newly launched apps), ie. it takes higher precedence. The service can also be declared a foreground service which requires a notification but give even higher precedence. I think in your case a Service would be perfect.
Once your UI (Activity) is opened the best way to connect to the Service would be the Binder. This will allow multiple interfaces to the Service from different applications / components if need be. AIDL is pretty cool stuff but from my experience much harder to manage since all parameters must be primitive or Parcables. AIDL is also slower an less efficient because it is really a form of IPC. When a Service is started with an intent the onStartCommand() method is called. If the service is started by an application trying to bind to it then the onBind() method is called. But you can start the Service with and Intent and then bind to it. If you prefer the RESTful approach where you just have quick calls for data you can use an IntentService with a ResultReceiver. This is a great article written about Google I/O examples and just overall well implemented if you are interested in the IntentService and ResultReceiver.
This is up to you. Using the Binder or AIDL your Activity can call the Service methods just like object method where the 'callback' would just be the method return. If you use a ResultReceiver the Activity interfacing the Receiver would be the callback. You could also just pass Intents back and forth but this could get messy. Again for your case the Binder approach would be good as well as a Receiver.
Think of the Service as a model in the MVVM system - use it as a helper to get data from, not as something that controls the logic of the application.
Sorry if this seems messy there are so many ways to achieve what you are looking for. Its just a matter of what fits your situation best what you 'feel' is better. Not to mention the Android SDK is pretty large. I tried to hit on all the topics that could help you out. Good luck!
Try a service with a boot reciever. Here is an example I found after a quick google search. Then make sure to store in the login info somewhere for when the app starts. Not sure what callbacks you might have, so really hard to answer that part. I would say that if the callbacks should affect the UI then let the activity take them over when it starts up. If you need a UI when only the service is running, probably best to throw up a notification and have it call the appropriate activity with the callback data.
you can authanticate user login by background services
package com.javaorigin.android.sample.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
String tag="TestService";
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service created...", Toast.LENGTH_LONG).show();
Log.i(tag, "Service created...");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(tag, "Service started...");
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class SampleAction extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView view = new TextView(this);
view.setText("Service Test");
Intent i = new Intent();
i.setClassName( "com.javaorigin.android.sample.service",
"com.javaorigin.android.sample.service.MyService" );
bindService( i, null, Context.BIND_AUTO_CREATE);
this.startService(i);
setContentView(view);
}
}
If you login is takes so long use [AccountManager][1]
and do it only once.
The idea behind the AccountManager
a token or whatever credentials you need to use in your Service
.
In your particular case I think the best way of communicating your Activity
with the Service
is binding to it.
Best source of knowledge about basic Service
usage is SDK. Long story short AIDL
is used for IPC communications and as long as you run the service in the same process you don't need it. I suppose you have two options:
If the only thing you need is just login, you can start a service on boot up, login and then i.e. send a sticky broadcast with bundled login data which will be then received in application. See this question for a good set of ways to start a service on boot up.
@Override
public void onCreate() {
Data data = performLogin();
Intent i = new Intent(ACTION_VOIP_LOGIN);
i.putExtra(EXTRA_LOGIN_DATA, data);
mContext.sendStickyBroadcast(i);
}
...
private final class LoginReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// You may use a Bundle instead
Data data = intent.getParcelableExtra();
processLoginData(data)
}
}
protected void onCreate(Bundle savedInstanceState) {
...
IntentFilter filter = new IntentFilter(ACTION_VOIP_LOGIN);
mContext.registerReceiver(new LoginReceiver(), filter);
}
In second case you might want to move all your logic to the service. Here you'll extend the Binder
class. See this SDK article for details.