Updating Notification Continuously - java

Hello There I am a newbie for Android Development, working to learn it to my own!
I just want to update my notification in a Java Thread in my application (I am just learning and curious about how can I do it).
I have an activity, a simple thread to increment an Integer value. Then, I just want to show it in my Notification whenever the Integer value increments!
My Code is as:
public class MainActivity extends Activity{
private final String LOG_KEY = this.getClass().getSimpleName();
private int c = 0;
private boolean flag = true;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
builder = new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false);
builder.setOngoing(true);
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Thread t = new Thread(new MyThread());
t.start();
}//OnCreate ends
#Override
protected void onStop() {
super.onStop();
flag = false;
}//stop ends
#Override
protected void onDestroy() {
super.onDestroy();
flag = false;
}//destroy ends
private class MyThread implements Runnable {
#Override
public void run() {
while (flag) {
c+=1;
showNotification(Integer.toString(c) + " Counts");
}//while ends
}//run ends
private void showNotification(String msg) {
try {
//set the notification
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends
}//private class ends
}//MainActivity class ends here
As from my code, the notification appears and updates the value! But the problem is that it freezes the device and application at a sudden!
I just want help for what I am doing wrong as I am a newbie and learning it to my own. Any help and idea will be highly appreciated!
Thanks

You shouldn't be creating a notification and then continuously updating it as fast as you can from a thread. It's really not designed for that.
The closest thing I can think of that would meet your use case is using a notification to display progress. See this link:
Displaying Progress in a Notification
You might want to put some kind a rate limiter in your thread, unless you want your count to reach very high numbers very quickly. Perhaps make the thread sleep for a second between updates.

The problem is that you produce too much notifications more then a device can consume.
For your goal (just learn) you can add a some pause between notifications like that:
private void showNotification(String msg) {
try {
//set the notification
Thread.sleep(1000); //set the pause
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends

Related

Android - How can I synchronize UsbManager::requestPermission?

I have the following code:
public final static #NonNull String ACTION_USB_PERMISSION = "blah blah";
public final #NonNull Object permissionLock = new Object();
public final #NonNull AtomicBoolean didReceiverReceive = new AtomicBoolean(false);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
didReceiverReceive.set(true);
synchronized (permissionLock) {
permissionLock.notifyAll();
}
}
}, new IntentFilter(ACTION_USB_PERMISSION));
final #NonNull UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
final #NonNull UsbDevice usbDevice = usbManager.getDeviceList().values().stream().findFirst().get();
// For the sake of requesting permission, assume
// usbDevice != null; (and unwrapping the Optional<UsbDevice> was successful)
// usbManager.hasPermission(usbDevice) == false;
// We need to request permission!
synchronized (permissionLock) {
usbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE));
/* CASE 1: assume UsbManager::requestPermission is asynchronous
* THIS CAUSES DEADLOCK! THIS IS BAD
try {
permissionLock.wait();
} catch (InterruptedException ie) {
// this never happens btw
throw new RuntimeException(ie);
}
*/
/* CASE 2: assume UsbManager::requestPermission is synchronous
* THIS THROWS AN ASSERTION ERROR! THIS IS BAD
assert didReceiverReceive.get();
*/
}
// TODO how do I safely block execution of the Thread that calls onCreate until the USB-permission broadcast receiver receives the broadcast intent?
}
I tried two things (named CASE 1 and CASE 2), which are in the onCreate method in the location in which they were invoked.
I was expecting that UsbManager::requestPermission was either asynchronous or synchronous. Pretty reasonable, no? It turns out it is semi-synchronous for lack of a better word. What happens is that the UsbManager seems to schedule the broadcast/permission request to be executed at some time in the future, but not necessarily on a different thread. This thread that it uses to schedule the broadcast/permission request is the same that calls onCreate, regardless of whether or not I put usbManager.requestPermission(...) in a new Thread. Consequently, I simply cannot create a scenario in which the USB-permission broadcast receiver's onReceive method is invoked appropriately before the onCreate method terminates.

