My app has an option to download a file. It works in this way:
Activity -> IntentService -> AsyncTask (here the file is downloading). Additionally, I use a notification to show progress in percents, and here is my problem: everything works well e.g. on Android 2.3, but on Android 4.2 or 5.0, the UI is blocked.
Earlier I had a bug in my code (I updated the progress bar in a loop every time), and now when I update it only when oldProgress != actualProgress, it works well (100+ operations instead of 2000+). But why does it work well on Android 2.3 even with 2000+ operations?
Here is my notification class:
public class NotificationProgressHelper {
private static final int DOWNLOAD_PROGRESS_NOTIFICATION_ID = 1;
private Context mContext;
private Notification mNotification;
private NotificationManager mNotificationManager;
private PendingIntent mContentIntent;
private CharSequence mContentTitle;
public NotificationProgressHelper(Context context) {
mContext = context;
}
public void createNotification() {
mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
int icon = R.drawable.download_icon;
CharSequence contentName = mContext.getString(R.string.notification_content_name);
mNotification = new Notification(icon, contentName, System.currentTimeMillis());
mContentTitle = mContext.getString(R.string.notification_title);
CharSequence contentText = mContext.getString(R.string.notification_percent_completed, 0);
//pending intent left blank till the whole apk file will be downloaded
Intent notificationIntent = new Intent();
mContentIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
mNotification.setLatestEventInfo(mContext, mContentTitle, contentText, mContentIntent);
mNotification.flags = Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(DOWNLOAD_PROGRESS_NOTIFICATION_ID, mNotification);
}
public void progressUpdate(int percentageComplete) {
CharSequence contentText = mContext.getString(R.string.notification_percent_completed, percentageComplete);
mNotification.setLatestEventInfo(mContext, mContentTitle, contentText, mContentIntent);
mNotificationManager.notify(DOWNLOAD_PROGRESS_NOTIFICATION_ID, mNotification);
}
public void completed() {
mNotificationManager.cancel(DOWNLOAD_PROGRESS_NOTIFICATION_ID);
}
public void removeDownloadSuccessNotification() {
mNotificationManager.cancel(ApplicationConstants.NotificationID.APP_UPDATE_NOTIFICATION_ID);
}
The downloadFile method is called in doInBackground(), of course.
I know this code is old and now I should use the builder but I tried and it does not concern the problem.
Am I doing something wrong? Why does the version with all operations work well on Android 2.3? I think it works on the main thread but why?
After Donut and till Honeycomb (1.6 – 3.0) till Version 3.0
it uses multiple AsyncTask in parallel by default so may be that is the reason why its working fine..
detailed explanation regarding the same can be reffered in, https://stackoverflow.com/a/36078608/2249287
Related
I make one android application.In my code in my java class I get some message: "The constructor Notification(int, CharSequence, long) is deprecated". Everything is ok with Application I don't have problem when I try to run the Application.
I just want to know why this message is showing up.
My code in my java class is:
public class Notifications extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.notifications);
Button b = (Button) findViewById(R.id.bNotifications);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notify = new Notification(
android.R.drawable.stat_notify_more,
"This is important", System.currentTimeMillis());
Context context = Notifications.this;
CharSequence title = "You have been notified";
CharSequence details = "Continue with what you have doing";
Intent intent = new Intent();
PendingIntent pending = PendingIntent.getActivity(context, 0,
intent, 0);
notify.setLatestEventInfo(context, title, details, pending);
nm.notify(0, notify);
}
});
}
}
Have a look at the documentation:
public Notification (int icon, CharSequence tickerText, long when)
Added in API level 1
This constructor was deprecated in API level 11.
Use Notification.Builder instead.
As far as I can tell, this would be the corresponding call to Notification.Builder:
Context context = Notifications.this;
Notification notify = new Notification.Builder(context)
.setTicker("This is important")
.setSmallIcon(android.R.drawable.stat_notify_more)
.setWhen(System.currentTimeMillis())
.build();
As you can see, Notification.Builder offers more flexibility in setting the various notification properties and improves code readability, which might be the reason why the Notification constructor was deprecated.
Sometimes the fact that a method is deprecated doesn't mean that you won't need it nor make use of it. So, after all, you need to support older devices (not the oldest like Android Donut or previous) and you will need to use the new way and the deprecated way. In this case, I've implemented as follows:
Notification notification;
String title = context.getString(R.string.app_name);
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN){
notification = new Notification(icon, message, when);
}else{
notification = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.drawable.ic_launcher)
.build();
}
Hope that it helps!
Since API level 11 Notification(int icon, CharSequence tickerText, long when) is no longer advised to be used as there exists an alternative to this. Use Notification.Builder instead.
Source: http://developer.android.com/reference/android/app/Notification.html#Notification(int, java.lang.CharSequence, long)
Ok I saw a lot of people just dismiss this question by saying
"it's reserved for OS component "
"it requires access to source"
Well I have access to the source and I can set any app or widget I want as a system app. So now how would I go about making my widget show its notification on the right side?
EDIT:
ok ppl are going in the wrong direction so ill add come context here . . .
look at ur phone . . . u see Wi-Fi signal and phone signal on the right side of the phone all the time right. I want my signal to be shown there aswell . . . along with the system signals . . I have a new hardware chip in the tablet my company is making and I have to display its signal strength constantly just like the phone signal. It is going to be integrated into the Android source of the tablet.
You might need to refer to the code of Android source code of phone status bar, at https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r3.1/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
And take a look at the methods like
addIcon
updateIcon
removeIcon
It is not easy task since you have to add lots of stuff by yourself.
You'll need to modify a few places:
framework/base/core/res/res/values/config.xml, add a slot in:
<string-array name="config_statusBarIcons">
then frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java:
mService.setIcon("<your slot name>", R.drawable.yourlogo, 0, null);
mService.setIconVisibility("<your slot name>", setVisible);
That's mostly it, I'm sure you can figure out the rest on your own with some trial and errors.
I have one easy idea ie:
In manifest declare android screen orientation as landscape
and design like landscape for portrait mode
so that ur app looks portrait in landscape mode.
public class GCMIntentService extends GCMBaseIntentService {
public static final String PROJECT_ID = "4898989797";
private static final String TAG = "GCMIntentService";
ModelNotificationMessage modelNotificationMessage;
public GCMIntentService() {
super(PROJECT_ID);
Log.d(TAG, "GCMIntentService init");
}
#Override
protected void onError(Context ctx, String sError) {
// TODO Auto-generated method stub
Log.d(TAG, "Error: " + sError);
}
#Override
protected void onMessage(Context ctx, Intent intent) {
Log.d(TAG, "Message Received");
String message = intent.getStringExtra("message");
Log.d(TAG, "Message Received" + message);
sendNotification(message);
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("GCM_RECEIVED_ACTION");
broadcastIntent.putExtra("gcm", message);
ctx.sendBroadcast(broadcastIntent);
}
private void sendNotification(String message) {
// this
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.notification;
CharSequence tickerText = message; // ticker-text
long when = System.currentTimeMillis();
Context context = getApplicationContext();
CharSequence contentTitle = modelNotificationMessage.getKey();
CharSequence contentText = message;
Intent notificationIntent = null;
int NOTIFICATION_ID = 9999;
NOTIFICATION_ID = CommonVariable.notification_message;
notificationIntent = new Intent(this, ViewMessages.class);
contentText = arrayList.get(0).getDescription();
tickerText = arrayList.get(0).getDescription();
// and this
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new Notification(icon, tickerText, when);
// Play default notification sound
notification.defaults |= Notification.DEFAULT_SOUND;
notification.setLatestEventInfo(context, contentTitle, contentText,
contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
I found some related information regarding your question on this forum...
http://forum.kde.org/viewtopic.php?t=107601
--Good day
I'm working on an application to display the battery status of then phone/tablet. I have it running and working as it is, but somehow the application is 'killed' when the screen is turned off.
The strange thing is though that is is killed on my LG phone, but not on my Galaxy Tab when the screen is off/locked.
The source code is as following:
public class BatteryLevelActivity extends Activity {
private TextView batterLevel;
CharSequence tickerText = "No need to charge at the moment";
public void onCreate(Bundle SavedInstanceState) {
super.onCreate(SavedInstanceState);
setContentView(R.layout.main);
this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(
Intent.ACTION_BATTERY_CHANGED));
batterLevel = (TextView) findViewById(R.id.batteryLevel);
};
private void notif(int level) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext();
CharSequence contentTitle = "BatteryWatch";
CharSequence contentText = "Remaining charge level is " + level + "%";
Intent notificationIntent = new Intent();
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText,
contentIntent);
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
}
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent intent) {
int level = intent.getIntExtra("level", 0);
batterLevel.setText("Battery level is at " + level + "%\n\n"
+ tickerText);
notif(level);
tickerText = "";
}
};
}
Somehow I think that I should have a method that is called something like 'onScreenOff' or maybe 'onScreenOn' and then the application could be reloaded, but I'm open to suggestions as to how to keeo it running when the screen is off/locked.
Thanks in advance
You probably want to consider using a Service because you want this running long term, the developer guide here explains more. Also (although I cannot find the link) want to tell Android that it should restart your app if it has to kill it. I cannot remember exactly what this is called
** Additional Info **
I gave slightly false information in the above. I believe you can make a Service re-start after Android has killed it but NOT an Activity. In the link above for the developer guide for Service it's detailed there. It's called starting a service as sticky, see the sub-section Extending the Service Class.
I am new to android development and I try to create a background download feature for my app. I followed this http://developer.android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView to create my custom notification.
The downloading is performed, I checked the downloaded file in the sdcard. Also,the status bar icon and title are changed properly.
The problem is that the custom layout I provide for the notification does not appear (expand under the bar). Here is the related code parts inside private AsyncTask class:
#Override
protected void onPreExecute() {
// create and configure the notification
notification = new Notification(R.drawable.download, "Downloading map..", System.currentTimeMillis());
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
//create a custom layout for the notification
myContentView = new RemoteViews(appContext.getPackageName(), R.layout.download_progress);
myContentView.setImageViewResource(R.id.status_icon, R.drawable.ic_menu_save);
myContentView.setTextViewText(R.id.status_text, "download in progress");
myContentView.setProgressBar(R.id.status_progress, 100, 0, false);
notification.contentView = myContentView;
notification.contentView.apply(appContext, dl.getListView());
//instantiate the pending intent
Intent myIntent = new Intent(appContext, DownloadList.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
int requestID = (int) System.currentTimeMillis();
PendingIntent myPendingIntent = PendingIntent.getActivity(appContext, requestID, myIntent, 0);
notification.contentIntent = myPendingIntent;
//add the Notification object to the notification manager
notificationManager = (NotificationManager) appContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIF_ID, notification);
}
#Override
protected void onProgressUpdate(Integer... progress) {
//update progress bar
notification.contentView.setProgressBar(R.id.status_progress, 100, progress[0], false);
notificationManager.notify(NOTIF_ID, notification);
}
}
Note that my DownloadList class extends ListActivity.
Do I need to do something more that just "notification.contentView = myContentView;" in order to inflate the layout?
Hmm... Well I compared your code to my code that already works... and I don't see many differences... But, it is possible that one of these minor differences is important.
final Notification notification = new Notification(R.drawable.icon, "Downloading", System.currentTimeMillis());
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
notification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_progress);
notification.contentView.setImageViewResource(R.id.status_icon, R.drawable.ic_status);
notification.contentView.setTextViewText(R.id.status_text, "Downloading in progress");
notification.contentView.setProgressBar(R.id.status_progress, 100, progress, false);
Intent notificationIntent = new Intent(MainPage.mainActivity, MainPage.class);
PendingIntent contentIntent = PendingIntent.getActivity(MainPage.mainActivity, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
//getApplicationContext();
final NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(
Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_MESSAGE, notification);
First, I looked at your old code and noticed that the NOTIF_ID = 1 I'm not so sure that is a good idea because what if someone else has an ID of one. Of course I could be mistaken about that, but I just pounded in a number like 792489743 and I expect no one else would have the same number. Just a precaution I suppose.
Second, I didn't get to see if the resources were correct? What does the stack trace say? I suppose that it would've just quit out on it if there was a problem there though.
Third, I put my in its own task as Service kinda as follows
public class DownloadService extends IntentService {
//initializing code and stuff
private class DownloadTask extends AsyncTask<String, Void, Boolean> {
and I did it in the doInBackground This way if the user kills the app or what not it wouldn't kill the download.
Lastly, I've never used apply I don't personally see how it would hurt, but I haven't seen an example that uses it either.
Hope this helps some!
It was an emulator problem after all.....
It lagged when I "dragged down" the notification! I killed some CPU extensive processes on my PC resulting to a faster emulator.
Lesson learned. Leave the heavy multitasking to pros or to another PC.
I have a alarm manager which is calling an activity class named ScheduleAlert.
public class ScheduleAlert extends ActivityGroup {
private String notificationAlart, editEventid;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...........
..........
// ************* Notification ************//
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
final Notification notifyDetails = new Notification(R.drawable.icon, "Myapp", nextAlarmTime);
Context context = getApplicationContext();
CharSequence contentTitle = "Myapp";
CharSequence contentText = notificationAlart;
Intent notifyIntent = new Intent(context, MyApp.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ScheduleAlert.this, 0, notifyIntent,android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
notifyDetails.setLatestEventInfo(context, contentTitle, contentText,pendingIntent);
notifyDetails.flags = Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_AUTO_CANCEL;
notifyDetails.defaults |= Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE;
mNotificationManager.notify((int) editEventid, notifyDetails);
// ************* Notification ************//
this.finish();
}
public void onDestroy(){
super.onDestroy();
}
}
I want that the indent of MyApp activity should fire when I tap on the notification massage. At the time of notification I want just sound and vibration. But now the I am getting the sound and vibration, and also the MyApp activity is fired, which I do not want actually. What is problem in my code?
There are lots and lots of strange things with this code:
I have no idea why you are extending ActivityGroup for this code
Do not use getApplicationContext() in most circumstances, such as this one
Since this is an ActivityGroup (for whatever reason) and not a Service, it is misleading to the OS and the user to have FLAG_FOREGROUND_SERVICE
FLAG_FOREGROUND_SERVICE and FLAG_AUTO_CANCEL make little sense in combination
However, I would not expect any of this to cause MyApp to automatically start. In fact, AFAIK, there is no circumstance in which a Notification will automatically invoke its PendingIntent without the user tapping on it. I suspect that your real problem lies elsewhere.