Android Starting activity from GCM - android

I need to run the following when i get a message from my GCM listner:
public void GetInfo1 (Bundle data){
Log.d("Get Messages", "Data: " + String.valueOf(data));
final String uid = data.getString("uid");
final String infoid = data.getString("infoid");
GetInfo(uid, infoid); // This is another activity that does a Json Post and returns a array that i use to populate my Listview
}
This is how i call the function :
if (activityName.equals(MyActivity.class.getName())) {
// Execute that special method from ActivityListView
Log.d(TAG, "Activity is running");
MyActivity myActivity = new MyActivity();
myActivity.Getinfo1(data);
} else {
// Show the notification
sendNotification(message);
}
but i am always getting this error :
Can't create handler inside thread that has not called
Looper.prepare()
I have tried everything, and am out of ideas now,
I need to call the function and pass the vars but if i make it static i get a error that you cant call non static methods from a static ....
Please any help will be fantastic
T-

In general, to start a new activity, you should not instantiate the activity directly but rather use an Intent to trigger the activity, using either startActivity() or startActivityForResult(). However, in this case, it would appear that you are doing an operation that is intended to run in the background (without user interaction). Activity is an application component intended for direct interaction with the user. For background processing, you should be using a Android Service, instead. As with an Activity, you do not create services directly, but rather invoke them by firing off appropriate Intents.

Related

Can push notification execute code in parallel with UI thread or not?

AsFirebaseMessagingService does not use the Main Thread, I am just wondering as all my code in all of my activities or fragments run in UI thread(Main Thread). Now suppose my activity's onCreate method is executing and then I receive the push notification. Will these two blocks of code run in parallel, or will the push notification code wait in the queue until onCreate() method OR Activity's last life cycle method gets executed?
Edit- As you are saying code will run parallelly then suppose I have a variable in App.java
public class App extends Application {
int ctr = 100;
}
StatusActivity.java
public class StatusActivity extends BaseActivity {
public void onCreate() {
fun();
}
public void fun() {
int d = App.ctr - 1;//Step 1 Here d = 99
int m = App.ctr - 1; // Step 3 Here m = 98
}
}
FcmListener.java
public class FcmListener extends FirebaseMessagingService {
Override
public void onMessageReceived(RemoteMessage mssg) {
App.ctr = App.ctr - 1;//STEP 2 // Now App.ctr = 99
}
}
Now as you can see in the above code there will be problems if push notif code executes in parallel with fun(). I want push_notif and fun() to run serially, where order doesn't matter but not in parallel.
As already pointed out in a parallel answer, the overriden methods of FirebaseMessagingService run in a background thread, so you should use synchronization strategies in order to access/use mutable object from different thread.
But the question I want to answer is a bit different. Let's for a moment assume, that overriden methods run on a main thread. So is there a possibility, that the order of execution will be STEP 1 then STEP 2 and then STEP 3?
Android works with a technique called MessageQueue, basically there are Messages posted on that queue, on which Looper loops and "parses/executes" them.
Now if we assume, that you are currently located on STEP 1, it means, that there was a particular Message which is currently being executed (hypothetically, let's assume that action is - perform onCreate() of this activity).
Until this message is fully executed there cannot exist another Message which might get have a chance to be executed. So if we assume, that Firebase dispatches an event on background thread but the actual overriden method is being run on main thread, then this overriden method would have chance to be executed only after current Message (activity's onCreate()) has finished. In other words, there would be posted another Message on the MessageQueue, which would perform onMessageReceived() when the Looper will give chance for this message to be executed.
So, theoretically, there is no chance that the ordering would be STEP 1 -> STEP 2 -> STEP 3.
If STEP 1 is already executed, then it will continue with STEP 3 and the STEP 2 (at some point in future, because you can't know what other Messages are already posted on MessageQueue).
See this article for more details about MessageQueue and related classes.
How about it?
class Sample {
private String message = null;
private final Object lock = new Object();
public void newMessage(String x) {
synchronized (lock) {
message = x;
}
}
public String getMessage() {
synchronized (lock) {
String temp = message;
message = null;
return temp;
}
}
}
Here is my 2 cents. You say,
Suppose my activity's onCreate method is executing and then I receive the push notification. Will these two blocks of code run parallelly or will the push notification code wait in the queue until onCreate method OR Activity's last life cycle method gets executed?
From the official documentation of FirebaseMessagingService:
Extending this class is required to be able to handle downstream messages. It also provides functionality to automatically display notifications, and has methods that are invoked to give the status of upstream messages. Override base class methods to handle any events required by the application. Methods are invoked on a background thread.
So its possible both methods execute at the same time. If you want to do the operations on a shared variable in your Application class, you can do thread safe operations using synchronize. See How to synchronize or lock upon variables in Java?. That will make sure only one thread is making changes at a time on that variable. If a new thread comes in, it waits for the lock to get free and then makes the changes on that variable. However this doesn't guarantee the order. It just means that one thread operates on it at time and is in FIFO order.
I suggest you a different approach, because using those global variables can lead to unexpected behavior.
If your ctr var is related to your activity, then keep it inside. If you need it on other activities consider passing it via the Intent as an extra.
Use LocalBroadcastManager to inform your activity that you received the push message
public class FcmListener extends FirebaseMessagingService {
public static final String ACTION_MESSAGE_RECEIVED = "ACTION_MESSAGE_RECEIVED"
#Override
public void onMessageReceived(RemoteMessage mssg) {
Intent intent = new Intent(ACTION_MESSAGE_RECEIVED) // put extra vars as needed
boolean delivered = LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
// 'delivered' is true if there is at least someone listening to the broadcast, eg. your activity
// If your activity is not running, then 'delivered' is false so you can act accordingly
}
}
Then inside your activity
public class StatusActivity extends BaseActivity {
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.equals(FcmListener.ACTION_MESSAGE_RECEIVED, action)) {
// do stuff with 'ctr'
}
}
};
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(FcmListener.ACTION_MESSAGE_RECEIVED);
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, filter);
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver);
}
}

