Android Oreo JobIntentServices closes always - android

I already tried a JobService as well, but I get the same result, as with the JobIntentService, namely my Notification gets called after x seconds when the app is running in the foreground, but not after swiping the app in the recent task area.
Here is how I start the JobIntentService from my Fragment:
Intent serviceIntent = new Intent(getActivity(), AlertJob.class);
serviceIntent.putExtra("inputExtra", timeForAlarm);
AlertJob.enqueueWork(getContext(), serviceIntent);
And this is my JobIntentService Class:
public class AlertJob extends JobIntentService {
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, AlertJob.class, 123, work);
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleWork(#NonNull Intent intent)
{
try
{
Thread.sleep(5000);
startService(new Intent(getApplicationContext(), Service_Notification.class));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public boolean onStopCurrentWork() {
return super.onStopCurrentWork();
}
}
I have already tried the AlarmManager and so on as well, but the problem remains the same. The JobIntentService gets destroyed when the app is only running in the background.
Thank you very much for your help!

Related

How Android O affect background service to reduce battery drain?

I create a service that start a new thread to do stuff. In Android O, the android document said if the service is not a foreground service, then it will be stopped by the system. But I tested the following code, the service is destroyed but the thread is still running.
My question is how the system can save user's battery if the thread is allowed to be run even if the service is stopped?
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view) {
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
public void stopService(View view) {
stopService(new Intent(this, MyService.class));
}
}
MyService
public class MyService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run in service: ");
}
}
}).start();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
System.out.println("service onDestroy");
}
}
Did you test this behaviour for longer hours ? I had the same set-up with a service (started via main thread) running a worker thread inside. Upon testing the set-up for longer duration like 2-3 days. You will notice that system shuts down the entire process. So you can not rely on doing the background execution with a worker thread. Better approach is to use periodic or timed Jobs.

Service stops when main app si closed

When I close main app servic stops broadcasting intents. Where is mistake? I can't find any way to keep it running.
Broadcast recevier:
public class CustomReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Custom Broadcast recevied", Toast.LENGTH_SHORT).show();
}}
Service (AAA.java):
public class AAA extends Service {
final class MyThreadClass implements Runnable {
int service_id;
MyThreadClass(int service_id) {
this.service_id = service_id;
}
#Override
public void run() {
synchronized (this) {
try {
while (true) {
Thread.sleep(3000);
Intent i = new Intent();
i.setAction("cz.johnyapps.custombroadcast");
sendBroadcast(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(new MyThreadClass(startId));
thread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}}
Manifest:
<service android:name="cz.johnyapps.notificationservice.AAA"
android:exported="true"
android:process=":ServiceProcess"/>
Main activity: startService(new Intent(this, AAA.class));
Use startForeground method inside the Service to prevent such behavior
According to my knowledge one way is to make service running even after closing the app.
You have to make as notification in you app which will bind the
service to it. if the app is closed that notification will be attached
which will be binding the service to it.
Example: Android phone default Media sound playing app, if you close the app an notification is shown on the notification bar which maintains the service to keep the music playing in the service.

Wrong when register two receiver in an activity Android

I have an activity. It will be receive two variable from an service. In the service, I will send two variable to the activity by
// Send first variable
sendBroadcast(new Intent("first_one"));
// Send second variable
sendBroadcast(new Intent("second_one"));
Now, In the activity, I used bellow code to receive the data. There are
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(firstRec, new IntentFilter("first_one"));
registerReceiver(secondRec, new IntentFilter("second_one"));
}
#Override
protected void onPause() {
super.onPause();
if (firstRec != null) {
unregisterReceiver(firstRec);
firstRec = null;
}
if (secondRec != null) {
unregisterReceiver(secondRec);
secondRec = null;
}
}
private BroadcastReceiver firstRec = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG","OK first");
}
};
private BroadcastReceiver secondRec = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG","OK second");
}
};
However, I cannot print the log "OK second" when I called sendBroadcast(new Intent("second_one")); in the service. What is happen? How can I fix it? Thank you
UPDATE: my activity is an accept calling activity get from #notz
How can incoming calls be answered programmatically in Android 5.0 (Lollipop)?. Then I create an service as following
public class myService extends Service{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent answerCalintent = new Intent(getApplicationContext(), AcceptCallActivity.class);
answerCalintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
answerCalintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(answerCalintent);
//Send the second command after 10 second and make the calling in background
new CountDownTimer(10000, 100) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
sendBroadcast(new Intent("second_one"));
}
}.start();
return START_STICKY;
}
}
You should unregister your reсeiver in a method opposite to that in which you register it:
If you registered receiver in onCreate() - then you should unregister it in onDestroy().
But as i know, for most cases, the best practice is to register receiver in onResume() and unregister it in onPause().

Android starting intent activity error in service

