MQTT client connection not running in background [duplicate] - java

I want to run my app in background if I kill the app instance also. But after I kill my app the service also stops working. Here is my code please any one help me to solve my issue.
I followed this link for running in the background but it is not working if I remove the instance. Please can any one show me how to run a background service if the instance is removed also?
This is my MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
setContentView(R.layout.activity_main);
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ALARM_REQUEST_CODE, alarmIntent, 0);
mSensorService = new SensorService(getCtx());
mServiceIntent = new Intent(getCtx(), mSensorService.getClass());
if (!isMyServiceRunning(mSensorService.getClass())) {
startService(mServiceIntent);
}
}
Ths is my service class
public class SensorService extends Service{
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.i("in timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}

Its a long story. I have gone through it. Still implemented it. Now my service runs on every boot_complete event and keeps running all the time ( with a notification ).
Official Documentation:
Big NO. Google android developer documentation is poor, with no proper sample example too. It is theoretical and just theoretical. Keep reading if interested
https://developer.android.com/about/versions/oreo/background
Synopsis 1:
You can only receive BOOT_COMPLETE and only few broadcasts in traditional receiver. Rest all broadcast receivers you need to implement runtime in a service by registering them through a code from service which always runs.
Synopsis 2:
Again, you can not have always running processes in or above 8.0 (Oreo)...
To achieve always running process... Create a Intentservice with proper notification of type ongoing and make OnStartCommand START_STICKY and register receiver with code in OnCreate
How to implement it :
I have implemented it take reference from here :
Oreo: Broadcast receiver Not working
Now Your Question : I want to run my app in background if it kills the
app instance also.
With the help of above implementation link of my own you can achieve it
*Terms and conditions
You device must have proper android operating system released and burnt as it is.
Yes, I am using android :
No... You are Using Funtouch OS : VIVO ( By modifying Android)
There are many devices in market COLOR OS : OPPO ( By modifying Android)
....
....
Already google has made it complicated... version by version....
With no proper documentation and sample codes....
And Now Independent mobile device manufacturers making a lot of
changes to allow only selective applications run in background
like WhatsApp, Facebook, Google Twitter Instagram
Now you will ask a developer question If these app runs in background then I can make my app run in background too....
No... They are OS based modifications to check if a service is from allowed vendors then only it can be alive there in background. If they will not allow these vendors then no one take phones which does not run these famous social apps.
Hushhhhhhhh.......

You need to create ForegroundService in order continue processing when your app is killed, as follows:
public class SensorService extends Service{
private PowerManager.WakeLock wakeLock;
#Override
public void onCreate() {
super.onCreate();
//wake lock is need to keep timer alive when device goes to sleep mode
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK_TAG");
createNotificationChannel(this);
Notification notification = new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL").setSmallIcon
(<icon>).setContentTitle("Title")
.setContentText("Content").build();
startForeground(1001, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
public void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Channel name";
String description = "Description";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel("NOTIFICATION_CHANNEL", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
To start the service:
Intent i = new Intent(context, SensorService.class);
ContextCompat.startForegroundService(context, i)
Note:
You cannot run service endlessly with this approach. During doze mode if OS recognizes it as CPU intensive then your Service will be terminated.
You need to call stopSelf() when your Timer task has been executed successfully.

Oreo Introduced
new Concept PIP (Picture in Picture Mode )
and it have categories services control by making channels and priority to them.you have to change the code just for oreo to create notifications and services
read about google developers documentation carefully here
https://developer.android.com/guide/topics/ui/notifiers/notifications
both java and kotlin code is available here to create notification in oreo
https://developer.android.com/training/notify-user/build-notification
it was my effort to find the solution after searching and sharing with you.
here is some sample code :
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
for creating channels write this code:
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
you can see full detials for push notifications and sending messages by clicking on the above links.

Related

How to run java In background

How to run this in background , I mean even I move to other app or go to home screen of my android or close the screen , the button will still clicking itself
please help me
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
button1.performClick();
}
}, 5000);
Things to know
I will try to elaborate as much as I can in a layman terms so that you have a better grasp the Idea of Threads and async tasks
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//business logic
}
}, 5000);
is an Blocking method, which runs on the UI thread (I am supposing you are new to programming/android)[please read about Threads to understand what I am saying in deapth],
which means, in short, your application is executing some logic on the thread ("A worker" which is responsible for the rendering the UI on-screen),
By using Threads you can achieve efficiency in your application by dividing multiple tasks to multiple workers "Threads" but you can't run your application in the background.
How to make your application work in the background?
Google introduced some background limitations in Android Oreo. so to keep your application alive you need
foreground service by showing an ongoing notification.
1. The way you should implement service is like
public class YourService extends Service {
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
// do your jobs here
startForeground();
return super.onStartCommand(intent, flags, startId);
}
private void startForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // don't forget create a notification channel first
.setOngoing(true)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText("Service is running background")
.setContentIntent(pendingIntent)
.build());
}
}
2. Also you need to start the service
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
startService(new Intent(this, YourService.class));
}
}
3. Add your service in the "application" tag of your AndroidManifest.xml
<service android:name=".YourService"/>
4. And also this permission request in the "manifest" tag (if API level 28 or higher)
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
In this way, you can keep your service in the background. I suggest you read articles and see GitHub repositories, and also practice practice practice a lot to be good at Android :)

