Prevent killing of service when clear recent tasks - java

My app has Remote, Foreground aidl service which bound to activity. When i clear recent task (by swipe) service destroy. How can i prevent killing of service.
<service android:enabled="true"
android:exported="false"
android:stopWithTask="false"
android:process=":xplay"
android:name="com.perm.x.Services.PlayingService"/>
Here is how i bind (in onResume)
Intent serviceIntent = new Intent(this,PlayingService.class);
startService(serviceIntent);
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
Here is how i unbind service (in onPause)
unbindService(serviceConnection);

For preventing service from killing i found one hack (actually i did read it somewhere here)
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent intent = new Intent(this, DummyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
DummyActivity:
public class DummyActivity extends Activity {
#Override
public void onCreate(Bundle icicle){
super.onCreate(icicle);
finish();
}
}
And that's it. But there's side effect of this hack - The panel with recents will be immediately hidden after you swipe app of

Related

startActivity() in broadcast receiver bag(?)

I'm trying to start MainActivity with BluetoothDevice.ACTION_ACL_CONNECTED receive just like in some stack overflow answers
public class BTReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("BT", "Receive");
String action = intent.getAction();
...
switch (action) {
case BluetoothDevice.ACTION_ACL_CONNECTED:
Intent i = new Intent();
i.setClassName("com.opendashcam", "com.opendashcam.MainActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
And like this
Intent intent1 = new Intent(context, MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
But all that I can see it's just these logs (first two say that receive was gotten and activity was started with connection to written MAC)
D/BT: Receive
D/BT: started app with 00:14:41:1E:26:27
I/Timeline: Timeline: Activity_launch_request time:129879532
My Main Activity's onCreate:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("MA", "Started app");
init();
}
Since Android 10, according to Android Developers docs ,Android does not allow launching an activity from the background:
Android 10 (API level 29) and higher place restrictions on when apps can start activities when the app is running in the background. These restrictions help minimize interruptions for the user and keep the user more in control of what's shown on their screen.
As an alternative, you can show notification that will launch the activity if clicked:
In nearly all cases, apps that are in the background should display time-sensitive notifications to provide urgent information to the user instead of directly starting an activity.

How to destroy/kill a service?

I have my application running a service for shake detect, however in my MainActivity, I have button for log out user, in which I must log out and terminate the service that detects the shake event.
my method for log out in my MainActivity is:
public void signOutAndFinish(){
//Stop Shakeservice
Intent intent = new Intent(this, ShakeService.class);
stopService(intent);
//Go to login activity
Intent iLoginView = new Intent(this, LoginActivity.class);
startActivity(iLoginView);
}
however if I shake my device after logging out, the service recognizes the shake, it is as if it will not kill it immediately:
Intent intent = new Intent(this, ShakeService.class);
stopService(intent);
The code in the method onDestroy is:
#Override
public void onDestroy() {
super.onDestroy();
}
How can I terminate the service so that when I log out the service dies?
Thanks for your help!
You can send a broadcast back your activity in the onDestroy() method of your service and then do the logout.
Here is some sample code of the above idea:
This for your service:
#Override
public void onDestroy() {
super.onDestroy();
Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data","Notice for logout!");
sendBroadcast(intent);
}
And this is for your activity:
private BroadcastReceiver br = new MyBroadcastReceiver();
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter("com.example.broadcast.MY_NOTIFICATION");
registerReceiver(br, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(br);
}
// An inner class at your activity
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "MyBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
YourActivity.this.finish();
// or do anything you require to finish the logout...
}
}
however if I shake my device after logging out, the service recognizes the shake
Then presumably you did not clean up your Sensor stuff in the service's onDestroy() method.
How can I terminate the service so that when I log out the service dies?
You are doing that now. However, if you set up something in the service, such as listening to events from SensorManager, you need to clean that up, typically in onDestroy() of the service.

onReceive from BroadcastReceiver is not called

I have a music application in which I am trying to add some action button on the notification bar.
I tried something like this:
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
Intent onPreparedIntent=new Intent("MEDIA_PLAYER_PREPARED").putExtra("CURR_SONG",songposn);
LocalBroadcastManager.getInstance(this).sendBroadcast(onPreparedIntent);
Intent notintent = new Intent(this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Notification.Builder builder=new Notification.Builder(this);
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,notintent,PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent prevPendingIntent=PendingIntent.getActivity
(this,1,new Intent().setAction("PREVIOUS"),PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pausePendingIntent=PendingIntent.getActivity
(this,2,new Intent().setAction("PAUSE"),PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent nextPendingIntent=PendingIntent.getActivity
(this,3,new Intent().setAction("NEXT"),PendingIntent.FLAG_UPDATE_CURRENT);;
builder.setContentIntent(pendingIntent).setSmallIcon(R.drawable.playicon)
.addAction(R.drawable.back, "Previous", prevPendingIntent)
.addAction(R.drawable.playsmall, "Pause", pausePendingIntent)
.addAction(R.drawable.forw, "Next", nextPendingIntent)
.setTicker(songArtist)
.setOngoing(true).setContentTitle(songTitle).setContentText(songArtist);
Notification not=builder.build();
startForeground(MusicService.NOTIFY_ID,not);
}
I declared a NotificationReciever class inside this service
public class NotificationReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.e("here","here");
String action=intent.getAction();
if(action!=null){
switch (action){
case "PREVIOUS":{
playPrev();
break;
}
case "PAUSE":{
pausePlayer();
LocalBroadcastManager.getInstance(MusicService.this).sendBroadcast(new Intent("STOP_THREAD"));
break;
}
case "NEXT":{
playNext();
break;
}
}
}
}
}
Structure looks something like this:
-MusicService extends Service
--NotificationReciever extends BroadcastReceiver
My manifest file contains reciever like this:
<receiver android:name=".MusicService$NotificationReciever">
<intent-filter>
<action android:name="PREVIOUS"/>
<action android:name="PAUSE"/>
<action android:name="NEXT"/>
</intent-filter>
</receiver>
When I run my music play, notification does come up with buttons but they don't seem to fire the onReceive function?
What am I missing here?
Update:
Followed hasif sayed answer and I seem to found an error
java.lang.RuntimeException: Unable to instantiate receiver com.example.tilak.imusicplay.MusicService$NotificationReciev‌​er: java.lang.InstantiationException:java.lang.Class has no zero argument constructor
Googling about it, I found that I have to use a static class or I have to register/unregister in the parent class.
So this is what I did:
public void onCreate() {
super.onCreate();
//
LocalBroadcastManager.getInstance(this).registerReceiver(
new NotificationReciever(),new IntentFilter("PREVIOUS"));
LocalBroadcastManager.getInstance(this).registerReceiver(
new NotificationReciever(),new IntentFilter("PAUSE"));
LocalBroadcastManager.getInstance(this).registerReceiver(
new NotificationReciever(),new IntentFilter("NEXT"));
}
PendingIntent prevPendingIntent=PendingIntent.getBroadcast
(this,1,new Intent().setAction("PREVIOUS"),PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pausePendingIntent=PendingIntent.getBroadcast
(this,2,new Intent().setAction("PAUSE"),PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent nextPendingIntent=PendingIntent.getBroadcast
(this,3,new Intent().setAction("NEXT"),PendingIntent.FLAG_UPDATE_CURRENT);
Now I don't get this above error but onReceive is not working again.
Actually the reason why your broadcast reciever is not called when you click on pause,previous and next button is because ,you have set the pending intent to fire an acitivity,instead you have to set the pending intent to fire a boradcast
instead of this code snippet
PendingIntent nextPendingIntent=PendingIntent.getActivity
(this,3,new Intent().setAction("NEXT"),PendingIntent.FLAG_UPDATE_CURRENT);;
you have to correct it like this
PendingIntent nextPendingIntent=PendingIntent.getBroadcast
(this,3,new Intent().setAction("NEXT"),PendingIntent.FLAG_UPDATE_CURRENT);;
make corrections in all the three pending intent code which you have written
UPDATE
The reason why you still not receiving the broadcast in your Broadcast Receiver is because you are programitically registering your Receiver as LocalBroadCast
When using with PendingIntent, LocalBroadcast will not receive the Broadcast
so please remove this Line
LocalBroadcastManager.getInstance(this).registerReceiver(
new NotificationReciever(),new IntentFilter("PREVIOUS"));
LocalBroadcastManager.getInstance(this).registerReceiver(
new NotificationReciever(),new IntentFilter("PAUSE"));
LocalBroadcastManager.getInstance(this).registerReceiver(
new NotificationReciever(),new IntentFilter("NEXT"));
Instead, you only have to register the receiver in the Manifest.xml file
or
programitically you can register in code as
NotificationReciever mReciever = new NotificationReciever();
this.registerReceiver(
mReciever,new IntentFilter("PREVIOUS"));
this.registerReceiver(
mReciever,new IntentFilter("PAUSE"));
this.registerReceiver(
mReciever,new IntentFilter("NEXT"));
but if you register this programitically, make sure you unregister it while service is getting destroyed. Otherwise you may LEAK the BroadcastReceiver Object

How to prevent restarting a running Service - Android

i'm want to do long background work
also i want to be able to show progress with statistics in ui anytime user goes to a activity also with updating notification.
i start a Service in START_STICKY mode then i bind it to my activity and run the proccess with an public method of Service.
everything works well until i close my app from recent apps.
it destroys and restart my running Service.
that's the problem. "i don't want my running service to restart"
i want my service to keep running without termination and without restarting.
how can i do what i want to do?
why os restart a running service: / thou
i tried START_NOT_STICKY but it's closing the service too.
On Android 6+, a foreground service will not be stopped when the user removes the app from recents. You can make your service a foreground service by adding this code to onCreate():
final Intent launcherIntent = new Intent();
final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, launcherIntent, 0);
final Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Test Notification")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent);
final Notification notification;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification = builder.build();
}
else {
//noinspection deprecation
notification = builder.getNotification();
}
this.startForeground(NOTIFICATION_ID, notification);
Prior to Android 6, services are always killed when the user removes the task from recents. There is nothing you can do about it except shut down cleanly in onTaskRemoved().
Try using foreground service:
In method where you start service:
Intent startIntent = new Intent(MainActivity.this, ForegroundService.class);
startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(startIntent);
Now in onStartCommand():
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
Log.i(LOG_TAG, "Received Start Foreground Intent ");
Toast.makeText(this, "Service Started!", Toast.LENGTH_SHORT).show();
Read more Simple foreground service
OR you can try something like this:
from onStartCommand() need to return START_STICKY
override in your service onDestroy method:
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent();
broadcastIntent.putExtra("broadcast.Message", "alarm, need to restart service");
sendBroadcast(broadcastIntent);
}
Now need to implement broadcast receiver:
public class RestarterBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
context.startService(new Intent(context, YourService.class));
}
}
check if service is running or not
if(!isBackgroundServiceRunning(BackgroundServices.class))
{
Intent intent = new Intent(this,BackgroundServices.class);
startService(intent);
}
private boolean isBackgroundServiceRunning(Class<?> service)
{
ActivityManager manager = (ActivityManager)(getApplicationContext().getSystemService(ACTIVITY_SERVICE));
if (manager != null)
{
for(ActivityManager.RunningServiceInfo info : manager.getRunningServices(Integer.MAX_VALUE))
{
if(service.getName().equals(info.service.getClassName()))
return true;
}
}
return false;
}

