Currently I'm setting up an alarm which when activated displays a notification to the user.
I can now set the text from my SQL to my notification but its only the first row from my database each time. Now I've come up with two possible solutions which are only theory's.
Is there a way in which each time the database is called to the notification it will move onto the next result?
As I mentioned above I'm setting an alarm and when the alarm goes off it then calls the notification. Now In my pending intent for the alarm I'm giving it a id which you can see as id is there a way of giving it to my notification ID and then setting up a statement where if the notification ID is equal to or in the list of my alarm ID's stored on my SQL then it will search for the correct text to input.
Pending Intent....
pendingIntent = PendingIntent.getBroadcast(v.getContext(), id, receiver,PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, myCalendar.getTimeInMillis(), pendingIntent);
intentArrayList.add(pendingIntent);
Broadcast....
MyDatabaseHandler myDatabaseHandler = new MyDatabaseHandler(context, null, null, 1);
Cursor cursor = myDatabaseHandler.getAllProducts();
// Information we are trying to acquire but can only get first result
String name = cursor.getString(cursor.getColumnIndexOrThrow("alarm_name"));
String date = cursor.getString(cursor.getColumnIndexOrThrow("alarm_date"));
// Alarm ID FROM SQL which we want to match with the NOTIFICATION ID.....
String alarm_request_code = cursor.getString(cursor.getColumnIndexOrThrow("alarm_code"));
////
Log.i("The reciever is working", "perfect");
//create an intent to service
Intent service_Intent = new Intent(context, MessageService.class);
context.startService(service_Intent);
//Notification
NotificationManager notificationManager = (NotificationManagercontext.getSystemService(context.NOTIFICATION_SERVICE);
Intent moveActivity = new Intent(context, AlarmActivity.class);
moveActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Works with moveActivity to move the user back to main application.
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,moveActivity, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setContentTitle(name)
.setContentText(date)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true);
notificationManager.notify(Integer.valueOf(alarm_request_code), builder.build());
}
}
////////////////////////////////////
Clearing up some issues
Whenever my alarm goes off currently a notification is sent to the user with a static name and description.
What I'm trying to accomplish is that when this alarm goes off, my notification is either given an ID matching the one of Alarm or looks up the alarm to then populate the text and title of the notification with the active alarms details.
This is what my current layout looks like inside of my SQLiteOpenHelper
private static final String DATABASE_NAME = "alarmList.db";
public static final String TABLE_NAME = "alarm_list";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_ALARMTIME = "alarm_time";
public static final String COLUMN_AlARMDATE = "alarm_date";
public static final String COLUMN_ALARMNAME = "alarm_name";
// Alarm request code column for working with switch and
public static final String COLUMN_ALARMRC = "alarm_code";
Followed by default oncreate and update methods
You could do this a few different ways. One would be to add a last_used date column, or a use_count column, and update that each time the record is used. You would then have a query that selects the least used item from your table.
Another way would be to store your alerts within your application and track that information there. The downside of that would be that, unless you store that count/last-used information out (probably to an external stats file) you would lose those counts when you restarted the application.
The concept would really be the same any way you were to approach this. You need to store usage information about your alerts somewhere.
I think this is what you are asking for, but after re-reading your question a few times, I am not as certain. Maybe you could provide some samples of your table structure and some of the data from those tables, and also provide an example of what you are trying to accomplish. If what I have here in my answer isn't what you are looking for, no worries. I will either update it to be more in-line with what you need or remove it altogether. Just want to make sure it is what you are looking for.
More on the last_used query, as requested:
You would want to write a query similar to:
select alert_id, alert_group, alert_text
from alerts
where alert_group = #parm_alert_group
order by last_used asc
limit 1 -- this may be different depending on the flavor of DBMS used
-- Oracle does not have "limit", but can be reproduced in other ways.
;
Then, when you use that alert item, you would want to update that record with the current datetime so that the next time your select query returns the record used longest ago.
update alerts set last_used = now() where alert_id = #parm_alert_id;
You could of course perform both of those actions within a function that returns the alert information and updates the last_used column before returning it, but that is just bonus functionality. The same idea is there using two separate calls, or a single call.
Related
My app has a service that tracks the user's location and compares it to a list of places, then when it finds a latitude/longitude match, it displays a custom notification. Tapping the notification then starts an activity, using a full screen intent, and passes a place name (string) from the service to the activity using putExtra/getExtras. This can happen multiple times as new places are found.
When I first install the app, this works perfectly. If the first place found is, say, London, the name London is passed to the activity correctly. However, if the next place is Bristol, the service has the correct name Bristol at the point where the notification is created (log.v below, labelled "show input"), but the activity still shows the name London (log.v below, labelled "show output") - the new name string is not getting passed across.
However many new places are found, the activity still shows the original name (London in this example) as the place. Also, if I stop and re-start the app, the activity still always shows the place as London, even if the first place found is somewhere else. The only way to get a new place name string passed across correctly is to uninstall and re-install the app.
The relevant code from the service is:
String placeName;
void createPopUpNotification(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.v("sTag","Create notification: placeNumber = "+ placeNumber+" placeName = "+placeName);//show input
String NOTIFICATION_CHANNEL_ID = "notifychannel";
Intent goShow = new Intent(this, DisplayActivity.class);
goShow.putExtra("plname",placeName);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, goShow, 0);
RemoteViews expandedView=new RemoteViews(getApplicationContext().getPackageName(),R.layout.expandednotify);
expandedView.setTextViewText(R.id.placename,placeName);
NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE ) ;
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
builder.setSmallIcon(R.mipmap.amjnotify);
builder.setCustomContentView(expandedView);
builder.setAutoCancel(true);
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setFullScreenIntent(pendingIntent,true);
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "mychannel", NotificationManager.IMPORTANCE_HIGH);
builder.setChannelId( NOTIFICATION_CHANNEL_ID ) ;
channel.setSound(null, null);
notificationManager.createNotificationChannel(channel);
notificationManager.notify(123, builder.build());
}
}
and the code from the activity DisplayActivity is:
int placeNumber;
String placeName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
Intent goShow = getIntent();
Bundle params = goShow.getExtras();
placeName=params.getString("plname");
Log.v("sTag","getParams: placeNumber = "+placeNumber+" placeName="+placeName);//show output
goShow.removeExtra("plnumber");
goShow.removeExtra("plname");
}
Can anyone help me to understand what is going on, and how to pass data (string in this case) correctly from the service to the activity?
copy this code and check
placeName=getIntent().getStringExtra("plname"));
Log.v("sTag","getParams: placeNumber = "+placeNumber+"
placeName="+placeName);//show output
goShow.removeExtra("plnumber");
goShow.removeExtra("plname");
I am trying to build an affirmation app which shows notification as an affirmation text and when user clicks on the notification it should take it to an activity, So far i am able to display notifications on hourly basis but i have no idea how to display different notifications each hour which opens a different activity each time because there is gonna be a random list of affirmations which will be displayed as notifications.
EDIT:
My MainActivity:
private void hourly()
{
Calendar calender=Calendar.getInstance();
Intent intent=new Intent(getApplicationContext(),notification_receiver.class);
PendingIntent pendingintent=PendingIntent.getBroadcast(this,100,intent,PendingIntent.FLAG_UPDATE_CURRENT);
// calender.setTimeInMillis(System.currentTimeMillis());
//// calender.set(Calendar.HOUR_OF_DAY, 10);
//// calender.set(Calendar.MINUTE, 30);
alarmmanager=(AlarmManager)getSystemService(ALARM_SERVICE);
int interval=60000;
alarmmanager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
interval,
interval, pendingintent);
Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
}
My notification_receiver class:
public class notification_receiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
ArrayList<String> notificationTexts = null;
notificationTexts.add("This is a nice day"); // this will go to notificationTexts in position 0;
notificationTexts.add("This is nice morning");
Random rand = new Random();
int n = rand.nextInt(notificationTexts.size());
NotificationManager notificationManager= (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent repeating_activity=new Intent(context,repeating_activity.class);
repeating_activity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent=PendingIntent.getActivity(context,100,repeating_activity,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder=new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setContentTitle("Affirmation")
.setContentText(notificationTexts.get(n))
.setAutoCancel(true);
notificationManager.notify(100,builder.build());
}
}
You already have a mechanism to show the notifications so what you are needing is a sort of backend where you can select a random text linked to a certain activity of your app.
In your main activity you can have 2 lists:
private ArrayList<Srtring> notificationTexts;
private ArrayList<Class> activitiesToStart;
Whith these two you add the text for your affirmations and the activity class you want to start under the same index of position in the list.
For example:
notificationTexts.add("This is a nice day"); // this will go to notificationTexts in position 0;
activitiesToStart.add(TheNiceDayActivity.class); //this will go to the activitiesToStart also in position 0;
In the mechanism you already have working, when you prepare the notification, you just have to calculate a random number between 0 and the length of either Lists, and pick the text from the first list and the activity from the second one. To pick the corresponding element you do it with list.get(position);
Once you got the activity, you create the PendingIntent that goes in the notification setup at the time of building it.
I haven't tried it but it should give you an idea on how it can be done.
EDIT I
A random number between 0 and 19 (including the 19) can be calculated with:
Random rand = new Random();
int n = rand.nextInt(20);
I just implemented GCM and notifications in my Android app, coming from an Apache/PHP-based webserver.
The notifications are already working, but I'm stuck at stacking the notifications, as described here.
What I'm trying to do
I have two types of notifications in my app, using data coming from the GCM Service:
Type 1 (Messages):
[data] => Array
(
[t] => 1
[other data...]
)
Type 2 (News):
[data] => Array
(
[t] => 2
[other data...]
)
These 2 types are completely different notifications, and I would like to stack both of them separate from each other, but I can't get this to work.
I would like to stack them like this, as soon as there are multiple notifications:
Default View
Expanded View
What I tried
2 Notification IDs and Atomic Integer
I tried to use 2 different notification IDs, so that notifications with the same type get overidden.
if (msg.get("t").toString().equals("1")) {
notificationNumber = messageCounter.incrementAndGet();
} else {
notificationNumber = newsCounter.incrementAndGet();
}
[...]
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setNumber(notificationNumber);
If 2 messages are sent at the same time, everything works fine and the counter shows 2. But if there is a short delay between two notifications, the counter switches to 1.
Unique Notification IDs
I also tried to use unique IDs generated with
Date now = new Date();
Notification_id = now.getTime();
so that there isn't no stacking or overriding at all.
Question
How can I solve my problem? Can I access the content of the previously sent notifications, so that I can show every message in one line, like in the expanded view of Gmail? How can I check which / how many notifications are currently displayed?
Long question, thank you very much!
I finally found the solution and ended up using atomic integers, but in a seperated class:
import java.util.concurrent.atomic.AtomicInteger;
public class Global {
public static AtomicInteger Counter1 = new AtomicInteger();
public static AtomicInteger Counter2 = new AtomicInteger();
}
To reset the counter after the application opening, i put this in my MainActivity (called in onCreate() and onResume():
private void clearNotifications(){
NotificationManager mNotificationManager;
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
Global.Counter1.set(0);
Global.Counter2.set(0);
}
When I create the notification, I check the counter:
Counter1 = Global.Counter1.incrementAndGet();
ContentText = (Counter1 < 2) ? /* Single notification */ : /* Stacking */;
I'm using a custom RemoteView for AndroidNotification, and I would like to mimic the system behavior.
How does Android update its notification time format - do they ever change once they are set? How am I able to mimic this behavior?
I don't know much about the notification time format, but if you want to mimic their behaviour should have a look at the DateUtils class, especially the formatSameDayTime which I think does what you described.
It is not possible to update the notification after being added unless .notify is called again with the same ID.
If dealing with time stamp, it is best to use the native Notification NotificationCompat.Builder without using RemoteViews.
I'm not sure whether you are still looking for answers, given that you have provided one yourself. However, if you are looking to achieve your original goal you will probably want to
Rebuild the RemoteView whenever the time changes (it's just way easier)
Set up a BroadcastReceiver to catch the ticks of the clock so you know when the time has changed.
So, some code a bit like this:
class MyCleverThing extends Service (say) {
// Your stuff here
private static IntentFilter timeChangeIntentFilter;
static {
timeChangeIntentFilter = new IntentFilter();
timeChangeIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
timeChangeIntentFilter.addAction(Intent.ACTION_TIME_CHANGED);
}
// Somewhere in onCreate or equivalent to set up the receiver
registerReceiver(timeChangedReceiver, timeChangeIntentFilter);
// The actual receiver
private final BroadcastReceiver timeChangedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_TIME_CHANGED) ||
action.equals(Intent.ACTION_TIMEZONE_CHANGED))
{
updateWidgets(); // Your code to rebuild the remoteViews or whatever
}
}
};
Every time you update your notification, do something as simple as this (24 hour time)...
public void updateNotifTime(RemoteViews customNotifView){
Date currentTime = new Date();
int mins = currentTime.getMinutes();
String minString = "";
if(mins<10){
minString = "0";
}
minString += mins;
customNotifView.setTextViewText(R.id.time, currentTime.getHours()+":"+minString);
}
I got a Activity which creates an alarm.
The alarm calls a Broadcast Receiver. In on Receive i create a Notification with the extras from the Activity (ID, Title, Content). The Alarm triggers the Broadcast Receiver creates the notification well.
But when i re install the application or install a newer version and setup a new Alarm with a new title and content the receiver shows me the first create notification intent. i can create may Alarm triggers all works but they show always the first create Notification intents.
I use a internal application counter for creating a notification ID
public class CollectApplication extends Application {
private Integer reminderCount;
#Override
public void onCreate() {
reminderCount = 1;
super.onCreate();
}
public Integer getReminderCount() {
return reminderCount;
}
public void setReminderCount(Integer reminderCount) {
this.reminderCount = reminderCount;
}
}
Of course after re installing or updating the application the counter starts from 1. But i create a new intent with the same ID 1 so i override it right?
How to override it or remove the intent from the notification to create a new one with new extras to display?
Or Should i save the current ID in the shared preferences?
How to override it or remove the intent from the notification to create a new one with new extras to display?
Use FLAG_UPDATE_CURRENT when you create your PendingIntent for the new Notification.
Or Should i save the current ID in the shared preferences?
No, because you should only have one ID. You may wish to persist your reminder count, though.
->Just add PendingIntent.FLAG_UPDATE_CURRENT
Example:
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);