Android service's new thread error: Thread already started - android

There's broadcastReceiver receive boot message and set a alarmmanager.
It start a service every DELAY mins:
Intent intent = new Intent();
intent.setAction("org.jxdwinter.getMessageServcie");
PendingIntent pendingintent = PendingIntent.getService(arg0, 0, intent, 0);
am = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), DELAY, pendingintent);
The service poll data from romate server in a new thread:
public int onStartCommand(Intent intent, int flags, int startId)
{
this.getMessage.start();
return Service.START_NOT_STICKY;
}
private class GetMessage extends Thread
{
public void run()
{
... ....
}
}
And when the app started, I can get the data at very first time and there's no
error.
Then the service start again in DELAY mins , there's an error:Thread already started.
Why is happened? Pls help me with this. Thank you!

Maybe you could just create a new instance of your thread each time you need it to run:
public int onStartCommand(Intent intent, int flags, int startId)
{
new GetMessage().start();
return Service.START_NOT_STICKY;
}

Is instance of GetMesdsage class you are using by any chance static? If yes, do not doe this - initialize new one

Related

Unable to start receiver : Not allowed to start service Intent ; App is in background

So I made an app that upon a button click sets up a repeating task using an Alarm Manager.
In on create:
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
servicePendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
On the button click:
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
firingCal= Calendar.getInstance();
firingCal.setTimeInMillis(System.currentTimeMillis());
firingCal.set(Calendar.HOUR_OF_DAY, 1); // At the hour you want to fire the alarm
firingCal.set(Calendar.MINUTE, 47); // alarm minute
firingCal.set(Calendar.SECOND, 0); // and alarm second
long intendedTime = firingCal.getTimeInMillis();
long interval = 1000 * 60 * 1;
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, intendedTime, interval, servicePendingIntent);
In the AlarmReceiver class:
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, WallpaperService.class);
context.startService(myIntent);
Log.d(TAG,"Am apelat serviciul");
context.stopService(myIntent);
}
And in the WallpaperService class I just make a get request and set an wallpaper.
public class WallpaperService extends Service {
String requestLink="";
boolean requestFinished = false;
public final String TAG = "Service";
public static int SERVICE_ID = 1;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"Wallpaper Service started");
Toast.makeText(WallpaperService.this,"Service started",Toast.LENGTH_LONG);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"In onStartCommand");
taskToBeRepeated();
stopSelf();
return START_STICKY;
}
.....
}
And the behaviour is that when I start the app and I click the button everything works well the first time the Alarm Manager fires ( With the app in the background). The second time the receiver gets triggered I get the error in the tile. To be more specific :
java.lang.RuntimeException: Unable to start receiver com.example.dailywallpaper.AlarmReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.dailywallpaper/.WallpaperService }: app is in background uid UidRecord{3e313bf u0a357 RCVR bg:+1m21s273ms idle change:uncached procs:1 seq(0,0,0)}
What seems to be the problem ? And why is working the first time and then it gives the error? How can I fix it ?
you need to read android official documentation about the policy of using background service or alarms in android 8 and above and adapt your app with this limitations.
I suggest you to read this two articles very carefully :
https://developer.android.com/guide/components/services
https://developer.android.com/about/versions/oreo/background

ContentObserver registered in service is killed when app killed

