How to start Service before BroadcastReceiver gets trigged in Android? - java

I have a BroadcastReceiver class which gets trigged sometimes And I also have a Service class. My Service class starts from my Application class named G.class. I want my Service class to start before BroadcastReceiver class. but as I see in LogCat, First G.class starts and it ends then BroadcastReceiver class starts and it ends then Service class starts. What is the problem?
AlarmReceiver.class
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Intent;
import com.hadi.android.dm.app.Logger;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Logger.i("receiver started");
//do something
}
}
G.class
import android.content.Intent;
public class G extends Application {
#Override
public void onCreate() {
super.onCreate();
Logger.i("G started");
startService(new Intent(getApplicationContext(), ApplicationService.class));
Logger.i("G ended");
}
ApplicationService.class
import android.app.Service;
import android.content.Context;
import android.content.Intent;
public class ApplicationService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.i("service started");
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Logger.i("service ended");
}
}
How my BroadcastReciever gets trigged
public void schedule(long time) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 2, new Intent(context, AlarmReceiver.class), 0);
android.app.AlarmManager alarmManager = (android.app.AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent);
} else {
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
}
My LogCat
07-09 00:44:00.797 18172-18172/com.hadi.android.dm I/MYAPP: G started
07-09 00:44:00.886 18172-18172/com.hadi.android.dm I/MYAPP: G ended
07-09 00:44:00.888 18172-18172/com.hadi.android.dm I/MYAPP: receiver started
07-09 00:44:00.890 18172-18172/com.hadi.android.dm I/MYAPP: service started

There's no way to do this. Here's what's happening:
The alarm goes off
The app, which is not running, is started. The received broadcast is noted and an actuon to call the receiver put in the Handler on the main thread.
The app creates the Application class. This calls startService, which adds an action to create the service to the Handler on the main thread.
The main thread message loop is returned to. It takes the next message on the queue, the BR message, and runs it, starting the BroadcastReceiver.
The main thread message loop is returned to. It takes the next message on the queue, the SS message, and runs it, starting the Service.
There is no way to change the ordering in any of this.

Related

After open my app from service can not setText to EditText

In my MainActivity XML file, I have an EditText which id is editsearch. I have a service class for listening to the clipboard text and open my app. Everything is happening fine but I can't set the text to my editsearch when my app opens from service class.
findViewById method is not work in the onStartCommand method of my service. I have also tried defining my editsearch EditText as a static property in my MainActivity class but not getting my expected result.
Here is my service class
package com.learn24bd.ad;
import android.app.Service;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class MyServiceReceiver extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MySerivce","Service Started");
final ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
public void onPrimaryClipChanged() {
String copiedText = clipboard.getText().toString();
Log.i("Copied",copiedText);
/* here i want to setText to my editsearch
also tried with static property
MainActivity.editsearch.setText(copiedText);
*/
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
});
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Services aren't suitable for dealing with UI.
Instead, in your case, you should pass the clipboard content for the MainActivity class to handle. For that, pass it as an intent extra:
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("clipboard_text", copiedText)
startActivity(i);
And receive and handle the text in your activity:
String clipboardText = getIntent().getStringExtra("clipboard_text");
Then you can set the text to your EditText:
editText.setText(clipboardText)

Service not run on app closed

The service works normally when is started from the MainActivity however when the application is removed from the recent apps or when activity is closed, the service is restarted instead of continuing from where it left off.
public class ServiceExample extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO: Implement this method
return null;
}
#Override
public void onCreate() {
// TODO: Implement this method
super.onCreate();
//Do Something
}
I need to perform an action in the background but it can not be stopped or restarted when the activity ends. The Service Statement is the best to Use?
Try putting this inside your service class.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
Add below code to service and override onStartCommand and return START_STICKY
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceTask = new Intent(getApplicationContext(),this.getClass());
restartServiceTask.setPackage(getPackageName());
PendingIntent restartPendingIntent = PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT);
AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
myAlarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartPendingIntent
);
super.onTaskRemoved(rootIntent);
}

Android how to run a task when app is in background of phone

