Should onHandleIntent be called when IntentService is started with bindService? - android

My service extends IntentService and when it is started with startService, onHandleIntent gets called. However, when the service is started with bindService (I do need binding), onHandleIntent does not get called.
Should onHandleIntent be called when IntentService is started with bindService? Is startService the only way IntentService should be started?
The documentation for IntentService says the following:
Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
Currently I solve my problem by calling startService right after bindService but I find it ugly. I would like to know is there a way to make it work with just one call.
Code snippets follow, it might be that I am missing something obvious.
ExampleService.java
public class ExampleService extends IntentService {
private class IncomingHandler extends Handler {
#Override
public void handleMessage(Message message) {
if (message.replyTo != null) {
outMessenger = message.replyTo;
}
}
}
private Messenger messenger = new Messenger(new IncomingHandler());
private Messenger outMessenger = null;
public ExampleService() {
super("ExampleService");
}
#Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
#Override
protected void onHandleIntent(Intent arg0) {
System.out.println("Service started");
for (int i = 0; i < 5; i++) {
SystemClock.sleep(5000);
if (outMessenger != null) {
try {
outMessenger.send(Message.obtain());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Service Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.service"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="3"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ExampleService">
<intent-filter>
<action android:name="com.example.service.ExampleService" />
</intent-filter>
</service>
</application>
</manifest>
MainActivity.java (caller)
public class MainActivity extends Activity implements ServiceConnection {
private class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "Message received", Toast.LENGTH_SHORT).show();
System.out.println("Message received!");
super.handleMessage(msg);
}
}
private Messenger messenger = new Messenger(new IncomingHandler());
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent("com.example.service.ExampleService");
bindService(intent, MainActivity.this, Context.BIND_AUTO_CREATE);
//startService(intent);
}
});
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Message message = Message.obtain();
message.replyTo = messenger;
try {
new Messenger(binder).send(message);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}

Should onHandleIntent be called when IntentService is started with bindService?
No.
Is startService the only way IntentService should be started?
IMHO, yes. IMHO, IntentService is not designed for the binding pattern.
In your case, you can:
Pass a Messenger from the activity in an Intent extra in the command sent by startService(), or
Use LocalBroadcastManager, or
Use Otto, or
Use an ordered broadcast, if the IntentService might continue past the activity's life and you want to, say, display a Notification when the work gets done in that case,
Etc.

You must call both startService and bindService.
This was worked for me.

Related

Service - the service isn't stopping

I'm having some problems with services.
Service:
public class MyService extends Service {
public MyService() {
}
private static final String TAG = "AutoService";
private Timer timer;
private TimerTask task;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Auto Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
int delay = 5000; // delay for 5 sec.
int period = 5000; // repeat every sec.
timer = new Timer();
timer.scheduleAtFixedRate(task = new TimerTask(){
public void run()
{
System.out.println("done");
}
}, delay, period);
}
#Override
public boolean stopService(Intent name) {
timer.cancel();
task.cancel();
return super.stopService(name);
}
#Override
public void onDestroy(){
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
MainActivity:
public class ClientSocket extends ActionBarActivity {
CheckBox enablecheck;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_socket);
enablecheck = (CheckBox)findViewById(R.id.enablecheck);
enablecheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(enablecheck.isChecked()){
startService(new Intent(ClientSocket.this, MyService.class));
}else
{
stopService(new Intent(ClientSocket.this, MyService.class));
}
}
});
}
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light" >
<activity
android:name=".ClientSocket"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" >
</service>
</application>
I'm just testing, when I try to stop the service, the fuction onDestroy() is called but don't stop the service. The service/android:exported and android:enable both are true.
Any help?
The Timer instance create a background thread. If you want to stop the service completely you also need to stop the thread. Timer has a cancel() method you can call in the onDestroy() method to terminate the Timer.
Also, exporting the service means other applications (processes) can access it. You most likely don't need that.
The issue in the code is a misunderstanding of what
#Override
public boolean stopService(Intent name) {
timer.cancel();
task.cancel();
return super.stopService(name);
}
really does.
It is not a callback that is called when the service is stopped. Instead it is overriding the stopService method on Context, which you call to stop a service (as you do in the Activity in your example).
In fact the override of stopServicein your code has no effect at all.
timer.cancel();
task.cancel();
should be placed in the onDestroy method of your service.

