I am fairly new to Android, and am currently working on a simple XMPP Client. A user should be able to log in, and should be notified whenever an XMPP message arrives. It should be possible to access an overview of all messages that arrived during the current session.
When launching the application, a LoginActivity is started, prompting the user to fill in his or her credentials. If the right credentials are provided, a background service is started:
Intent intent = new Intent(this, NotificationService.class);
startService(intent);
On startup, the notification service adds a packet listener to the XMPP connection and requests to be running in the foreground. The users is prompted with a notification caused by this foreground request ("Ongoing"). Now I have provided a second activity called XMPPClientActivity, showing all messages that are received during the session and a simple logout button. When opening the application from within the "Ongoing" notification, the XMPPClientActivity is started because the notification is defined like this:
xmppIntent = new Intent(this, XMPPClientActivity.class);
pendingIntent = PendingIntent.getActivity(this, 0, xmppIntent, 0);
NotificationCompat.Builder xmppBuilder = new NotificationCompat.Builder(this);
xmppBuilder.setContentIntent(pendingIntent);
// Notification details
startForeground(id, xmppBuilder.build());
When opening the application from the home screen however, the LoginActivity is opened again. Of course I want the XMPPActivity to be started, but I can't seem to figure out how this should be done. I have been looking into binding an activity to a service, but I'm unsure if this can be of any help. What is the right way to do this?
What you can do, as I understand you issue, is use ShaeredPreferences. Create a preference like "loggedin" and set a boolean variable to true the first time they log in. Now you can set this to false when they click the "logout" Button.
When the Activity is started you can check the SharedPreference before calling setContentView() and if the value is true then finish() the LoginActivity and open your other Activity.
The link to the docs I provided has a good example of creating, opening, and editing SharedPreferences
Related
I am working on an android project that has an alarm clock like functionality.
I schedule an intentService for each alarm instance (fires at 9pm, for example.), this intentService builds the notification and displays it. The notification includes a fullScreenIntent, which works as expected and launches the activity. I use the following code to do this:
alarmActivityIntent = new Intent(this, AlarmActivity.class);
PendingIntent alarmActivityPendingIntent = PendingIntent.getActivity(this, alertSchedule.getIntentId(), alarmActivityIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder.setFullScreenIntent(alarmActivityPendingIntent, true);
Notification mNotification = mBuilder.build();
mNotificationManager.notify(alertSchedule.getIntentId(), mNotification);
This works as expected when only one alarm is set to fire at a specific time, however if two alarms are set to fire at a specific time the behavior changes.
I want the first fullScreenIntent to start its activity, then when that activity finishes, show the next one. I believe I want to build up a task stack, and push these alarm intents onto it. However this is all new to me.
Is it possible to group these notifications?
If you are using the full screen Intent feature, you don't need to use an IntentService or a Notification at all. Just have the AlarmManager start your Activity when it fires.
You don't want to build a task stack, that is all too complicated. If you have multiple alarms that can fire at the same time, you can have the AlarmManager start the same Activity each time. Set the launch mode of this Activity to singleTop (in the manifest), so that if the Activity is already showing when the alarm fires, it will not create another instance of the Activity on top of the existing one, but instead will deliver the Intent by calling onNewIntent() on the existing instance of the Activity. In onNewIntent() you can save the data (extras) of the Intent in a queue that will be processed when the user finishes the currently shown Activity. To do that, just override onBackPressed() so that when the user presses the BACK button to finish the current Activity, you can check if there are any additional alarms waiting in the queue. If there are none, you can just call super.onBackPressed() to finish the Activity. If there is anything in the queue, you can remove the first element in the queue and display that in your Activity. Keep doing that until the queue is empty.
I need to implement this feature but I am not sure if this is possible on android.
We have gcm listener service running. But let's say the app is open, and a notification arrives from the server. I need to have an activity triggered automatically without touching the notification status bar on the top of the phone screen.
In other words, without any user interaction once the notification arrives, if the app is running, an activity must be triggered immediately.
I took a look at this thread, but this is not really what I need.
Intent - if activity is running, bring it to front, else start a new one (from notification)
any clues or more info?
thx!
You can start an activity without another prior activity by using the FLAG_ACTIVITY_NEW_TASK flag.
Context c = getApplicationContext(); // or getContext(), or any other context you can find from the current app
Intent i = new Intent(c, YourActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
So, my app, has multiple activities.
One of them displays a list of messages (retrieved from a local SQLite).
I also have a GlobalClass that extends Application and I use it in order to store some values between activities.
Like this:
import android.app.Application;
public class GlobalClass extends Application {
private String uzid;
...
public String getUzer() {
return uzid;
}
public void setUzer(String aUzer) {
uzid = aUzer;
}
My app, of course has a login page, where user authenticates itself before gaining access to the app. When he does that, I set a userId integer in my GlobalClass with the id number of the logged user.
Until now, nothing fancy.
I also have a sync adapter that checks for new messages on a remote server and synchronizes the 2 tables (local and remote). And when the sync adapter finds new messages on the remote server, it generates an Android Notification. When user clicks on the notification, my app opens and the activity with the inbox shows up displaying all messages.
I noticed that from time to time, my globalClass userID is empty, even though when I start the app, you cannot get passed the login activity without setting it.
So the app absolutelly sets this globalClass value.
So my guess is that when my android notification is clicked, and the activity with the message list is shown, somehow the globalClass is re-initialized ?!?!?!?!
Is there any way of making sure this does not happen?
I really need my user to be able to use the app just like never happened when he starts it from the notification bar by clicking on the notification.
I mean, the user logs in, GlobalClass userId is being set, then the app goes on. After a a while it enters pause, display shuts down, then a new message arrives and a notification is shown. The user clicks it and my app is brought back to the display showing messages, but the userId is null now.
Why?
And how to prevent this?
This is how I show the notification when a new message is found in the syncAdapter:
Intent intent = new Intent(context, MesajeActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, i, intent, PendingIntent.FLAG_UPDATE_CURRENT); //(context, 0, intent, 0);
// Build notification
Notification noti = new Notification.Builder(context)
.setContentTitle("Message from "+ self.getSursanume())
.setContentText(self.getTitlu()).setSmallIcon(R.drawable.new_50)
.setContentIntent(pIntent)
.build();
NotificationManager notificationManager;
notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
// hide the notification after its selected
noti.flags |= Notification.FLAG_AUTO_CANCEL;
noti.defaults |= Notification.DEFAULT_VIBRATE;
noti.sound = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.htc4);
noti.number = i;
notificationManager.notify(i, noti);
What is wrong here?
I use the current user id (found in GlobalClass) to identify the messages that are intended for the current user, so in onCreate, and also in onResume I instantiate my GlobalClass and retrieve the userID. But this crashes my app. Because sometimes when entering the app from the notification, my global variable "userID" is NULL.
How do I make this problem go away?
Thank you
I noticed that from time to time, my globalClass userID is empty, even though when I start the app, you cannot get passed the login activity without setting it. So the app absolutelly sets this globalClass value.
First, your app may not be started to launch an activity (e.g., app started to send a command to a service).
Second, your app may not be started to launch your login activity (e.g., user came back to you from recent-tasks list).
So my guess is that when my android notification is clicked, and the activity with the message list is shown, somehow the globalClass is re-initialized ?!?!?!?!
Your process was terminated in between invocations. This is perfectly normal.
Is there any way of making sure this does not happen?
Not really. Processes go away all the time, on all operating systems, for any number of reasons (e.g., crashes, manual termination by the user).
I really need my user to be able to use the app just like never happened when he starts it from the notification bar by clicking on the notification.
Then you are going to need to persist your data. Static data members, including custom Application objects, are only a cache.
Or, rather than having a "login activity", have it be some sort of fragment that you can display in any of your activities when authentication is needed.
Or, have your Notification route to the "login activity", which would determine that authentication is not needed and forwards the user along to the end destination. If, OTOH, authentication is needed, the "login activity" handles this, then forwards the user along to the end destination.
I have a service that shows a notification that I wish that will be able to go to a specific activity of my app each time the user presses on it. Usually it would be the last one that the user has shown, but not always.
If the activity was started before, it should return to it, and if not, it should open it inside of the app's task, adding it to the activities tasks.
In addition, on some cases according to the service's logic, I wish to change the notification's intent so that it will target a different activity.
How do i do that? Is it possible without creating a new notification and dismissing the previous one? Is it also possible without creating a new task or an instance of an activity?
No it wouldn't be possible to change the Activity once you have sent the notification.
You can start an Activity on your task stack that is not a problem, check out the notification service in the tutorial here:
http://blog.blundell-apps.com/notification-for-a-user-chosen-time/
You have to set a pending intent on the notification:
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, SecondActivity.class), 0);
// Set the info for the view that shows in the notification panel.
notification.setLatestEventInfo(this, title, text, contentIntent);
You can see the pending intent takes a normal intent "new Intent(this, SecondActivity.class" so if you want specific behaviour (like bringing to the top instead of starting a new activity. Add the flags like you would normally to this intent. i.e. FLAG_ACTIVITY_REORDER_TO_FRONT (something like that)
Since platform version 11, you can build a notification using Notification.Builder. The v4 support library has an equivalent class NotificationCompat.Builder.
You can't change the Activity once you've sent the notification, but you can update the notification with a new Intent. When you create the PendingIntent, use the flag FLAG_CANCEL_CURRENT. When you send the new notification, use the ID of the existing notification when you call NotificationManager.notify().
Also, you should be careful how you start your app. The Status Bar Notifications guide tells you how to set up the back stack.
Ok,
I am working on an Android app that uses a service to collect & process GPS data. The service also creates a notification in the status bar. What I cannot figure out is how to have the notification open the main class when a user clicks on it. From what I've found online it shouldn't be that hard to do, but I cannot get it to work. Does anyone have some suggestions on where to look?
Intent notificationIntent = new Intent(this, MyClass.class);
This line of code is from http://developer.android.com/guide/topics/ui/notifiers/notifications.html.
Simply replace MyClass with your activity class - it will be launched when you click the notification.