I'm trying to create a service for the first time that runs a method from the activity every 15 seconds once a toggle button is checked when app is the background of a phone and so far the tutorials havent been helpful; this is my code so far. Forgive me if I look stupid here, its my first time using a service.
Service Code
package com.example.adrian.trucktracker;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import java.util.Timer;
import java.util.TimerTask;
public class AutoUpdateService extends Service {
Locator locator = new Locator();
Timer myTimer = new Timer();
private class MyTimerTask extends TimerTask
{
#Override
public void run() {
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
locator.TemperatureCatch();
}
}, 1000 );
}
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
MyTimerTask myTimerTask = new MyTimerTask();
myTimer.scheduleAtFixedRate(myTimerTask, 0, 15000);
}
#Override
public void onDestroy() {
super.onDestroy();
myTimer.cancel();
stopSelf();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
My toggle button code
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
{
startService(new Intent(this,AutoUpdateService.class));
}
else
{
stopService(new Intent(this,AutoUpdateService.class));
}
You got it right to use Service. Do not use Timer, since it is extra thread you do not need. What you can do is to use AlarmManager to schedule your service intent to be launched every 15 seconds (interval). This will trigger interval time your service by calling onStartCommand in your service where you can do whatever you need by reading (if need) intent from parameters of onStartCommand.

Trouble keeping Google Cloud Message alive

I am trying to work around the gcm time out issue, there are many threads on this subject, here is one for reference.
A proposed workaround is to broadcast a pair of intents at an interval shorter than the tcp timeout.
My implementation is to create a class that extends the CountDownTimer class and hold an instance of that class in an existing service. This derived class restarts itself when it is finished and the service is marked as STICKY_START, so once started, I would think it should just keep broadcasting the intents every 4 minutes, but for some reason there are gaps, when the counter does not broadcast the intents and I still loose contact with the GCM server.
The two relevant classes are below. Can anyone explain and offer a solution as to why this strategy does not work?
I created a class that extends CounDownTimer that should broadcast the intents every 4 minutes.
public class GcmKeepAlive extends CountDownTimer {
protected CountDownTimer timer;
protected Context mContext;
protected Intent gTalkHeartBeatIntent;
protected Intent mcsHeartBeatIntent;
public GcmKeepAlive(Context context) {
super(4*60* 1000,4*60*1000);
mContext = context;
gTalkHeartBeatIntent = new Intent("com.google.android.intent.action.GTALK_HEARTBEAT");
mcsHeartBeatIntent = new Intent("com.google.android.intent.action.MCS_HEARTBEAT");
System.out.println("stariing heartbeat countdown timer");
this.start();
}
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
System.out.println("sending heart beat to keep gcm alive");
mContext.sendBroadcast(gTalkHeartBeatIntent);
mContext.sendBroadcast(mcsHeartBeatIntent);
this.start();
}
}
here is the service in my app that holds an instance of the GcmKeepAlive class
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class LocationMonitorService extends Service {
private DeviceLocationClient deviceLocationClient;
private GcmKeepAlive gcmKeepAlive;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
System.out.println("creating the LocationMonitorService");
deviceLocationClient = new DeviceLocationClient(this);
gcmKeepAlive = new GcmKeepAlive(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("inside service making request for location updates");
deviceLocationClient.requestLLocationUpdates();
gcmKeepAlive.start();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Here is an example of a gap as seen in logcat.
07-13 14:59:05.583 I/System.out(21651): sending heart beat to keep gcm alive
07-13 15:03:05.640 I/System.out(21651): sending heart beat to keep gcm alive
07-13 15:07:05.776 I/System.out(21651): sending heart beat to keep gcm alive
07-13 15:11:05.922 I/System.out(21651): sending heart beat to keep gcm alive
07-13 15:27:31.994 I/System.out(21651): sending heart beat to keep gcm alive
I actually solved this some time ago, Erik Z's recent comment remained me to post my solution.
I solved this by creating a recurring alarm that triggers a broadcast, which creates and broadcasts the intents. The gaps were caused by the original service being killed and then restarted as a result of the START_STICKY flag.
Here are the various parts (pulled from various files)
This was needed pre-kitkat at the very least, I don't know if it is still needed, I assume it is. I have not turned it off to confirm however.
The alarm manager, intent , and pending intent.
AlarmManager alarmManager = (AlarmManager) Context.getSystemService(Context.ALARM_SERVICE);
Intent gcmKeepAliveIntent = new Intent("com.gmail.npnster.ourlatitude.gcmKeepAlive");
PendingIntent gcmKeepAlivePendingIntent = PendingIntent.getBroadcast(mContext, 0, gcmKeepAliveIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, 4*60*1000, gcmKeepAlivePendingIntent);
The broadcast receiver:
public class GcmKeepAliveBroadcastReceiver extends BroadcastReceiver {
private GcmKeepAlive gcmKeepAlive;
#Override
public void onReceive(Context context, Intent intent) {
MyLog.p(this,"inside gcm keep alive receiver");
gcmKeepAlive = new GcmKeepAlive(context);
gcmKeepAlive.broadcastIntents();
}
}
The keep alive class that sends the keep alive broadcasts.
public class GcmKeepAlive {
protected Context mContext;
protected Intent gTalkHeartBeatIntent;
protected Intent mcsHeartBeatIntent;
public GcmKeepAlive(Context context) {
mContext = context;
gTalkHeartBeatIntent = new Intent(
"com.google.android.intent.action.GTALK_HEARTBEAT");
mcsHeartBeatIntent = new Intent(
"com.google.android.intent.action.MCS_HEARTBEAT");
}
public void broadcastIntents() {
MyLog.p(this,"sending heart beat to keep gcm alive");
mContext.sendBroadcast(gTalkHeartBeatIntent);
mContext.sendBroadcast(mcsHeartBeatIntent);
}
}

Android Alarm Service Not Responding

I took some code from some questions here in SO as well as some other website and I came up with a reasonable solution.
What I am trying to do: I need to shutdown the app after 2 minutes of inactivity. So The idea is to start up the alarm service when our app goes in into 'onPause' and cancel the service when our app goes into 'onResume'.
What I currently Have: Here is the relevant code that is currently running. My issue is that the TimeoutService java file is never being 'onCreated'. Does simply calling AlarmManager.set NOT start up the pending intent?
The Timeout.java File
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class Timeout
{
private static final int REQUEST_ID = 0;
private static final long DEFAULT_TIMEOUT = 2 * 60 * 1000; // 2 minutes
public static final String INTENT_TIMEOUT = "timeoutintent";
public static void start(Context ctx)
{
//long triggerTime = System.currentTimeMillis() + DEFAULT_TIMEOUT;
long triggerTime = System.currentTimeMillis() + (5000);
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, TimeoutService.class);
PendingIntent pi = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, 0);
am.set(AlarmManager.RTC, triggerTime, pi);
}
public static void cancel(Context ctx)
{
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ctx, TimeoutService.class);
PendingIntent pi = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, 0);
am.cancel(pi);
}
}
LockingActivity File. This is used as a superclass to all of my Activities.
import android.app.Activity;
import android.widget.Toast;
public class LockingActivity extends Activity
{
#Override
protected void onPause()
{
super.onPause();
Timeout.start(this);
}
#Override
protected void onResume()
{
super.onResume();
Timeout.cancel(this);
checkShutdown();
}
private void checkShutdown()
{
if ( AppVM.isShutDown() )
{
Toast.makeText(this, "Shuting Down", 1).show();
finish();
}
}
}
I could send over the TimeoutService file as well, but it's just a typical service file. The problem is the TimeoutService class is never being instanced, so I can't imagine the problem would lie in that class.
I think you are complicating things with an alarm. Use a Handler and postdelayed() to set a Runnable in two minutes, all in your main activity. Any user interaction cancels the post and sets a new one for the next two minutes. The runnable needs only yourActivity.finish();
Follow this answer here: Count for 45 seconds, pause for 20 then repeat with different title for an example of a timer and how to remove the callbacks.
Hi Try using PendingIntent.FLAG_CANCEL_CURRENT flag for your Pending Intent.
PendingIntent pi = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent,PendingIntent.FLAG_CANCEL_CURRENT);
Make Alarm manager as RTC_WAKEUP to wake up device if it is going off some where and check.
With this you need to register a broadcast receiver and fire intent with some action when alarm goes off. Set action to same intent you are using for pending intent.
Start your service in your receiver.
Your this broadcast receiver should be able to listen to action fired by this Intent when Alarm goes OFF.
Intent intent = new Intent(SCH_ALARM_ACTION);
intent.setClass(getBaseContext(), SchAlarmReciever.class);
registerReceiver(new SchAlarmReciever(), new IntentFilter(SCH_ALARM_ACTION));
PendingIntent pi = PendingIntent.getBroadcast(getBaseContext(),
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT);

Categories

Resources