Broadcast Receiver Registration

I am new to android.
My project is having one activity and one service. My service is having one broadcast receiver and activity is having broadcast sender which is in PeriodSender method .Dynamically when i am registering the receiver then at the start of the service it is not invoking but if i send some thing after few moment then it invokes.
But I want to register it in Manifest ,I have included the receiver details in Manifest but the receiver is not invoking . My receiver class name is MyReceiver21 and the intent action is MY_ACTION1. actually I want my broadcast receiver to be registered at the starting it self.
Following is my Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.experiment.Test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="3"
android:targetSdkVersion="3" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.experiment.Test.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver21" >
<intent-filter>
<action android:name="com.experiment.Test.MainActivity.MY_ACTION1" />
</intent-filter>
</receiver>
<service
android:name="Myservice21"
android:enabled="true" />
</application>
</manifest>
my activity code is
public class MainActivity extends Activity {
MediaPlayer OurSong;
Context SavedThis=this;
int i=0;
public Handler handler1 = new Handler();
public Handler handler2= new Handler();
Button Start;
Button Stop;
Button Button21;
Button StopButton;
public int GProgreess=0;
int Rc=0;
int BitCount=0;
int SeekPos=0;
int Period=500;
MyReceiver myReceiver;
final static String MY_ACTION1 = "MY_ACTION1";
public int Data=0;
public int beat=0;
int BreakVar=0;
Thread myThread ;
static public TextView text1,text2,text3,text4;
private SeekBar bar;
private TextView textProgress,textAction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StopButton=(Button)findViewById(R.id.buttonstop);
StopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopService(new Intent(SavedThis,Myservice21.class));
BitCount=0;
}/****End of on clk******/
});/*****End of set on clk listener*****/
Button21.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
Rc=0;
BitCount=13;
stopService(new Intent(SavedThis,Myservice25.class));
SystemClock.sleep(200);
startService(new Intent(SavedThis,Myservice21.class));
PeriodSender();
}/****End of on clk******/
});/*****End of set on clk listener*****/
}
public void PeriodSender()
{
Intent intent1 = new Intent();
intent1.setAction("MY_ACTION1");
intent1.putExtra("kz", Period);
sendBroadcast(intent1);
text3.setText(""+Period);
Toast.makeText(getApplicationContext(), "PeriodSent",Toast.LENGTH_SHORT).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
my service class
public class Myservice21 extends Service {
int BitCount=0;
int Rc=0;
int Period=500;
Intent intent = new Intent();
MyReceiver21 myReceiver21;
public Handler handler1 = new Handler();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public void onCreate()
{
intent.setAction(MY_ACTION);
myReceiver21 = new MyReceiver21();
IntentFilter intentFilter1 = new IntentFilter();
intentFilter1.addAction(com.experiment.Test.MainActivity.MY_ACTION1);
registerReceiver(myReceiver21, intentFilter1);
Intent intent1 = new Intent(Myservice21.this,MainActivity.class);
startService(intent1);
handler1.post(runnable1);
}
public class MyReceiver21 extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
int data = intent.getIntExtra("kz", 0);
Period=data;
Toast.makeText(getApplicationContext(), "PeriodRceived21",Toast.LENGTH_SHORT).show();
}
}
public void onStart(Intent intent,int StartId)
{
Rc=0;
}
public void onDestroy()
{
}
}
can any one help me to register the receiver in manifest. Thanks in advance
You don't have to add the intent filter for your own broadcasts. Just register the service for that broadcasts with registerReceiver() when the service is started.
Note, that you have to start the service manually when your App starts, for instance in the MainActivity.onCreate():
startService(new Intent(this, Myservice21.class));
When the MainActivity has been created, it will start the service, which itself registers for BroadcastIntents and starts listening for them. This should work.

