I've got an interesting (well, to me at least) issue:
I have a notification which I pop up in my app as needed. everything works great on my Galaxy S II (epic touch 4g from sprint, since there are so different models of the S II out there, I feel I need to be specific), and the notification word wraps with no problem - for example:
this is a notification, but it's too long,
so it'll show this second line on it's own.
To my horror, I realized that some android phones did NOT auto word wrap, and in fact simply cut my notification at the end of their screen, so the above message would show up as:
this is a notification, but it's too long,
obviously, this won't do. so, what can I do to make sure the entire message always shows up?
Rewrite
As we discussed before you want to force the Notifcation's tickerText to word wrap. One approach is to break the text into lines of the appropriate length and send out a notification for each one:
public class Example extends Activity {
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v("Example", "Alarm received");
sendNotification();
}
}
AlarmManager alarmManager;
NotificationManager notificationManager;
AlarmReceiver alarmReceiver = new AlarmReceiver();
Notification notification = new Notification();
Intent notificationIntent;
PendingIntent pendingIntent;
int tickerIndex = 0;
List<String> tickerTexts = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Determine the screen width and density, split tickerText appropriately
String tickerText = "A tickerText that is long enough to cause a word wrap in portrait.";
tickerTexts.add(tickerText.substring(0, 35));
tickerTexts.add(tickerText.substring(35));
notificationIntent = new Intent(this, Example.class);
pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.flags = Notification.FLAG_ONLY_ALERT_ONCE;
notification.icon = android.R.drawable.star_on;
sendNotification();
registerReceiver(alarmReceiver, new IntentFilter("Generic"));
}
#Override
protected void onDestroy() {
unregisterReceiver(alarmReceiver);
super.onDestroy();
}
public void sendNotification() {
Log.v("Example", "Send Notification " + tickerIndex);
notification.tickerText = tickerTexts.get(tickerIndex);
notification.setLatestEventInfo(this, "Title", "Text " + tickerIndex, pendingIntent);
notificationManager.cancel(0);
notificationManager.notify(0, notification);
tickerIndex++;
if(tickerIndex < tickerTexts.size()) {
Log.v("Example", "Setting up alarm");
PendingIntent alarmPending = PendingIntent.getBroadcast(this, 0, new Intent("Generic"), 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000, alarmPending);
}
}
}
However you can see I skipped an integral part of the set up: I assumed the length of the text that would fit, I didn't calculate it. In order to determine an appropriate break point you need to calculate the screen's width, the font's scaled size, and the density. You also would need factor in the fact that "!!!" might be shorter than "www" depending on the font and that the user could switch between landscape and portrait... You could look in the source code to see how a generic Android breaks up the tickerText.
Anyway, forcing a tickerText to word wrap might be more complex than condensing your original String or sending angry letters to the "non-wrapping" phone manufacturers.
Related
I have a kind of weird problem. I know that I am missing something but I don't know what.
I am adding approximatly 5 notifications per day that I create each two to three hours.
If we have the scenario below:
Notification 1 is created at 8:00 and should be fired at 12:00.
When Notification 1 is received, it is processed and Notification 2 is created and needs to be fired at 14:00.
When Notification 2 is received, it is processed and Notification 3 is created and should be fired at 17:00
When Notification 3 is received, it is processed and Notification 4 is created and should be fired at 8:00 the next Day.
Notification 4 will not be received until I manually unlock/unsleep the phone. The time of the notification is 8:00 even if I unlocked the phone at 9:00.
So my problem is when the phone goes to sleep for a long time, the notifications are not processed until I manually pressed the wake button on my Samsung S7. Also, I am playing a media each time the notification is received thru a Service. For Notification 4 the media does not play until I manually wake the phone. Also, I have some style applied to the content, It displays correctly for Notification 1,2 and 3 but not on Notification 4.
I thought that maybe when I am creating Notifications for the next day, there is a problem registering them so I tried to play with my date manually and everything works ok.
This is how I create my Notification:
public Notification getNotification(String notificationName, long notificationTime) {
Intent intent = new Intent( context, NotificationPlayerService.class );
intent.setAction( NotificationPlayerService.ACTION_STOP );
PendingIntent pendingIntent = PendingIntent.getService(context, 1, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentTitle("Notification");
builder.setContentText(notificationName);
builder.setSmallIcon(R.drawable.icon);
builder.setColor(ContextCompat.getColor(context, R.color.teal_500));
builder.setLights(Color.GREEN, 3000, 3000);
builder.setVibrate(new long[]{0,750});
builder.setWhen(notificationTime);
builder.setShowWhen(true);
Uri sound= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(sound);
builder.setDeleteIntent(pendingIntent);
return builder.build();
}
And this is how I schedule them:
#SuppressLint("NewApi")
public void scheduleNotification(Notification notification, long notificationTime, String action, int id) {
Intent notificationIntent = new Intent(context, NotificationPublisher.class);
notificationIntent.setAction(action);
if(id!=-1){
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, notification);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, id);
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT > 19) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, notificationTime, pendingIntent);
}
}
This is how I receive them:
public void onReceive(Context context, Intent intent) {
this.context = context;
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String action = intent.getAction();
int id = intent.getIntExtra(NOTIFICATION_ID, -1);
Log.e("NOTIFICATION_RECEIVER","Notification received " + action +"-"+ id);
if(id != -1){
Notification notification = intent.getParcelableExtra(NOTIFICATION);
notificationManager.notify(id, notification);
}
Intent serviceIntent = NotificationService.startNotificationService(context);
if (serviceIntent != null) {
startWakefulService(context, serviceIntent);
}
}
And Finally I am using an IntenService to create my notifications:
#Override
protected void onHandleIntent(Intent intent) {
try{
startNotifications();
}
finally {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
}
}
startNotification uses methods getNotification and scheduelNotification shown above. Basically it gets some settings from SharedPreferences and calculates when the notifications should be fired.
Thank you
In my android application, I want to generate a notification when current time matches with the time that I have retrieved from my database. And the notification should be generated even if the application is not running. For this I have done something like this, but this is not working (no notification is being generated).
I am new to android, and I have seen many examples and tutorials for solving this issue, but they did not helped. So please give Answer that what should I do for getting the desired result?
In MainActivity.java I am doing this:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*here I am retrieving time from database*/
String time_from_database = "20:00:00";
if(Calendar.getInstance()==time_from_database) {
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(MainActivity.this, NotGen.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
alarmMgr.set(AlarmManager.RTC, Calendar.getInstance(), alarmIntent);
}
}
}
this is code of NotGen.java class:
public class NotGen extends BroadcastReceiver {
public NotificationCompat.Builder mBuilder;
#Override
public void onReceive(Context context, Intent intent) {
PendingIntent pIntent = PendingIntent.getActivity(context,0,intent,0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
mBuilder.setTicker("Ticker Title");
mBuilder.setSmallIcon(R.drawable.my_img);
mBuilder.setContentTitle("Notification Alert, Click Me!");
mBuilder.setContentText("Hi, This is Android Notification Detail!");
mBuilder.setContentIntent(pIntent).getNotification();
mBuilder.setAutoCancel(true);
mBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mBuilder.setSound(alarmSound);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0,mBuilder.build());
}
}
Calendar.getInstance()==time_from_database will never work.
First, getInstance() is going to create a new instance, and == is object identity equality.
Second, time_from_database is a String ("20:00:00"). A Calendar instance will never equal that, if for no other reason than a Calendar is a combination of date and time.
You can achieved it using Service. Service will running in background all the time even your application is not running.
1) Create service and register it into Manifest file.
2) Start it on application start.
3) Into service you can generating your notification when current time will matched with database time.
For service example you can see below links
http://javatechig.com/android/android-service-example
http://www.tutorialspoint.com/android/android_services.htm
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 using some alarm functions to produce a notification every five seconds. In the functions there are variables which should change each time it is called. But nothing is happening , it just continues to display the first set of data in the notification.
This is from the MainActivity class:
public void setRepeatingAlarm(){
Intent intent = new Intent(this, TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (5 * 1000), pendingIntent);
}
This is from the TimeAlarm class:
public void onReceive(Context context, Intent intent) {
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Homework";
CharSequence message = "test"+ MainActivity.arraytest[x2]+ x2;
x2 +=1;
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,new Intent(context,TimeAlarm.class), 0);
Notification notif = new Notification(R.drawable.ic_launcher,"Update", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
nm.notify(notify_id, notif);
}
The problem is that the x2 variable is not updating. it only updates when it is first called.
Thanks.
Making the x2 variable static seemed to solve the problem.
Maybe long shot but... I suspect that x2 may be accessed by more than one threads? In that case, it should be declared as volatile in order for compiler to skip any optimizations not suitable for variables accessed by multiple threads (which can be causing the wrong behaviour in this case).
Are you doing anything else with x2? Have a look at the lifecycle documentation for BroadcastReciever. Likely your instance of TimeAlarm is getting killed after each run of onReceive(); you'll need to do something to persist the value of x2 between runs.
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.