Running background service through shortcut

So I want to launch a service from a shortcut. I know that this is not possible to do directly, so I've set up a activity with the sole purpose of starting the service.
The aim of my service is to send an intent to another app and then 5 seconds later send another so I've used a CountDownTimer to do this.
However, when I launch the Activity that starts the service from the shortcut (this is getting confusing) it launches the apps UI. I don't want this, as I want it to be a background service.
What am I doing wrong. I've only just got into development, so it could be something obvious, but I've been battling with this for a few days now.
For some reason when I run it from the service it just launches the app straight away...
When I run it straight from the invisible activity it runs properly for the 1st 5 seconds fine and then loads the app...
I can't figure out why it's loading the app at all.
I've included as much info as I can that would be relevant.
Any help is appreciated!
My service:
public class Pop1_5Service extends IntentService {
public Pop1_5Service() {
super("Pop1_5Service");
}
#Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
new CountDownTimer(5000, 2500) {
public void onTick(long millisUntilFinished) {
Intent i = new Intent(INTENT_ACTION);
Bundle b = new Bundle();
b.putInt(BUNDLE_VERSION_CODE, 1);
b.putString(BUNDLE_STRING_NAME, "POP1");
b.putString(BUNDLE_STRING_VALUE, "1");
i.putExtra(BUNDLE_NAME, b);
sendBroadcast(i); }
public void onFinish() {
Intent i = new Intent(INTENT_ACTION);
Bundle b = new Bundle();
b.putInt(BUNDLE_VERSION_CODE, 1);
b.putString(BUNDLE_STRING_NAME, "POP1");
b.putString(BUNDLE_STRING_VALUE, "1");
i.putExtra(BUNDLE_NAME, b);
sendBroadcast(i); }
}
}.start();
}
}
Activity that launches service:
public class Pop1_5Activity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, Pop1_5Service.class);
startService(intent);
finish();
}
}
Subsection of Manifest:
<activity
android:name=".Pop1_5Activity"
android:theme="#android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".Pop1_5Service" />
And the 'Create a Shortcut' Activity:
public class CreateShortcutActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent shortcutintent = new Intent(this, Pop1_5Activity.class);
ShortcutIconResource iconResource = Intent.ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutintent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Pop1_5");
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
setResult(RESULT_OK, intent);
finish();
}
}
From the look of things, it looks like CreateShortcutActivity does nothing.
Your LAUNCHER is Pop1_5Activity, so when the user presses the app icon, this Activity will run, and it launches the Service.
All the code you have showed us are "invisible", the two Activities finish() themselves, and the Service is a Service.
You might want to look at how your BroadcastReceiver handles your broadcast. For instance, does it create another Activity through PendingIntent? Is the Activity created invisible?
Maybe you should try creating a pending Service instead of pending Activity in the BroadcastReceiver.

Categories

Resources