Service stop working when there are many apps opened - android

I am just trying Services in Android with this simple code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, PlayerService.class));
}
PlayerService.java:
public class PlayerService extends IntentService
{
public PlayerService()
{
super("PlayerService");
}
#Override
protected void onHandleIntent(Intent i)
{
int n=0;
while(true)
{
Log.i("SERVICE", "Event n." + n++);
try {
Thread.sleep(1000);
}
catch (InterruptedException e)
{ }
}
}
#Override
public void onDestroy()
{
Log.i("SERVICE", "Distr Service");
}
}
I have declared the Service in the manifest:
<service android:name="PlayerService"/>
When I start this app and then open many other apps, then this app stop working ( as I can see in the LogCat that stop showing me "Event n..." ). Why ?

In Manifest, Declare Like this
<service
android:name="Yourpackagename.PlayerService"
android:enabled="true" />
Thanks

Use Service, not IntentService. According documentation, IntentService is stoped when operation is done. Take a look here for more things about IntentService. Service is used for long term running. Take a look here.

The problem was that I must use the foreground service.

Related

listen for firebase event after app killed

I was trying listen for a change in firebase firestore collection, after the app is closed. For that I have written the following code:
FirebaseFirestore.getInstance().collection("demo").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
//show a notification to user
...
...
Toast.makeText(MainActivity.this, "collection modified", Toast.LENGTH_SHORT).show();
}
});
It works when the app is in background (pressed backbutton to exit app, but app is available on recent screen) but when I clear the app from recent screen, the code stops working.
How can I listen for firebase event even after the app is killed?
Edit:
I tried to use two approaches, but as soon as the app get swiped from recents screen both of these approaches stop working:
Using Alarm Manager. Following is the code for this implementation:
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
FirebaseFirestore.getInstance().collection("demo").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
Toast.makeText(context, "collection modified", Toast.LENGTH_LONG).show();
}
});
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startFirebaseTesting();
}
});
}
private void startFirebaseTesting() {
Intent in = new Intent(this, FirebaseService.class);
in.setAction("com.example.this.app");
in.addCategory("android.intent.category.DEFAULT");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 4, in, PendingIntent.FLAG_ONE_SHOT|PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000*5, pendingIntent);
} else
alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000*5, pendingIntent);
}
}
AndroidManifest.xml
<application>
...
...
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.this.app"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
...
...
</application>
Adnan Arshad's answer to this question
Both of these solution don't work on MotoG5s plus (Oreo) and Samsung A50 (Android 10).
Whenever you wish to run any code in the background use Services.
So in our case it will be something like this:
Create a FirebaseService.java class.
public class FirebaseService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "service starting", Toast.LENGTH_SHORT).show();
FirebaseFirestore.getInstance().collection("demo").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
//show a notification to user
Toast.makeText(getApplicationContext(), "collection modified", Toast.LENGTH_SHORT).show();
}
});
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
Toast.makeText(getApplicationContext(), "service done", Toast.LENGTH_SHORT).show();
}
}
Start the service using startService() from your Activity.
Intent intent = new Intent(this, FirebaseService.class);
startService(intent);
Note:
When a service is started, it has a lifecycle that's independent of the component that started it. The service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is complete by calling stopSelf(), or another component can stop it by calling stopService().
Every Service must be declared in the Manifest.xml file.
<manifest ... >
...
<application ... >
<service android:name=".FirebaseService" />
...
</application>
</manifest>
SUGGESTION
If you just want to display a pop up notification when the firebase collection is updated then it is best to implement it using Firebase Cloud Messaging as you can easily display built-in notifications without worrying about the lifecycles.
If you want to use this method then here is a complete tutorial that will help you:
https://www.youtube.com/watch?v=Y6jMKQ9zo-o

Proper way to start activity in background

I need to do a logout after some time, so I'm opening the login window in my app using.
startActivity(intent);
Problem is that, if the user has my app in the background, my activity will pop up.
Is there a way to easily open an activity but keep my app in the background?
It can be done with Android appliaction component Service.
you can read about it in official documentation by links below.
https://developer.android.com/training/run-background-service/create-service#java
https://developer.android.com/guide/components/services?hl=en
Initialize your Service
public class MyBackgroundService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
//onCreate - Service created
}
#Override
public void onDestroy() {
//onDestroy - Service destroyed (Stopped)
}
#Override
public void onStart(Intent intent, int startid) {
//onStart - Service started
}
}
Then call Service in your Main Activity
startService(new Intent(this, MyBackgroundService.class));
And don't forget about declare in Manifest.
<service android:enabled="true"
android:name=".MyBackgroundService" />
You can implement "local logout" after some time and when user returns to activity you can detect it. More: https://developer.android.com/guide/components/activities/activity-lifecycle