How to send data to Firebase continuously avoiding Doze and App Standby

I developed this app that needs to send data to Firestore when user press a button and ends when user stop it (by pressing another button). The data must be sent even if the user is doing other things or even if the user leavs the phone in standby for hours (so i need to avoid Doze and App Standby).
I used a service to achieve this and just one thing seems to work in the wrong way.
Service
public class MyService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
// vars declaration
private Date date = null;
// get every X seconds
public static final long DEFAULT_SYNC_INTERVAL = 60000;
private Runnable runnableService = new Runnable() {
#Override
public void run() {
class GetDataTask extends AsyncTask<String, Void, List<Data>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
if(getPositionData.isCancelled()){
return;
}
}
#SuppressLint({"MissingPermission", "HardwareIds"})
#Override
protected List<Data> doInBackground(String... v) {
// skipping get Timestamp code
// skipping get position code
myPos = new Data(position.getId(), latitude, longitude, timestamp);
// Insert data into Firebase
documentReference = firebaseFirestore.collection("data").document();
Map<String, Object> data = new HashMap<>();
data.put("lat", myPos.getLat());
data.put("date", myPos.getDate().toString());
documentReference.set(data).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.i("data", "data added.\n");
}
});
Toast.makeText(DataPollService.this, "" +
"ID: " + myPos.getImei()
+ " Latitude: " + myPos.getLat()
+ " Longitude " + myPos.getLng()
+ " Date: " + myPos.getDate()
, Toast.LENGTH_SHORT).show();
}
}
}, Looper.getMainLooper());
positionsList.add(myPos);
return positionsList;
}
protected void onPostExecute(List<Data> result) {
Position.getInstance().setPositions(result);
}
}
// RUN TASK
getPositionData = new GetDataTask();
getPositionData.execute(position.getId());
handler.postDelayed(runnableService, DEFAULT_SYNC_INTERVAL);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ksurf)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
handler = new Handler();
handler.post(runnableService);
return START_NOT_STICKY;
}
// onBind
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
Log.d("show", "onDestroy");
handler.removeCallbacks(runnableService);
stopSelf();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
In MainActivity starting the service like this:
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("inputExtra", "run");
ContextCompat.startForegroundService(this, serviceIntent);
If I don't use the phone and let the app sending data in background, the data are not sent to Firebase until I open the app back again. The service is not stopped, I just need to open the app in order to send data to firebase!
I read about Firebase Cloud Messaging but I didn't understand if I need them for my purpose. What am I doing wrong?
The data must be sent even if the user is doing other things or even if the user leavs the phone in standby for hours (so i need to avoid Doze and App Standby).
Generally speaking, it is not a good idea to have your app running processes when in Doze or App Standby mode. The Android documentation even points out that Network access is suspended; and therefore, your process might not be guaranteed to run reliably or terminate over other apps that may have a higher priority.
The problem is that if I don't use app for like 1 hour (so phone is in standby) data on firebase are only added when I open the app again. It's like they are saved in cache and sent to DB when app is opened again.
According to the documentation, "Cloud Firestore supports offline data persistence. This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline. You can write, read, listen to, and query the cached data. When the device comes back online, Cloud Firestore synchronizes any local changes made by your app to the Cloud Firestore backend."
The service is not stopped, I just need to open the app in order to send data to firebase! I read about Firebase Cloud Messaging but I didn't understand if I need them for my purpose.
A recommended solution would to ping your app from your server using Firebase Cloud Messaging when your client app goes into idle mode. This feature is useful when you need to send real-time downstream messages to your backend server or simply notify your client app that new data is available to sync (which may be what you're looking for).
You can refer to the above documentation for further details.
in every platform or language, there is a deferent way to connect to the firebase, so, please more information about the platform can help ??,
but you can check this link maybe his can to help you -> link

Android: Can I move a Service between foreground and background? [duplicate]

From the stackoverflow and many blogs, i surely understand that foreground service never run without notification in API>25. But still i confuse that Is notification mandory while app is running on screen or visible.
For eg. no need of notification when user stand within app. So is this possible to remove notification while app running ?
In service class
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
......
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(text)
.setAutoCancel(true);
Notification notification = builder.build();
startForeground(1, notification);
}
return START_NOT_STICKY;
}
In activity
Intent myService = new Intent(this, MyService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(myService);
} else {
startService(myService);
}
It's not possible to remove the notification while the foreground service is running, but it is possible to change your foreground service back into a "regular" service. This removes the need for a notification. In fact, the function to use,
stopForeground(boolean removeNotification)
...includes a removeNotification parameter just for that purpose. You service can switch from being "foreground" to "regular" on demand, by alternating calls to startForeground() and stopForeground().
In case it's not clear, you'd probably want to call stopForeground() whenever you have at least one Activity in a "started" state. This is something you'd have to track manually. Then, when the number of "started" activities reaches 0, you'd call startForeground().
EDIT
One approach is to use a bound service. Then, it's easy to call stopForeground() on it when you want.
Assume you have a single Activity. You can bind it to the service (see this doc or use one of these examples). Then your onServiceConnected() function could look like this (adapted from the Google example):
//MyActivity.java:
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mService.stopForeground(true); //This makes the notification go away
bound = true;
}
...
#Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MyService.class), this, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (bound) {
Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(text)
.setAutoCancel(true);
Notification notification = builder.build();
mService.startForeground(1, notification); //This brings the notification back! Service is already running, and continues to run.
unbindService(this);
bound = false;
}
}
No, it is mandatory even your app is running in foreground your foreground service need a notification.
You won't able to hide it.
Why :
You can use any other background task handler like intent service, job sclr but things is designed defferent for foreground service your user understand that event i will close this one of it's progress is going to keep running but things is defferent with background service your know it will do something in background but when system decide it's best time to do it not when your app want (as like in foreground service).
One more case ex :
Suppose your app in foreground battery level is lower than expected by user or system your foreground service will execute instantly no matter what so it's important for your user to know this it's running and take my resources (battery, data, etc)
Hopefully you got my mean 🙂

