Calling an Activity from a Service - android

I have a service class for an alarm service containing the service methods. These methods are called when the alarm service is activated. What I want to do is to call an intent to another class in one of these methods that are called in the service class (when the alarm goes off). All it does is just flag up errors when calling the intent. This only happens in the methods that are called when the alarm service is activated (methods in service class). Is this because the class extends Service and not extends Activity? I'm not sure, any ides?
(Below is my service class, when the intent to another activity is called in the onStart method the app force closes.)
public class MyAlarmService extends Service {
#Override
public void onCreate() {
// TODO Auto-generated method stub
Toast.makeText(this, "MyAlarmService.onCreate()", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG).show();
return null;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "MyAlarmService.onDestroy()", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "MyAlarmService.onStart()", Toast.LENGTH_LONG).show();
//////////////////////////////////////////////////////////////////////////////////
Intent i = new Intent("com.exercise.AndroidAlarmService.HELLO");
startActivity(i);
The intent that is send to open another class, an activity.
**
/////////////////////////////////////////////////////////////////////////////////
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "MyAlarmService.onUnbind()", Toast.LENGTH_LONG).show();
return super.onUnbind(intent);
}
}
One of these errors on the LogCat is:
06-24 01:11:36.857: E/AndroidRuntime(10805): java.lang.RuntimeException: Unable to start service com.exercise.AndroidAlarmService.MyAlarmService#412f23f8 with Intent { flg=0x4 cmp=com.exercise.AndroidAlarmService/.MyAlarmService (has extras) }: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Have you tried what the error log suggests?
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

You can call an Activity using onStart() of your service.....
#Override
public void onStart(Intent intent, int startId) {
...
Log.i("Service", "onStart() is called");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(<Set your package name and class name here>);
startActivity(callIntent);
...
}

You can do it by enabling the flag as suggested by others. The reason why it is prevented by default is because services are prone to automatic restart by system, in the background. If you are starting an activity during onStart of a service, this activity starts irrespective of what the user may be doing. This will be bad user experience. Please bear this caveat in mind and have work around for this scenario.

Related

Auto Logout Users in Android

I've looked at several examples, but I can't figure out what I'm doing wrong.
Auto logout after 15 minutes due to inactivity in android
After looking at that example, I created a LogoutService class that extends Service. Also, do I still have to have an intent that calls my login activity? Something like this:
Intent intent = new Intent(getBaseContext(), LoginActivity.class);
startActivity(intent);
My LogoutService Class
public class LogoutService extends Service {
public static CountDownTimer timer;
private final String TAG="Service";
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
timer = new CountDownTimer(1 * 60 * 1000, 1000) {
public void onTick(long millisUntilFinished) {
//Some code
Log.v(TAG, "Service Started");
}
public void onFinish() {
Log.v(TAG, "Call Logout by Service");
// TODO should I create an Intent
// my Login method here?
stopSelf();
}
};
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
And put this in all my other classes:
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
try {
LogoutService.timer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
LogoutService.timer.cancel();
}
But I keep getting a null pointer exception due to
LogoutService.timer.cancel();
I surrounded it with an if statement that checks if it's null, but then nothing happens, not sure what I should do.
getting a null pointer exception due to LogoutService.timer.cancel();
Because LogoutService extends Service class but not starting it using startService method so onCreate method is not called and timer is null.
Do following :
Start/Stop service using startService and stopService methods
cancel timer in onDestory() of Service.
Add LogoutService class as service in AndroidManifest.xml

Starting service from another service

I'm trying to start a service from another service. But wonder what's going wrong. The code is like
class Service1 extends GCMBaseIntentService {
#Override
protected void onMessage(Context arg0, Intent intent) {
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_LONG).show();
Intent service = new Intent(getApplicationContext(), Service2.class);
startService(service);
}
}
And Service2 is
class Service2 extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_LONG).show();
}
}
I'm getting the Toast "Hello" in Service1 but not getting Toast "Service Started" from Service2
Instead of using getApplicationContext() you should use Service1.this or getBaseContext() . Have you declared your Service2 in the AndroidManifest?

Android Service's method onDestroy called before Bluetooth scanning ends

I have a problem that I start a service with an Intent, in onCreate() method register BroadcastReceiver and then in onDestroy() unregister the BroadcastReceiver. In Method onHandleIntent() I start discovery for bluetooth devices. THe problem is, that I my BroadcastReceiver is destroyed before any device is found so I cant really do anything with the BluetoothDevice.ACTION_FOUND intent. I tried to move startDiscovery() to onCreate() but no results. My code looks like this:
public class BluetoothService extends IntentService{
private BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
private final String SMART_TOKEN_ADDRESS = "F0:E7:7E:5F:63:70";
private final BroadcastReceiver receiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.v("BLUETOOTH","found it!");
}
};
public BluetoothService() {
super("BluetoothService");
// TODO Auto-generated constructor stub
}
#Override
public void onCreate(){
super.onCreate();
Log.v("SERVICE", "Just got created");
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(receiver, filter);
btAdapter.startDiscovery();
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.v("BLUETOOTH", "Discovery just started");
//btAdapter.startDiscovery();
}
#Override
public void onDestroy() {
super.onDestroy();
Log.v("BLUETOOTH","Just got destroyed!");
unregisterReceiver(receiver);
}
}
Log looks like this:
1. Just got created
2. Discovery just started
3. Just got destroyed!
4. Received android.bluetooth.device.action.FOUND
Thanks for help!
T.
This is happening because after handling all the requests, the service is stoped. From documentation: "Stops the service after all start requests have been handled, so you never have to call stopSelf()."
So, you should use wait or other command to tell the worker thread to wait the execution, if you want to use service.
Please, refer to the documentation about services: http://developer.android.com/guide/components/services.html

