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.
Related
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
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 want to notify user of mobile as particular event take place,Using notification bar icon.
Is there any way to do the same?
use this method where you required.its worked for me properly.
Hope it will solve your problem.
private void notification(Context c)
{
// TODO Auto-generated method stub
EfficientAdapter1 e1=new EfficientAdapter1(c);
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) e1.no(ns);
//int icon = R.drawable.xyz;//your image
CharSequence tickerText = "ticker text";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, Text, when);
Context context = c;
CharSequence contentTitle = "your title";
CharSequence contentText = " your text";
Intent notificationIntent = new Intent(context, ViewAllSMS.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
final int HELLO_ID = 1;
notification.flags = Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(HELLO_ID, notification);
}
Use the Android NotificationManager (http://developer.android.com/reference/android/app/Notification.html)
Refer the app dev guide example - http://developer.android.com/guide/topics/ui/notifiers/notifications.html
After setting the required properties and calling the notify method, the status bar would show up the notification which you require.
Omkar Ghaisas
You can always go for pop ups. they are neat and gives you chance to notify the user. Other wise you can use toast also. Just the problem in toast is that it appears for some time and then disappears, so if somehow user misses that toast he may never know about toast. or say notification. You can see example here
from my service I send (with "ongoing" ID = 0) ongoing notification and it seems that there is no way of clearing it from code. if I send other notifications to the same ID (0), icon and intents
will update :/
I dont know if this is a bug in API 7 but it just dont make sens to me.
when I sent notification with Notification.FLAG_ONLY_ALERT_ONCE with different ID(ex. 1) then it is classified as simple notification and I could easily clear it from expanded menu or from code. BUT just by sending same notification to previous ID (0) it is classified as ongoing and I cannot cancel it anyhow!
I also tried to save reference to "ongoing" notification and then re-notify it with other PendingIntent and/or flags but it has no effect!
my current code of the service
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "start notification");
startStatusBarNotification();
//do other stuff
// We want this service to continue running until it is explicitly stopped, so return sticky.
return START_STICKY;
}
private void startStatusBarNotification()
{
Log.d(TAG, "startStatusBarNotification.");
final int icon = R.drawable.stbar_icon_fail;
final long when = System.currentTimeMillis();
final Notification notification = new Notification(icon, getString(R.string.notify_title), when);
final Intent notificationIntent = new Intent(this, MyActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, getString(R.string.notify_title), expandText, contentIntent);
notification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;//| Notification.FLAG_NO_CLEAR
Log.d(TAG, "notify send.");
final NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(SERVICE_ONGOING_NOTIFICATION_ID, notification);//ID = 0
}
#Override
public void onDestroy()
{
Log.d(TAG, "clear status bar notification.");
cancelNotification();
super.onDestroy();
}
private void cancelNotification()
{
final int icon = R.drawable.stbar_icon_exit;
final long when = System.currentTimeMillis();
final Notification notification = new Notification(icon, getString(R.string.notify_title), when);
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, null, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, getString(R.string.notify_stopping_title), getString(R.string.notify_stopping_text), contentIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
final NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(SERVICE_ONGOING_NOTIFICATION_ID); //NOTHING HAPPENS
mNotificationManager.notify(SERVICE_ONGOING_NOTIFICATION_ID, notification); //ID = 0 but if this was changed to 1 cancel notification can be cleared :/
}
I can see "exit" icon so onDestroy and cancelNotification are called, i have no idea what im doing wrong
It does not appear that you can successfully cancel ongoing notifications with ID 0: you will probably have to use a non-zero notification id.
The core notification manager service code is here, which doesn't appear to have a specific restriction on the choice of notification ID but everyone else who uses ONGOING notifications (for example, the Phone application) uses non-zero IDs.
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.