Background Service with Notification

I am developing an Android application which calls API's to fetch data. Now I want to perform this task in background and each time data is changed in the List view, a notification should be generated.
How can I achieve this?
How can I make my API called in background and how can i generate notification.
I am new to Services and BroadcastReceivers so help me
I am calling the service this way:
startService(new Intent(this, MyService.class).putExtra("Background",true));
I created this code to testing purpose. To check if notifications can be called in background even if the app is closed.
My Service Class
public class MyService extends Service {
private Boolean isShowingNotification = true ;
NotificationManager notificationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (intent.hasExtra("Background")) {
if (isShowingNotification) {
StopImportantJob();
stopSelf();
} else
DoImportantJob();
} else {
DisplayNotification("Now showing the demo");
}
return START_NOT_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Toast.makeText(this, "On Create Called", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
super.onDestroy();
notificationManager.cancelAll();
}
public void DisplayNotification(String message){
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setContentTitle(message)
.setContentText("Touch to off Service")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
notificationManager.notify(0,notification);
}
public void DoImportantJob(){
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("New mail from " + "test#gmail.com")
.setContentText("Subject")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
startForeground(1992, notification);
isShowingNotification =true;
}
public void StopImportantJob(){
stopForeground(true);
isShowingNotification = false;
if(false){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ){
stopForeground(STOP_FOREGROUND_DETACH);
stopForeground(STOP_FOREGROUND_REMOVE);
}
}
}
}
What I believe I should do is listed below, please correct me if I am wrong.
Start Service in the onCreate() of the MainAcitivity of Application.
In the Service call I will create a method which will do the API call.
On notifyDataSetChanged(); will call the Notification method.
Now here is the question: In Service class the API method will be called in onCreate() or onStartCommand().
Now i want to perform this task in background and each time data is
changed in the List view, a notification should be generated. How can
i achieve this? How can i make my API called in background and how can
i generate notification.
First Decide, whether you want this operation when your application is in Foreground OR Background. Now, if Foreground, you might not want to use Service class and use AsyncTask instead for making your webservice calls and generate the notification and updatethe listview once task is done. If Background, you can create IntentService and do your API operation there. However, in background mode, your application do not need to be notified as your app will not be visible to client.

Android: Background Service always shuts down

Recent changes in Androids background task running behaviour makes it very difficult to keep Services alive and continue work in applications when the phone is locked. My Service is only working properly when the screen is on or the phone gets charged. When the phone is locked, the Service shuts down almost immediately or runs way too slow to be useful in any way.
I tried to use "START_STICKY" flag and a startForeground() Notification to keep the Service alive but this doens't help at all. I'm using a Handler that calls dowork() every 5 seconds, which then checks if theres something to do.
I want to perform a simple task on a certain time event: wake up every half/quarter or full hour, do some quick work without CPU limitation, then shut down until next time. The phone should wake up reliable and accurate on time and get "whitelisted" to use some CPU power for around half a minute. I don't do any intense work, that could affect user performance.
public class MyService extends Service {
public MyService() {
super();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("MyService")
.setContentText("Service is running")
.setPriority(IMPORTANCE_HIGH)
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
dowork();
handler.postDelayed(this, 5000);
}
}, 1500);
return START_STICKY;
}
For this question i want to refer to Alarm Manager Example
. This one is doing it's job pretty well, i finally got it working that way.

Categories

Resources