I need to close a notification when the application is closed

I have this Runnable method which send a notification once it is called and every minute sends a JSON Post on an HTTP Server. So i coded the method "sendNotification" to keep informed the user regards the "service" is running but when I close the app, the method to send the JSON stops and the notification stays active on the notification bar. I would like to close the notification as well.
//Runnable methods for frequency position
private final Runnable oneMinuteRunnable = new Runnable() {
#Override
public void run() {
sendNotification();
getTimestamp();
new Thread(new Runnable() {
#Override
public void run() {
getLocation();
doPostRequest();
}
}).start();
handler.postDelayed(this, 60 * 1000);
}
};
This is the notification method
//Make notification when the frequency service is running
public void sendNotification() {
Notification notification = new NotificationCompat.Builder(this, com.example.httptracker.Services.Notification.NOTIFICATION_ID)
.setSmallIcon(R.drawable.ic_baseline_run_circle_24)
.setContentTitle("AMP Tracker")
.setContentText("Tracker is running")
.build();
compat.notify(1, notification);
}
I looked up online and I saw only solutions with a Service class but I would need to develop a "stop service" button to cancel the notification. But it is not what I need. The notification should disappear once the app is closed or the method killed.
Thanks in advance
try to cancel your notification with:
compat.cancel(1); // assuming compat is NotificationManager instance, 1 is your id
in e.g. onDestroy of Activity or any place when your app is stopping oneMinuteRunnable looped execution

How can i keep the job service running when the app is closed from recent task list by user

I am using Job Scheduler API in my app to schedule a job for me after specific time interval. It runs fine when the app is running. But whenever the user closes the app or clears it from the recent task list the app stops and the scheduled job never executes afterwards until you open the app and it is rescheduled again from the time it is opened.
Now i want someone to help me to keep the jobs on executing even if the app is closed or cleared from the recent task list.
If there is any alternative solution please tell me.
i am looking for the solution from the past 3 days. Tried everything said by developers on StackOverFlow and other sites and none of them worked for me.
This is where is schedule the job!
ComponentName componentName = new
ComponentName(getActivity().getBaseContext(),WallpaperJobService.class);
JobInfo jobInfo = new JobInfo.Builder(777,componentName)
.setRequiresCharging(sharedPreferences.getBoolean("Charging",false))
.setRequiredNetworkType(sharedPreferences.getBoolean("Wifi",false) ?
JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY)
.setPeriodic(sharedPreferences.getInt("Duration",15) * 60 *
1000)
.setPersisted(true)
.build();
JobScheduler scheduler = (JobScheduler)
getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
My Job Service Class:
public class WallpaperJobService extends JobService {
private boolean jobCancelled;
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
#Override
public boolean onStartJob(JobParameters params) {
Log.i("WallpaperJobService", "Job started!");
changeWallpaper(params);
return true;
}
private void changeWallpaper(final JobParameters params) {
final ArrayList<Image> images = (ArrayList<Image>)
MainActivity.favoritesRoomDatabase.roomDao().getAllFavoriteWallpapers();
sharedPreferences = getSharedPreferences("GridSize", MODE_PRIVATE);
editor = sharedPreferences.edit();
if (images != null && images.size() != 0) {
if (sharedPreferences.getInt("Index", 0) == images.size()) {
editor.putInt("Index", 0);
editor.commit();
}
Picasso.get().load(Constants.domain +
images.get(sharedPreferences.getInt("Index", 0)).getImage_url()).into(new
Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap,
Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
if (jobCancelled) {
Log.i("WallpaperJobService","Returned");
return;
}
try {
//Doing some work here
} catch (IOException e) {
e.printStackTrace();
}
Log.i("WallpaperJobService", "Job finished!");
jobFinished(params, false);
}
}).start();
}
#Override
public void onBitmapFailed(Exception e, Drawable errorDrawable)
{
Log.i("WallpaperJobService", "Bitmap load failed " +
e.getMessage());
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
} else {
Log.i("WallpaperJobService", "Favorite database is null!");
}
}
#Override
public boolean onStopJob(JobParameters params) {
Log.i("WallpaperJobService", "Job cancelled before completion!");
jobCancelled = true;
return true;
}
}
When doing stuff periodically in the background — JobScheduler, WorkManager, AlarmManager, FCM push messages, etc. — you have to take into account that your process might not be around when it is time for you to do your work. Android will fork a process for you, but it is "starting from scratch". Anything that your UI might have set up in memory, such as a database, would have been for some prior process and might not be set up in the new process.