Bus Implementation... Checking For Fragment Equality... Or Something Similar

I have implemented a bus for my app for communication between fragments and activities. I add a subscriber by adding an instance of either a Fragment or an Activity to a list. and I iterate through that list invoking a method to notify each of the subscribers of what is going on. Now I need to keep the list clean, I don't want to add multiple instances of of the same class in the list. I can use equals() for an Activity but I cant for a Fragment because its final so I cant override it.
WHAT I HAVE TRIED
I have tried to keep a Class object of each subscriber in the list which works fine until I go to invoke the method. You cant invoke a method without an instance to invoke it from. So that doesnt work.
I could also keep a separate list, one to hold Class objects and one to hold the actual instance. But I want to avoid adding another dependency if at all possible.
I could also manually do a instanceof check for each Fragment, but I dont want to do that because I already have 5 fragments, and if I add or remove any then I have to come back here and update this method.
So my question is, other than adding another List to hold the Class objects or manual instanceof checks, are there any other ways I can make sure I dont add multiple instances to the subscribers List?
Here is the relevant code if you need it:
public void subscribe(Object object) {
if (!mSubscribers.contains(object)) {
mSubscribers.add(object);
}
}
public void notifySubscribers(BusEvent event) throws InvocationTargetException, IllegalAccessException {
for (Object o : mSubscribers) {
Method methodToCall = getMethodToCall(o);
if (methodToCall != null) {
methodToCall.invoke(o, event);
}
}
}
Ok I have found a suitable answer to my problem. I want to share it here in hopes that it will help someone else out. Android has a class called LocalBroadcastManager. It is available in the v4 support library. In your activity you call 'LocalBroadcastManager.getInstance().registerReceiver()'. You pass into that method a class that extends BroadcastReceiver and an 'IntentFilter' to tell the receiver what to listen for. Then in any class including Fragments you call LocalBroadcastManager.getInstance().sendBroadcast() and pass in an Intent that matches the IntentFilter you used when registering. Here is the code I used to get it to work:
private void registerLocalBroadcastReceiver() {
// call this method in your activity (or any class you want to listen for broadcasts)
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
manager.registerReceiver(new OpenMenuBroadcastReceiver(), new IntentFilter("open-html"));
}
private void sendMessageToActivity(int position) {
// use this in a fragment (or any other class) to send a message
LocalBroadcastManager broadcast = LocalBroadcastManager.getInstance(getActivity());
Intent message = new Intent("open-html");
String name = (String) getListAdapter().getItem(position);
message.putExtra("name", name);
broadcast.sendBroadcast(message);
}
class OpenMenuBroadcastReceiver extends BroadcastReceiver {
// this is an inner class to my activity, when you send the message this method
// will be called to handle the message
#Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
if (name != null && name.equalsIgnoreCase("home")) {
replaceFragment(Tag.HOME_FRAGMENT.getTag(), new HomeFragment(), R.id.main_frame);
mDrawerLayout.closeDrawer(Gravity.START);
return;
}
openMenuItemsFragment(name);
}
}
The good thing about this is that it is completely local to your app. External apps cant receive your broadcasts so its secure. You can find out more on how to use it on the Android developer site.