Can't call a Bluetooth BroadcastReceiver method in a Service

I have this Service class:
public class BluetoothService extends Service {
private static Activity mActivity;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
this.registerReceiver(bluetoothReceiver, intentFilter);
}
#Override
public void onDestroy() {
if (bluetoothReceiver != null) {
this.unregisterReceiver(bluetoothReceiver);
}
}
#Override
public void onStart(Intent intent, int startid) {
//
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public static BroadcastReceiver bluetoothReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
TextView tvStatus = (TextView) mActivity.findViewById(R.id.tvtatus);
Messaging.appendMessage(tvStatus, Bluetooth.getDeviceState(state));
if (Bluetooth.isBluetoothEnabled()) {
Messaging.appendMessage(tvStatus, Bluetooth.showMessage());
}
}
}
};
}
And in my Activity class, I have this:
public class MainActivity extends Activity {
private TextView tvStatus;
private Intent intentBluetooth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvStatus = (TextView)findViewById(R.id.tvtatus);
intentBluetooth = new Intent(this, BluetoothService.class);
startService(intentBluetooth);
}
}
The BroadcastReceiver method (bluetoothReceiver) in the Service class is never called. I don't know why. If I have the IntentFilter and the BroadcastReceiver codes above all in an Activity, then it works - but not in a [separate] Service. I'm stumped.
My AndroidManifest.xml is:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.onegoal.androidexample"
android:versionCode="1"
android:versionName="1.0.0"
android:installLocation="auto"
android:hardwareAccelerated="true">
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:debuggable="true" >
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BluetoothService">
</service>
</application>
</manifest>
I'm new to Android so what I'm doing may not be the best. Hope someone can help me.
maybe the fact that your receiver is static causing the problem.
BroadcastReceiver should never be static. it can cause lots of problems.
other really bad design problem with your code - holding reference to activity inside service, and using it to modify views is really wrong thing to do. it can cause easily to memory leek.
the right why to communicate between Service and Activity is by implement android's Messanger, or sending broadcasts between them via BroadcastReceiver.
if you'll listen to my advice - you won't be have to make your receiver static (I guess you've made it static only because you are using the mActivity static instance inside)
and I'm pretty sure it will solve your problem
you can read about Messanger here: http://developer.android.com/reference/android/os/Messenger.html
sure you'll find lots of usage examples in the net.
example of broadcasting updates to the activity from service:
public class MyService extends Service {
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
this.registerReceiver(bluetoothReceiver, intentFilter);
}
#Override
public void onDestroy() {
if (bluetoothReceiver != null) {
this.unregisterReceiver(bluetoothReceiver);
}
super.onDestroy();
}
public BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
updateUIWithNewState(state);
}
}
};
protected void updateUIWithNewState(int state) {
Intent intent = new Intent("serviceUpdateReceivedAction");
intent.putExtra("state", state);
sendBroadcast(intent);
}
}
and that's the activity:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mServiceUpdatesReceiver, new IntentFilter("serviceUpdateReceivedAction"));
}
#Override
protected void onPause() {
unregisterReceiver(mServiceUpdatesReceiver);
super.onPause();
}
private BroadcastReceiver mServiceUpdatesReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra("state", -1);
// do what ever you want in the UI according to the state
}
};
}

Service wont start / bind to variable?