Cant get ProgressDialog to show up in android

I cant get a progress dialog to show when I need it to. I have tried putting it in my asyncTask the ui class and the its own thread that runs on the ui and none have worked. Can anyone help me?
the method where the progressDialog method is called:
public void shareTest(View view){ //method called to jump to share activity if criteria matched
if(checkInputs()) { //call to check inputs
Share start = new Share();
boolean isConnected=start.connectToServer(); //connectToServer
Intent intent = new Intent(HomeScreen.this, Share.class); //create intent to move to share class from this activity
startProgressDialog();
if (isConnected) { //check to see if isconnected was succesful
if (Share.matchFound ){ //check to see if a match was found
progress.dismiss();
startActivity(intent); //if true jump to share activity
} else {
while (!Share.timedOut) { //While the time has not timedOut
if (Share.matchFound) { //if a share has been found
startActivity(intent); //start share activity
break; //if true then break
}
}
if (Share.timedOut) {
//send an notice that a match wasn't found
sendToast(getString(R.string.noShare)); //if not true then send Toast
}
}
}
else sendToast(getString(R.string.errServCon)); //if connection to server failed then send toast
}
}
this is the method:
void startProgressDialog() {
new Thread(new Runnable() {
#Override
public void run() { //creates a new runnable thread
// Issue command() on a separate thread
while (!Share.matchFound) { //while havent been asked to disconnect //if a new location has been recieved
activity.runOnUiThread(new Runnable() {
#Override
public void run() { //run on the ui thread act
progress.show(); //call the method that does the update
}
});
}
progress.dismiss();
}
}).start();
}
Declare a global variable like this:
ProgressDialog progress;
Wherever you want to show the progress, paste this code:
progress = ProgressDialog.show(this, "Please wait",
"Loading..", true);
When you are done, simply dismiss it:
progress.dismiss();

How to set activity to be active all the time?