Android How to reconnect to AsyncTask after onDestroy() and relaunch onCreate()?

I have tested the statement that AsyncTasks are not destroyed along with their launching activity. And it is true.
I made the AsyncTask just publish a Log.i() message every 3 seconds for 1 minute. And I put Log.i() messsage in the onDestroy() method of the activity.
I see the activity is destroyed, but the AsyncTask keeps running until it finishes all 20 Log.i() messages.
And I am confused.
What if the AsyncTask had publishProgress() into the destroyed UI?
I guess some sort of exception would occurr, right?
What if the AsyncTask stores data in a global variable of class Application?
No idea here, NullPointer exception?
What if the app is restarted?
It will probably launch a new AsyncTask. Can it reconnect with the still running AsyncTask?
Is the AsyncTask immortal after the mother app is destroyed?
Maybe yes, how do all LogCat apps keep logging messages while the UI application is not visible anymore, maybe destroyed? And when you reopen them they show you the messsages that were generated while it was 'dead'.
All this seems like a discussion, but the question is in the title. I have this orphan AsyncTask, which I would like very much to reconnect to when the app is relaunched, but I don't know how to do it.
I forgot to tell why this is very important. The app gets destroyed when an orientation change occurs. And I don't want to loose the data produced by the AsyncTask, I don't want to stop it and restart it. I just want it to keep going and reconnect after the orientation changes are done.
I hope I've got this right as it's from some old code I no longer use (I now use an IntentService to do what this used to do).
This is what I originally had when I downloaded files in my main Activity...
public class MyMainActivity extends Activity {
FileDownloader fdl = null;
...
// This is an inner class of my main Activity
private class FileDownloader extends AsyncTask<String, String, Boolean> {
private MyMainActivity parentActivity = null;
protected void setParentActivity(MyMainActivity parentActivity) {
this.parentActivity = parentActivity;
}
public FileDownloader(MyMainActivity parentActivity) {
this.parentActivity = parentActivity;
}
// Rest of normal AsyncTask methods here
}
}
The key is to use onRetainNonConfigurationInstance() to 'save' the AsyncTask.
Override
public Object onRetainNonConfigurationInstance() {
// If it exists then we MUST set the parent Activity to null
// before returning it as once the orientation re-creates the
// Activity, the original Context will be invalid
if (fdl != null)
fdl.setParentActivity(null);
return(fdl);
}
I then have a method called doDownload() which is called from onResume() if a Boolean indicating downloadComplete is true. The Boolean is set in the onPostExecute(...) method of FileDownloader.
private void doDownload() {
// Retrieve the FileDownloader instance if previousy retained
fdl = (FileDownloader)getLastNonConfigurationInstance();
// If it's not null, set the Context to use for progress updates and
// to manipulate any UI elements in onPostExecute(...)
if (fdl != null)
fdl.setParentActivity(this);
else {
// If we got here fdl is null so an instance hasn't been retained
String[] downloadFileList = this.getResources().getStringArray(R.array.full_download_file_list);
fdl = new FileDownloader(this);
fdl.execute(downloadFileList);
}
}

Analog of startActivityForResult for Service