Android Service with a loop?

I need to create a background service that starts and stops with two buttons. My service will cycle every 5 minutes and it will take data from an online database. I read somewhere that IntentService class is not used for loops. I would override onStartCommand so it will return START_STICKY. If i do that in this class my service doesn't start. How can I do this?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view){
startService(new Intent(this, ForegroundService.class));
}
public void stop(View view){
stopService(new Intent(this, ForegroundService.class));
}
}
public class ForegroundService extends IntentService{
private boolean stato;
public ForegroundService(){
super("ForegroundService");
}
#Override
public void onCreate(){
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
}
#Override
protected void onHandleIntent(Intent i){
stato = true;
int n=0;
while(stato)
{
Log.i("PROVA SERVICE", "Evento n."+n++);
try {
Thread.sleep(1000);
}
catch (InterruptedException e)
{ }
}
}
#Override
public void onDestroy() {
stato = false;
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
}
Only have a service running when it is actively delivering value to the user. Sitting and watching the clock tick is not actively delivering value to the user.
Also, please understand that what you want ("cycle every 5 minutes and it will take data from an online database") may not be what the user wants and certainly is not what Google wants. Too many developers are doing stuff like this, and battery life is suffering as a result.
Generally speaking, your best solution (given your stated objective) is JobScheduler, perhaps falling back to AlarmManager if your minSdkVersion is below 21. Both of those allow you to schedule periodic work. Your process does not need to be running in between those bits of work. You teach JobScheduler or AlarmManager how frequently to trigger the work, and you do the work in a JobService or IntentService.
Just bear in mind that on Android 6.0+, unless the user tells Android via the Settings app to leave your app alone, your app will eventually enter Doze mode or app standby mode, and you will not be able to get control every five minutes.

How do i stop my service?

i have a service which shows a toast message. i defined it in manifest like this-
<service android:name=".ShowNotification" />
and this is my service-
public class ShowNotification extends Service {
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(), "service worked once",
Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
but i cannot figure out how to stop this service and also how to start it again?
Try :
stopService(new Intent(this, ShowNotification.class));
startService(new Intent(this, ShowNotification.class));
And restart the Service, gona recall onCreate()
Use IntentService rather than using only Service. IntentService will be destroyed automatically after completion of the task.You don't need to worry about stopping it.

How should I implement this secondary thread to avoid errors? (Android)

I am implementing in my Android app a splash screen which:
dowloads a sqlite database from a server
loads urls to get JSONs
creates a sqlite database in the device and execute several queries
I am using AsyncTask to do everything, my problem will occur if the user close the app in the middle of the process or turn off the device because the app:
could be creating a database or executing crucial queries in the device
could be downloading the sqlite db from a server
could be running several important process
etc
Definitely, the entire process (3-5 seconds) is important.
So... How could I avoid this? should I use handlers, loaders, on-(pause, stop, destroy) methods in order to get my objective? Can you give me an example?
As mentioned in the comment above, you should use a service as their lifecycle is separate to that of the activity.
Create the service like so:
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Do everything you need to here, then call stop:
Log.d("DEBUG", "Started...");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Intent intent = new Intent("com.example.androidexample.SERVICE_STOPPING");
sendBroadcast(intent);
super.onDestroy();
}
}
Then in the activity:
public class MainActivity extends Activity {
private ServiceCompleteReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter;
receiver = new ServiceCompleteReceiver();
filter = new IntentFilter("com.example.androidexample.SERVICE_STOPPING");
startService(new Intent(this, MyService.class));
registerReceiver(receiver, filter);
}
public class ServiceCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do whatever needs to be done here
unregisterReceiver(receiver);
}
}
}
EDIT :
Don't forget to add it to your manifest as well
<service
android:name="com.example.androidexample.MyService"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
</service>

Categories

Resources