I am making an application in android using eclipse IDE and i want to implement a notification in my android i want to make the notification on button click example i want to notify saved data..i found this tutorial here i copied the code and paste it in my setOnClickListener code..but im getting error..i dont know how to start doing this because in the tutorial they just give you the code snippet..this is my code
UPDATE QUESTION
what is the difference between notification and push notification and which is better to use..
submit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
mNotifyManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
#Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr <= 100; incr+=5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(5*1000);
} catch (InterruptedException e) {
Log.d(TAG, "sleep failure");
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
mNotifyManager.notify(ID, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
}
});
You should change this
mBuilder = new NotificationCompat.Builder(this);
to
mBuilder = new NotificationCompat.Builder(youractivity.this);
You need to pass current Context for creating mBuilder object.
Related
Currently, if our device connected to WiFi, WhatsApp will perform sync to cloud, by showing a progress bar in notification area.
I was wondering, how can I achieve so using WorkManager? Currently, I know I can setup specific constraint, for WorkManager to run a background job.
Delayed time
Network constraint
But, how can we show a notification UI, via WorkManager?
Here is something which i have in my mind that can help.
The idea is to create a worker and put your logic to get the progress and show updates as a notification using handler.
NOTE : This code is not tested and i am using it just to explain the way
Worker Code
public class CompressWorker extends Worker {
public CompressWorker(#NonNull Context context, #NonNull WorkerParameters params) {
super(context, params);
}
#NonNull
#Override
public Result doWork() {
ProgressManager manager = new ProgressManager();
int i = 0;
while(i<100){
i++;
try {
Thread.sleep(1000);
manager.updateProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i("Ansh", "worker's job is finished");
// Indicate success or failure with your return value:
return Result.success();
// (Returning Result.retry() tells WorkManager to try this task again
// later; Result.failure() says not to try again.)
}}
And there is another class using the handler to send the updates to the notification
public class ProgressManager {
Context context;
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
Handler handler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
context);
notificationBuilder.setProgress(100, msg.arg1, true);
Notification notification = notificationBuilder.build();
notificationManagerCompat.notify(1000, notification);
}
};
public void updateProgress(int val) {
Message msg = new Message();
msg.arg1 = val;
handler.sendMessageDelayed(msg, 1000);
}}
I have followed tutorial in http://developer.android.com/training/notify-user/index.html
It works well. But what I want is : when I click ping, the old service will we stopped, and then create the service again. So if I clicked id multiple time, It will notify me only once.
Problem: If I set time 10, then I click "Ping" button. Then after 5 second, I click it again. It will notify me twice.
What I want : If I set time 10, then I click "Ping" button. Then after 5 second, I click it it will notify only once, 10 secondds after the last time I click the button.
public class MainActivity extends Activity {
private Intent mServiceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Creates an explicit Intent to start the service that constructs and
// issues the notification.
mServiceIntent = new Intent(getApplicationContext(), PingService.class);
}
/*
* Gets the values the user entered and adds them to the intent that will be
* used to launch the IntentService that runs the timer and issues the
* notification.
*/
public void onPingClick(View v) {
stopCurrentService();
int seconds;
// Gets the reminder text the user entered.
EditText msgText = (EditText) findViewById(R.id.edit_reminder);
String message = msgText.getText().toString();
mServiceIntent.putExtra(CommonConstants.EXTRA_MESSAGE, message);
mServiceIntent.setAction(CommonConstants.ACTION_PING);
Toast.makeText(this, R.string.timer_start, Toast.LENGTH_SHORT).show();
// The number of seconds the timer should run.
EditText editText = (EditText) findViewById(R.id.edit_seconds);
String input = editText.getText().toString();
if (input == null || input.trim().equals("")) {
// If user didn't enter a value, sets to default.
seconds = R.string.seconds_default;
} else {
seconds = Integer.parseInt(input);
}
int milliseconds = (seconds * 1000);
mServiceIntent.putExtra(CommonConstants.EXTRA_TIMER, milliseconds);
// Launches IntentService "PingService" to set timer.
startService(mServiceIntent);
}
private void stopCurrentService() {
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager
.getRunningServices(Integer.MAX_VALUE);
if (serviceList.size() <= 0) { }
int size = serviceList.size();
for (int i = 0; i < size; i++) {
RunningServiceInfo serviceInfo = serviceList.get(i);
ComponentName serviceName = serviceInfo.service;
if (serviceName.getClassName().equals(PingService.class.getName())) {
try {
Intent intentstop = new Intent();
intentstop.setComponent(serviceName);
getApplicationContext().stopService(intentstop);
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
}
}
PingService creates a notification that includes 2 buttons: one to snooze the
notification, and one to dismiss it.
public class PingService extends IntentService {
private NotificationManager mNotificationManager;
private String mMessage;
private int mMillis;
NotificationCompat.Builder builder;
private boolean status;
public PingService() {
// The super call is required. The background thread that IntentService
// starts is labeled with the string argument you pass.
super("com.example.android.pingme");
}
#Override
protected void onHandleIntent(Intent intent) {
// The reminder message the user set.
mMessage = intent.getStringExtra(CommonConstants.EXTRA_MESSAGE);
// The timer duration the user set. The default is 10 seconds.
mMillis = intent.getIntExtra(CommonConstants.EXTRA_TIMER,
CommonConstants.DEFAULT_TIMER_DURATION);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String action = intent.getAction();
// This section handles the 3 possible actions:
// ping, snooze, and dismiss.
if (action.equals(CommonConstants.ACTION_PING)) {
issueNotification(intent, mMessage);
} else if (action.equals(CommonConstants.ACTION_SNOOZE)) {
nm.cancel(CommonConstants.NOTIFICATION_ID);
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.snoozing));
// Sets a snooze-specific "done snoozing" message.
issueNotification(intent, getString(R.string.done_snoozing));
} else if (action.equals(CommonConstants.ACTION_DISMISS)) {
nm.cancel(CommonConstants.NOTIFICATION_ID);
}
}
private void issueNotification(Intent intent, String msg) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Sets up the Snooze and Dismiss action buttons that will appear in the
// expanded view of the notification.
Intent dismissIntent = new Intent(this, PingService.class);
dismissIntent.setAction(CommonConstants.ACTION_DISMISS);
PendingIntent piDismiss = PendingIntent.getService(this, 0,
dismissIntent, 0);
Intent snoozeIntent = new Intent(this, PingService.class);
snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
PendingIntent piSnooze = PendingIntent.getService(this, 0,
snoozeIntent, 0);
// Constructs the Builder object.
builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_notification)
.setTicker("Ping ! ping ! PIng!")
.setContentTitle(getString(R.string.notification))
.setContentText(getString(R.string.ping))
.setDefaults(Notification.DEFAULT_ALL)
// requires VIBRATE permission
/*
* Sets the big view "big text" style and supplies the text (the
* user's reminder message) that will be displayed in the detail
* area of the expanded notification. These calls are ignored by
* the support library for pre-4.1 devices.
*/
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.addAction(R.drawable.ic_stat_dismiss,
getString(R.string.dismiss), piDismiss)
.addAction(R.drawable.ic_stat_snooze,
getString(R.string.snooze), piSnooze);
/*
* Clicking the notification itself displays ResultActivity, which
* provides UI for snoozing or dismissing the notification. This is
* available through either the normal view or big view.
*/
Intent resultIntent = new Intent(this, ResultActivity.class);
resultIntent.putExtra(CommonConstants.EXTRA_MESSAGE, msg);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Because clicking the notification opens a new ("special") activity,
// there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
startTimer(mMillis);
}
// Starts the timer according to the number of seconds the user specified.
private void startTimer(int millis) {
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.timer_start));
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.sleep_error));
}
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.timer_finished));
issueNotification(builder);
}
private void issueNotification(NotificationCompat.Builder builder) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Including the notification ID allows you to update the notification
// later on.
mNotificationManager.notify(CommonConstants.NOTIFICATION_ID,
builder.build());
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
I have called stopService(), but the old notification shows up again.
What I want is it will notify me once, 10 seconds after the latest click.
You can use handler in order to stop/start your service.
Please look at my code. It's not exactly related to your code but you can get the idea.
Click this link
You can do checking in Run method of Runnable.
here is my code :
public class MainActivity extends Activity {
private NotificationManager mNotifyManager;
private NotificationCompat.Builder mBuilder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
}
public void click(View view) {
noti();
}
private void noti() {
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_launcher);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
#Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr <= 100; incr+=5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
mNotifyManager.notify(0, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
}
}
it works fine on android 4.2.2 device , but when I tried to run it on an android 2.2 device , the notification didn't show up,and I got the following logs:
RuntimeException in notify -
java.lang.Throwable: stack dump
at android.app.NotificationManager.notify(NotificationManager.java:118)
at android.app.NotificationManager.notify(NotificationManager.java:92)
at com.gyh.notitest.MainActivity$1.run(MainActivity.java:49)
at java.lang.Thread.run(Thread.java:1019)
can anyone help me ? how can I display a progress bar in a Notification on android 2.2 devices without custom layout?
thanks!
Never mind..
I change my code to:
public class MainActivity extends Activity {
private NotificationManager mNotifyManager;
private NotificationCompat.Builder mBuilder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(
getApplicationContext()).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(resultPendingIntent);
}
public void click(View view) {
noti();
}
private void noti() {
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
#Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr <= 100; incr+=5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
mNotifyManager.notify(0, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
}
}
Then there came the Notification , But no progress T_T There is nothing I can do about it .. the only way I can think of right now is a custom layout with a progress bar...
Have you tried import the v4.jar library to your project? It supports features of new api version running on low api ( Android 2.2 for instance).
Cheers,
I re-wrote your code to enable multiple Notification Progress. Also updated to work on android Oreo+
class MainActivity : AppCompatActivity(){
private var mNotifyManager: NotificationManagerCompat? = null
private var mBuilder: NotificationCompat.Builder? = null
private var notificationId = 0
val CHANNEL_ID ="download_progress_notification"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mNotifyManager = NotificationManagerCompat.from(this)
mBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
}
private fun noti(notficationId : Int) {
mBuilder?.setContentTitle("Picture Download")
?.setContentText("Download in progress")
?.setSmallIcon(R.mipmap.ic_launcher)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // you must create a notification channel for API 26 and Above
val name = "my channel2"
val description = "channel description2"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = 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
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(channel)
}
// Start a lengthy operation in a background thread
Thread(object : Runnable{
override fun run() {
var incr: Int
// Do the "lengthy" operation 20 times
incr = 0
while (incr <= 100) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder?.setProgress(100, incr, false)
// Displays the progress bar for the first time.
mNotifyManager?.notify(notficationId, mBuilder!!.build())
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep((1 * 1000).toLong())
} catch (e: InterruptedException) {
e.printStackTrace()
}
incr += 5
}
// When the loop is finished, updates the notification
mBuilder?.setContentText("Download complete")
// Removes the progress bar
?.setProgress(0, 0, false)
mNotifyManager?.notify(notficationId, mBuilder!!.build())
}
}).start()
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.menu_option -> {
noti(notificationId++)
return true
}
}
return super.onOptionsItemSelected(item)
}
}
When closing an application with back or homescreen button, app showing a webview closes.
On returning back to the app, it load the page all over again.
More specifically, the page this app loads contains an upload button. File upload takes some time depending on the internet speed. If the used starts uploading and goes to other app, the upload progress will be lost and on revisiting the app, the page will load all over again.
What to do to make upload in VebView work in background. Giving a notification of "upload in progress..." in notification area will be an added benefit. Suggest what to do and how?
You should do the upload in a Service, instead of in a Activity. (Lookup IntentService for example, which will shut itself down after upload)
here is sample code of service just edit is as per your need:
i have create one service and call it from my activity using:
startService(new Intent(MainActivity.this, TempServices.class));
here is my service class
package com.example.uploadfile;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log;
public class TempServices extends Service {
protected static final int ID = 100;
private NotificationManager mNotifyManager;
private Builder mBuilder;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
mNotifyManager = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_launcher);
// Start a lengthy operation in a background thread
new Thread(new Runnable() {
#Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr <= 100; incr += 5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
Log.e("error-->", "sleep failure");
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0, 0, false);
mNotifyManager.notify(ID, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
return super.onStartCommand(intent, flags, startId);
}
}
for counting progress check this link
do not forgate to add this service in android manifes:
<service android:name="TempServices" >
I am having a hard time figuring out how to display the current time every fixed time interval in the status bar using service with its own thread. The following code allows me to display the current time when I click the start service button (there is also a stop service button) but it does not display the current time again. I suspect some sort of loop or timer is needed or perhaps my thread sleep mechanism is not correct. Please hint or suggest a solution. The run method is where help is needed (first). Thanks much in advance!
public class MyOwnService extends Service {
// Use a layout id for a unique identifier
private static int TIME_NOTIFICATIONS = R.layout.status_bar_notifications;
// variable which controls the notification thread
private ConditionVariable mCondition;
private NotificationManager mNM;
// Create Runnable object
private Runnable mTask = new Runnable() {
public void run() {
try{
SimpleDateFormat sdfDate = new SimpleDateFormat("hh:mm:ss");
Date now = new Date();
String strDate = sdfDate.format(now);
showNotification(R.drawable.icon, strDate);
Thread.sleep(30000);
} catch (Exception e) {
}
// Show happy face for 5 seconds
//showNotification(R.drawable.icon, strDate);
//mCondition.block(5 * 1000);
// Done with our work... stop the service!
//MyOwnService.this.stopSelf();
}
};
#Override
public void onCreate() {
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
/// Start up the thread running the service. Note that we create a
/// separate thread because the service normally runs in the process's
/// main thread, which we don't want to block.
Thread notifyingThread = new Thread(
null, // Thread group
mTask, // Runnable object
"NotifyingService"); // Thread name
mCondition = new ConditionVariable(false);
notifyingThread.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel(MOOD_NOTIFICATIONS);
// Stop the thread from generating further notifications
mCondition.open();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private void showNotification(int timeId, String strTime) {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = strTime;
// Set the icon, scrolling text and time stamp.
// Note that in this example, we pass null for tickerText. We update the
// icon enough that
// it is distracting to show the ticker text every time it changes. We
// strongly suggest
// that you do this as well. (Think of of the "New hardware found" or
// "Network connection
// changed" messages that always pop up)
Notification notification = new Notification(timeId, text, System
.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, ServiceLauncher.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this,
getText(R.string.status_bar_notification_title), text,
contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to
// cancel.
mNM.notify(TIME_NOTIFICATIONS, notification);
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new Binder() {
#Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
}
Run() is not a loop. You need to wrap your code in a while loop.
You also want to add a way to stop that thread gracefully so in your while loop you should check a variable that can be set from the main thread. ie
while(!stopped){ ... }
then add this to your onDestory()
mTask.stopped = true;