Despite similar question was asked, I have differnet situation:
My app consists mostly of a background Service. I want to start external activities and get results back.
I see several options:
Create dummy Activity and keep reference to it for using its startActivityForResult. This consumes quite a lot of memory, as we know.
Use Broadcast Intents instead of Android's results infrastructure: ask client activities to broadcast their results before closing. This kind of breaks the idea and not so performance-efficient.
Use Instrumentation directly - try to copy code from startActivityForResult into my Service.
Use Service interfaces - serialize and add AIDL connection to the Intent for starting an Activity. In this case Activity should call Service directly instead of providing result.
The third approach feels closer to Android for me, but I'm not sure if it's possible to do - Service does not have its Instrumentation, and default implementation seems to always return null.
Maybe you have any other ideas?
I’ve been thinking about this recently when implementing account authenticators with three-legged authorisation flows. Sending a result back to the service for processing performs better than processing it in the activity. It also provides a better separation of concerns.
It’s not that clearly documented, but Android provides an easy way to send and receive results anywhere (including services) with ResultReceiver.
I’ve found it to be a lot cleaner than passing activities around, since that always comes with the risk of leaking those activities. Additionally, calling concrete methods is less flexible.
To use ResultReceiver in a service, you’ll need to subclass it and provide a way to process the received result, usually in an inner class:
public class SomeService extends Service {
/**
* Code for a successful result, mirrors {#link Activity.RESULT_OK}.
*/
public static final int RESULT_OK = -1;
/**
* Key used in the intent extras for the result receiver.
*/
public static final String KEY_RECEIVER = "KEY_RECEIVER";
/**
* Key used in the result bundle for the message.
*/
public static final String KEY_MESSAGE = "KEY_MESSAGE";
// ...
/**
* Used by an activity to send a result back to our service.
*/
class MessageReceiver extends ResultReceiver {
public MessageReceiver() {
// Pass in a handler or null if you don't care about the thread
// on which your code is executed.
super(null);
}
/**
* Called when there's a result available.
*/
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Define and handle your own result codes
if (resultCode != RESULT_OK) {
return;
}
// Let's assume that a successful result includes a message.
String message = resultData.getString(KEY_MESSAGE);
// Now you can do something with it.
}
}
}
When you start an activity in the service, create a result receiver and pack it into the intent extras:
/**
* Starts an activity for retrieving a message.
*/
private void startMessageActivity() {
Intent intent = new Intent(this, MessageActivity.class);
// Pack the parcelable receiver into the intent extras so the
// activity can access it.
intent.putExtra(KEY_RECEIVER, new MessageReceiver());
startActivity(intent);
}
And finally, in the activity, unpack the receiver and use ResultReceiver#send(int, Bundle) to send a result back.
You can send a result at any time, but here I've chosen to do it before finishing:
public class MessageActivity extends Activity {
// ...
#Override
public void finish() {
// Unpack the receiver.
ResultReceiver receiver =
getIntent().getParcelableExtra(SomeService.KEY_RECEIVER);
Bundle resultData = new Bundle();
resultData.putString(SomeService.KEY_MESSAGE, "Hello world!");
receiver.send(SomeService.RESULT_OK, resultData);
super.finish();
}
}
I think option 2 is the most idiomatic way on android. Using startActivityForResult from an Activity is a synchronous/blocking call, i.e., the parent activity waits and does not do anything until the child is done. When working from a Service and interacting with activities your primarily doing asynchronous/non-blocking calls, i.e., the service calls out for some work to be done and then waits for a signal to tell it that it can continue.
If you are using the android local service pattern then you can have your activities acquire a reference of the Service and then call a specific function after it has performed its work. Attempting your option 3 would be counter to what the framework provides for you.

Android: How to close foreground activity from active activity?

I created an application which is asynchronously communicating with the server. When the application makes a server request a new dialog (activity) with "loading" notification is created. The main activity implements methods for handling server responses and I would like to close the foreground activity when the main activity receives the answer from the server.
Notification dialog is created the following way:
private void showServerRequestDialog(String actionLabel){
Intent intent = new Intent(this, DlgServerRequest.class);
intent.putExtra(SERVER_REQUEST_ACTION, actionLabel);
startActivity(intent);
}
so when the user tries to authenticate the following method is called:
private void authenticateUser(String IMEI, String username, String password){
mEncoderConnection.authenticateRequest(IMEI, username, password);
showServerRequestDialog("Authenticating...");
}
and onAuthenticateResponse handles authentication response:
public void onAuthenticateResponse(AuthenticateResponse pkg) {
//code for response handling
//TODO: close ServerRequestDialog
}
}
I would appreciate if anyone could suggest a way to close the notification dialog (DlgServerRequest) when the onAuthenticateUser() is executed.
Why not use a real ProgressDialog or some other Dialog? Then, all you need to do is dismissDialog(), and you're done?
If that is unacceptable, you have two main courses of action that I can see:
Move your authentication logic into the DlgServerRequest class, so it can finish() itself.
Put your instance of your DlgServerRequest class into a static data member so your main activity can call finish() on it
If you choose option #2, it is really important to null out that static data member to avoid memory leaks.

Categories

Resources