I'm trying to start a service on android in order to performe some network-related tasks in background. I have written a basic network-manager for my app, which is a service. I basically used the tutorial from the android documentation. The basic structure goes as following:
public class MyNetworkManager extends Service {
// some code
private final IBinder mBinder = (IBinder) new MyBinder();
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyBinder extends Binder {
MyNetworkManager getService() {
return MyNetworkManager.this;
}
}
public void onCreate() {
// some network related stuff like setting up sockets etc.
}
public void onStart(Intent intent, int startid) {
while(true) {
// receive new connections etc
}
}
The calling app/activity is then:
public class AndroidNetworkManagerClient extends Activity {
private Button buttonSend;
private EditText inputText;
private TextView outputText;
private MyNetworkManager networkManager;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
networkManager = ((MyNetworkManager.MyBinder) binder).getService();
}
public void onServiceDisconnected(ComponentName className) {
networkManager = null;
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
inputText = (EditText) findViewById(R.id.textInput);
outputText = (TextView) findViewById(R.id.textOutput);
buttonSend = (Button)this.findViewById(R.id.buttonSend);
buttonSend.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (inputText.getText().length() != 0) {
outputText.append("Out: " + inputText.getText() + "\n");
networkManager.sendData("localhost", inputText.getText().toString());
}
}
});
bindService(new Intent(this, MyNetworkManager.class), mConnection, Context.BIND_AUTO_CREATE);
doSomeAppRelatedStuff();
}
bindService() seems to be called without any problems, but the variable "networkManager" is always null! I already tried to debug into the onCreate() method or onServiceConnected() but it seems, that these parts are not reached at all (at least no breakpoint was triggered).
The service is already registered in the AndroidManifest.xml:
package="some.random.name"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".AndroidNetworkManagerClient"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyNetworkManager"></service>
</application>
Anyone an idea?
Chances are, your Activity is getting into doSomeAppRelatedStuff() and trying to use networkManager before the binding is complete.
If doSomeAppRelatedStuff() absolutely must have the network manager to function, move your call to doSomeAppRelatedStuff() into onServiceConnected() so it won't actually start until the binding is complete. Note that if you do that, your onStart() and onResume() calls will probably (but not guaranteed!) happen before the binding is complete, so program accordingly.

How to start an application in android when mobile is switched ON?

Hai i have a application using background service.its running clearly.If my mobile is switch off,my service is ound service off.when my application is started then only my background service is strated .i want to restart the service again when mobile switch off?
is it possible?
Anybody explain with code
update
public class loginForm extends Activity
{
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (R.layout.login);
receiver = new ConnectionReceiver();
registerReceiver(receiver,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
}
private class ConnectionReceiver extends BroadcastReceiver{
private Timer mTimer;
private TimerTask mTimerTask;
#Override
public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra (ConnectivityManager.EXTRA_NETWORK_INFO);
if(null != info)
{
String state = getNetworkStateString(info.getState());
if(state.equals("Connected")){
mTimer = new Timer();
mTimerTask = new TimerTask() {
#Override
public void run() {
loginForm.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//Toast.makeText(getBaseContext(), "Disenabled provider " + provider,
///Toast.LENGTH_SHORT).show();
try{
insertAllGpsInformation();
}
catch(Exception e)
{
Toast.makeText(getBaseContext(), "Your Net Connected or Not Login to Net"+"", Toast.LENGTH_LONG).show();
Log.e("Upload Picture Error:",e.getMessage());
}
}
});
}
};
mTimer.scheduleAtFixedRate(mTimerTask,180000,180000);
}
}
}
}
}
Register for the ACTION_BOOT_COMPLETED (see here for details). Start your service on boot.
You should register a BroadcastReceiver and look for the BOOT_COMPLETED Intent.
Here is link with some details: http://androidgps.blogspot.com/2008/09/starting-android-service-at-boot-time.html
Did I understand your question correctly?
create Broadcast Receiver that with the Intent of BOOT COMPLETED Action.
please refer following links for more help :
http://blog.gregfiumara.com/?p=82
http://marakana.com/forums/android/examples/60.html
You can use
public class BootReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
Log.i("BootReceiver :: Start Booting..");
Intent i = new Intent(context, StartService.class); // Start your service class
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
and use the broadcastreciever in androidmanifest.xml as
<receiver android:name=".receiver.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

Categories

Resources