I need to be able to detect when changes occur in contact data (any type of change to any contact in the address book).
I am using this ContentObserver:
public class ContactsContentObserver extends ContentObserver {
private Context context;
private Handler toastMessageHandler;
public ContactsContentObserver(Handler handler, Context ctx) {
super(handler);
context = ctx;
}
#Override
public void onChange(boolean selfChange) {
this.onChange(selfChange,null);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
// Change Detected! Do something.
}
}
I register this observer in a service like this:
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
registerContactsContentObserver();
return START_STICKY;
}
private void registerContactsContentObserver(){
ContactsContentObserver myObserver = new ContactsContentObserver(new Handler(), this);
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, myObserver);
}
I start this service in my main activity.
It works fine as long as the activity is open (even if in the background), and the onChange() method is called every time I change any contact data.
But it doesn't work at all if I manually close the app by clearing it from recent apps in android
Am I doing something wrong? Isn't the service supposed to run even when the app is closed?
I've been able to solve the issue with the help of pskink
Starting the service in the forground like this:
private void runAsForeground(){
Intent notificationIntent = new Intent(this, LauncherActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, PendingIntent.FLAG_ONE_SHOT);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("test")
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
}
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
runAsForeground();
registerContactsContentObserver();
return START_STICKY;
}
solved the issue.
Although, I still don't understand why the issue occurred in the first place, since, the service is sticky and supposed to run even if the app is closed. Even if android stopped the service to save memory, it is supposed to restart it.
Can somebody explain to me why starting the service in the foreground is any different than a regular sticky service in the background?

Timer inside Android service

I have an Android service that starts a timer that does stuff:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
timer.scheduleAtFixedRate(new VeryImportantTask(), 0, RATE);
return START_STICKY;
}
I know Services are singleton but, does onStartCommand method called each time that I call startService()? If so, I should control that my timer is just started the first time, shouldn't I? I'm thinking in a static boolean flag in the service. Is there a better way?
In your case i.e START_STICKY you can simply check the intent value nullity
like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(null==intent){
// service restarted do what you want
}
return START_STICKY;
}
because first time the intent will not be null and it will be null every time in case of a restart with START_STICKY.

Android: Ping server in every 10 minutes

I need to ping server(api call) in every 10 mins, api call should be working if my application runs in background. Please suggest me the better option.
Right now I used Service, but it get finish after some time if my application is in background(due to GC clear).
How to avoid GC clear if application runs in background. Please help me.
If you want to restart your service automatically after being killed, set the service sticky.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
You can use Handler for that. A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
Example :
private final static int TIMEINTERVAL = 600000; //10 minutes
Handler mHandler;
Runnable mHandlerTask = new Runnable()
{
#Override
public void run() {
// call your api here.
ApiCall();
mHandler.postDelayed(mHandlerTask, TIMEINTERVAL);
}
};
private void startTask(){
//run your Task
mHandlerTask.run();
}
private void stopTask()
{
// stop your Task
mHandler.removeCallbacks(mHandlerTask);
}
You can also use AlarmManager and set a repeating alarm from your Activity which will invoke the receiver every 10 minutes:
AlarmManager alarmManager=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),600000,
pendingIntent);
BroadcastReceiver:
public class Receiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//Call your API
}
}
Registerd Receiver in your Manifest.xml
<receiver
android:name="com.YourPackage.AlarmReceiver"
android:exported="false">

Android service killed immediately after start, despite calling startForeground()

I'm having a problem with my IntentService. Every time I start my service, the onDestroy() method is called as soon as the service becomes idle. I set up my service to run in the foreground, and despite this the service is still being killed right away. I have only one other activity in my application, and it is not calling stopService().
Reading the developer docs gives me the impression that calling startForeground() will allow your service to persist, even when idle, except when there is an very high demand for memory, or am I reading this wrong?
My code below:
public class FileMonitorService extends IntentService {
public int mNotifyId = 273;
public FileMonitorService(){
super("FileMonitorService");
}
#Override
protected void onHandleIntent(Intent arg0) {
}
#Override
public void onDestroy() {
Toast.makeText(this, getText(R.string.toast_service_stop), Toast.LENGTH_SHORT).show();
stopForeground(true);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = new Notification(R.drawable.icon, getText(R.string.notification_short), System.currentTimeMillis());
notification.flags|=Notification.FLAG_NO_CLEAR;
Intent notificationIntent = new Intent(this, FileMonitorActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_short),getText(R.string.notification_long), pendingIntent);
startForeground(mNotifyId, notification);
Toast.makeText(this, getText(R.string.toast_service_start), Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}
}
You need to look into using a regular Service instead of an IntentService. IntentService is designed to keep running while it has work to do. Once you've finished your onStartCommand method, it tries to stop.
See the docs:
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.
(Emphasis mine)

Categories

Resources