Start service when device boot completed

I am doing an application in which I want to call a number when that device boot completed. My code is like this:
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("**inside onRecevier");
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.test.app.TestService");
context.startService(serviceIntent);
}
First I created BroadcastReceiver. I registered this receiver in manifest file like this:
<receiver android:name="TestReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
In a receiver I called the below service:
public class TestService extends Service{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
System.out.println("**inside onCreate");
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
Intent call = new Intent(Intent.ACTION_CALL,Uri.parse("tel:+5555"));
startActivity(call);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("**inside onDestroy");
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
System.out.println("**inside onStart");
super.onStart(intent, startId);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
}
}
when I tried to boot a device after booting the application getting force close. How to do this in android??
Thanx in advance
You need to add the NEW_TASK flag before starting an activity from a service:
Intent call = new Intent(Intent.ACTION_CALL,Uri.parse("tel:+5555"));
call.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(call);
This explains:
Note that if this method is being called from outside of an Activity
Context, then the Intent must include the FLAG_ACTIVITY_NEW_TASK
launch flag. This is because, without being started from an existing
Activity, there is no existing task in which to place the new activity
and thus it needs to be placed in its own separate task.
Also, you must hold the permissions:
RECEIVE_BOOT_COMPLETED
CALL_PHONE
And as Waqas mentioned, it would be better for you to start your service from your onReceive like:
Intent serviceIntent = new Intent(context, TestService.class);
context.startService(serviceIntent);
Make sure you've done all that I've stated, and if you continue to have an issue, then it would be helpful if you edit your question and paste the logcat from the force close.
change your onReceive to this
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("**inside onRecevier");
Intent serviceIntent = new Intent(context, TestService.class);
context.startService(serviceIntent);
}
There's a variety of reasons why you'd get a Force Close. The best way to tell which is to look at the log. It should tell you exactly what exception is being thrown, and give you a hint as to how to solve the problem.

Android bind service to own class

I guess I have more like a design issue than a "how to bind a service" issue. What I'm trying to do is to have a service running in a separate process that handles bluetooth communication. Further I have several tabs, within each another activity. The processing and UI events from each activity results in simple commands which have to be passed over bluetooth like "up", "down", "left" or "right". As the results in each tab activity are the same, I don't wnat to connect each with the service, and use the same message handler. So I created my own Handler object and a "connector" object. However I'm not sure how to connect this connector object with my service as it requries a context. Does it make sense to simply pass the application context to my connector object and bind it that way???
I'm open for any suggestions or hints
I'd suggest against using binding in this case. Actually, I'd suggest against binding in most use cases. Try to handle all communication between you Activities and the service running in another thread using intents only.
That means:
Send commands to the service from the activities by the .startActivity() method, passing the details of the actual command in the Intent's extras.
Receive events and result from the service in your activities by dynamically registered BroadcastReceivers. You register a listener in onResume() and unregister it in onPause() in you Activity. The service sends stuff only by broadcasting it (sendBroadcast()).
I prefer this architecture. It's loosely coupled and you can skip the annoying part where you're wondering if every one of your Activities unbinds correctly from you service when they're not using it. Also, you skip the pain of using IPC, which is a huge plus I think.
Here you are, my example .. will make you clear about that LOL
// My MyServiceInterface.aidl
package com.mad.exam;
interface MyServiceInterface{
int getNumber();
}
//MyService
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "Service OnBind()", Toast.LENGTH_LONG).show();
return mBinder;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Destroyed ", Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "Service Started ", Toast.LENGTH_SHORT).show();
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
private final MyServiceInterface.Stub mBinder = new MyServiceInterface.Stub() {
public int getNumber() {
return new Random().nextInt(100);
}
};
}
//My Activity
public class ServiceDemo extends Activity implements OnClickListener {
MyServiceInterface mService;
ServiceConnection mConnection;
Button retreive;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.service);
retreive = (Button) findViewById(R.id.retreive);
retreive.setOnClickListener(this);
mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mService = MyServiceInterface.Stub.asInterface(service);
try {
int i;
i = mService.getNumber();
Toast.makeText(ServiceDemo.this, "The service value is: " + String.valueOf(i),
Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("My Tag", "Clicked");
Button btn = (Button) v;
Intent callService = new Intent(this, MyService.class);
bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Intent callService = new Intent(this, MyService.class);
bindService(callService, mConnection, Context.BIND_AUTO_CREATE);
}
}

Categories

Resources