In my application, there is a service class. I want to start an intent 10 seconds later with this service. When I try a basic toast message instead of starting intent, it works. However, when I write startActivity(intent) an error occurs. Here is my code. Where am I making mistake?
public class EkraniKilitle extends Service {
Handler yardimci;
Intent kilitEkrani;
final static long ZAMAN = 10000;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
kilitEkrani = new Intent(EkraniKilitle.this, KilitEkrani.class);
yardimci = new Handler();
yardimci.postDelayed(new Runnable() {
#Override
public void run() {
servisiDurdur();
startActivity(kilitEkrani);
}
}, ZAMAN);
}
public void servisiDurdur() {
stopService(new Intent(this, EkraniKilitle.class));
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
i guess you need to add your second activity to the manifest
after </activity> add <activity android:name=".MySecondClass"/>
Call startActivity(kilitEkrani); before servisiDurdur(); and to stop your current service all what you need is to call stopSelf() you do not have to use stopService

Sticky Service Management

I've got a Sticky Service (returns START_STICKY from onStartCommand) which executes some code in an AsyncTask, but I'm having some problems with how and when to start, bind, stop, unbind. I only want the service around whilst the parent activity is alive, I don't want it hanging around in the background when the app has been closed, but I need the service to survive an orientation change. I currently don't need the service to be active for the entire duration of the activity being active, so I call stopSelf() after the main work is done in my AsyncTask in the Service and then start the Service again when needed. Sometimes I'll need to interrupt the work the service is doing, cancel the AsyncTask and start again with different data. The problem is that no matter what I do - I can't seem to get it solid throughout all the different possible scenarios. Can anyone have a look through and tell me what I'm doing wrong?
My Service is :
public class ChordCalculatorService extends Service {
private final IBinder mBinder = new LocalBinder();
private AsyncTask<SearchData, SearchStatusData, List<Item>> currentTask;
#Override
public void onCreate() {}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public ChordCalculatorService getService() {
return ChordCalculatorService.this;
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public SearchData getSearchData() {
return searchData;
}
public void startWork() {
if (currentTask != null && currentTask.getStatus() == Status.RUNNING) {
currentTask.cancel(true);
}
if(searchData != null) {
Worker task = new Worker();
currentTask = task.execute(new SearchData[] { searchData });
} else {
Message msg = handler.obtainMessage(ERROR, "No search data set");
handler.sendMessage(msg);
}
}
class Worker extends AsyncTask<SearchData, SearchStatusData, List<Item>> {
// ... code ...
#Override
protected void onPostExecute(List<Item> result) {
Message msg = handler.obtainMessage(COMPLETE, new StatusData(Status.STATUS_FINISHED, result));
handler.sendMessage(msg);
stopSelf();
}
}
}
Currently I have the Service being started when my custom View is created:
public class MyCustomView extends BasicFretBoardView {
private ServiceConnection conn;
private MyService myService;
private boolean isServiceStarted;
private boolean isServiceBound;
public MyCustomView(Context context, AttributeSet attr) {
super(context, attr);
startService();
}
public void startService() {
Intent serviceIntent = new Intent(getContext(), MyService.class);
conn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = ((LocalBinder) service).getService();
myService.registerHandler(serviceHandler);
}
#Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
}
};
// Explicitly start the service. Don't use BIND_AUTO_CREATE, since it
// causes an implicit service stop when the last binder is removed.
getContext().startService(serviceIntent);
getContext().bindService(serviceIntent, conn, 0);
isServiceStarted = true;
isServiceBound = true;
}
public void stopService() {
if (isServiceStarted) {
Intent serviceIntent = new Intent(getContext(), MyService.class);
getContext().stopService(serviceIntent);
isServiceStarted = false;
}
unBindService();
}
public void unBindService() {
if(isServiceBound) {
getContext().unbindService(conn);
isServiceBound = false;
}
}
// gets called based on some user interaction
private void startServiceWork() {
if(!isServiceStarted) {
startService();
} else {
myService.cancelCalcalation();
}
myService.setData(data);
myService.startWork();
}
}
and stopping the service is handled in the Activity:
public class CustomChordActivity extends Activity {
// ... code ...
#Override
public void onBackPressed() {
super.onBackPressed();
}
#Override
protected void onPause() {
if(isFinishing()) {
chordsView.stopService();
}
super.onPause();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onDestroy() {
chordsView.unBindService();
super.onDestroy();
}
#Override
protected void finalize() throws Throwable {
super.finalize();
}
}
It seems that you want your task to run on demand, maybe an IntentService would be a more suitable option. When you need work to be done, (startServiceWork()), you just start the service and that kicks off your AsyncTask. The service will then finish after the task has finished.
Now, regarding orientation changes, you would have to implement a Broadcast Receiver whose intent filter is "android.intent.action.CONFIGURATION_CHANGED". (I assume that you want the service to do work when the orientation changes) Place the Broadcast Receiver, within your activity/main ui thread. This will in effect make the hosting process of your Broadcast Receiver to be the main application process making it safer to start the service from within the Broadcast Receiver.

Categories

Resources