I have activity which needs to be active all the time. I have thread which sleep 10 sec, and monitors values taken from database, compare them and start method. I'm wondering if user go back to other applications and activities, does my activity and thread still work, or they are handled by activity manager and go to pause-stop-destroy?? How to stay them a live??
Thank you.
here is code for that thread:
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(10000);
myHendler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
final Calendar cal = Calendar.getInstance();
int godina2 = cal.get(Calendar.YEAR);
int mesec2 = cal.get(Calendar.MONTH);
int dan2 = cal.get(Calendar.DAY_OF_MONTH);
int sati2 = cal.get(Calendar.HOUR_OF_DAY);
int minuti2 = cal.get(Calendar.MINUTE);
trenutniDatum = new StringBuilder().append(dan2).append("-").append(mesec2 +1).append("-").append(godina2);
trenutnoVreme = prepraviVreme(sati2) + ":" + prepraviVreme(minuti2);
for(int i = 0; i < primljenoIzBazeDatum.length; i++){
String bazaBroj = "";
String bazaText = "";
if(primljenoIzBazeDatum[i].toString().equals(trenutniDatum.toString()) && primljenoIzBazeVreme[i].toString().equals(trenutnoVreme)){
int bazaId = Integer.parseInt(primljenoIzBazeId[i]);
bazaBroj = primljenoIzBazeBroj[i].toString();
bazaText = primljenoIzBazeText[i].toString();
String datumPromena = "*" + primljenoIzBazeDatum[i].toString() + "* SENT *";
datumVreme.open();
datumVreme.updateData(bazaId, datumPromena);
datumVreme.close();
sendPoruka(bazaBroj, bazaText);
}
} // end for
} // end run
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
Based on my understanding of what you want to do, here is what I would do :
First, create a BroadcastReceiver
public class Poller extends BroadcastReceiver {
private final String TAG = "Poller";
#Override
public void onReceive( Context context, Intent intent ) {
Log.i(TAG, "Poller broadcastintent received");
Intent myIntent = new Intent( context, PollerService.class );
context.startService( myIntent );
}
then , create the service that is called and then shuts itself down
public class PollerService extends Service {
final String TAG = "PollerService";
#Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "Service onStart()");
pollingTask.execute();
}
AsyncTask<Void, Void, Void> pollingTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... param) {
// Do what you want in the background
}
#Override
protected void onPostExecute(Void result) {
stopSelf();
}
};
}
then, set an AlarmManager to wake the service every minute
AlarmManager am = ( AlarmManager ) getSystemService( Context.ALARM_SERVICE );
Intent alarmIntent = new Intent( "CHECK_DATABASE" );
PendingIntent pi = PendingIntent.getBroadcast(context, 0 , alarmIntent, 0 );
int type = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long interval = POLLING_INTERVAL_IN_MILLISECONDS;
long triggerTime = SystemClock.elapsedRealtime() + interval;
// For short intervals setInexact repeating is same as exactRepeating, use at least fifteen minutes to make it more efficient
am.setInexactRepeating( type, triggerTime, interval, pi );
Log.i(TAG, "Set inexact alarm through AlarmManager");
}
setup the receiver in Android manifest
<receiver android:name="Poller">
<intent-filter>
<action android:name="CHECK_DATABASE"/>
</intent-filter>
</receiver>
finally, unset the AlarmManager to stop polling once your required SMS is received
AlarmManager am = ( AlarmManager ) getSystemService( Context.ALARM_SERVICE );
Intent intent = new Intent( "CHECK_DATABASE" );
PendingIntent pi = PendingIntent.getBroadcast( context, 0 , intent, 0 );
am.cancel(pi);
I do think that Peter is right though and this will kill you battery unless you'll only be checking until you get the required info and then don't poll and that's a short time.
Also, if you can get the exact time when you want to send the SMS with a single call from the database you can just set up the AlarmManger to wake up the service at that time, perform the action and be done with it. That would be the best approach (I can't quite make out if that is the case from you code but it does seems to be from you comments).
No, no application code on Android is not guaranteed to run all the time. Android OS can kill off aplications and services any time it feels it needs to.
Your best bet to periodically execute code would be to use AlarmManager, which makes your code execute periodically. Also a proper flag must be set to execute your code when device is asleep.
Note, since your period is very short (10s), it would keep CPU running all the time, draining the batterry very quickly.
If it has to be active all the time you have to use a Service: http://developer.android.com/guide/topics/fundamentals/services.html
I'm wondering if user go back to other applications and activities,
does my activity and thread still work, or they are handled by
activity manager and go to pause-stop-destroy?? How to stay them a
live??
They won't be kept "alive". If the system needs the resources your activity is destroyed. If you want to keep things running in the background even after your app is finished you have to use a Service.
In Java language you can scheduling your programs by traditional way:
java.util.Timer
java.util.TimerTask
for more information you can see:
http://enos.itcollege.ee/~jpoial/docs/tutorial/essential/threads/timer.html
http://www.ibm.com/developerworks/java/library/j-schedule/index.html
but better practice is using a scheduling framework such as Quartz, you can see http://www.quartz-scheduler.org/.
Spring framework also integration with Quartz framework.

Categories

Resources