How to start Activity once and then use the same instance? - android

I have the Activity with Messages list. When new message arrived I want to show it in the list. And I want to use the same Activity instance instead of creating new for each new message.
But my Activity doesn't opening (and I don't see my log message from onCreate() method).
There is me Activity code:
public class MessagesListDialogActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
super.onCreate(savedInstanceState);
Log.e("MESSAGE", "onCreate()");
// ... create UI
handleIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(#NonNull Intent intent) {
// obtain the message and add to list on UI
}
}
And this is code from my Launcher class:
public static void showMessage(#NonNull Context context, #NonNull Message message) {
final Intent intent = new Intent(context, MessagesListDialogActivity.class);
BundleUtil.setMessage(intent, message);
context.startActivity(intent);
}
And this lines from Manifest:
<activity android:name=".features.messages.list.MessagesListDialogActivity"
android:screenOrientation="portrait"
android:theme="#style/DialogTheme"
android:launchMode="singleTop"/>
I try use different launchMode params, like singleTask and singleInstance but it doesn't work.

Thank you for your attention. After lot of attempts to fix it i try use this flags:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);
And this help me. Thank you and hope my experience help you in the future.

Related

My Activity not receiving Local Broadcasts sent from another activity

I'm just getting familiarised with the Local Broadcast Messages. I have 2 activities.
MainActivity :
I have 2 buttons. On the click of 1 button, I'm broadcasting the message. On the click of another one, I'm navigating to second Activity.
public class MainActivity extends AppCompatActivity {
Button btn;
Button btn1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.sendBroadCast);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendMessage();
}
});
btn1 = (Button)findViewById(R.id.btn);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
void sendMessage(){
Log.d("RAK","Gonna send braodcast");
Intent intent = new Intent("customMsg");
intent.putExtra("message", "This is my message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Second Activity :
Registering for the receiver in onCreate of this activity.
public class SecondActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Log.d("RAK","In oncreate of second activity.Registered for local receiver");
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("customMsg"));
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
}
The issue I'm facing is, the second Activity is not receiving the broadcast. Please help me.
P.S : Please dont mark this a duplicate. I have followed this link : how to use LocalBroadcastManager?
Thanks,
Rakesh
So as to receive the broadcast the second activity should be up and running while the first one is sending a broadcast, which is going to be hard in your case (2 activities not running at same time).
Your first Activity sends the broadcast, but no activity (in your case second activity) is launched yet so the messgae get 'lost'.
You could test by broadcasting from within a service for example, and your second activity running. Then, the activity could handle/receive it.
What you may want to do is passing a String to the secondActivity using extraData. If you wish to test BroadcastReceiver, then, try with a service sending the broadcast !
The problem is your registering your broadcast receiver inside onCreate() of second activity, that means the second activity should have been previous launched before you broadcast your intent keeping in mind that your do not unregister it when the second activity is destroyed.
Alternative you can register your receiver statically in the Manifest file
public class Receiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
// Whatever
}
}
Manifest
<receiver
android:name=".Receiver"
android:exported="false" >
<intent-filter>
<action android:name="customMsg" />
</intent-filter>
</receiver>
NOTE:
Registering statically ensure that the the receiver is registered at system boot time or when the application is added at run time

Android LocalBroadcastManager from Fragment to Activity not receiving message

I want to sent a message from a Fragment to an Activity (not the Fragment parent Activity, just another one).
Actually I do the same from a Service to the same Activity and it works great.
This is my code:
Fragment:
private void sendBroadcastMessage() {
Intent intent = new Intent("my_event");
// add data
intent.putExtra("message", "test");
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);
}
Activity:
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
super.onPause();
}
#Override
protected void onResume() {
super.onResume(); LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, new IntentFilter("my_event"));
}
I've just followed that great post, but it only works from Service to Activity
I think it has something to do with the Context from the Fragment, maybe getActivity() is not the right way...
Any ideas?
Thanks.
Register broadcast in onCreate and unregister in onDestroy of your activity.
In your case it may be unregister in onPause. so unregister in onDestroy instead of onPause.
Thanks,

Broadcast receiver not working in some cases

So i have this receiver in my Fragment.class
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WeekplanHepler.ACTION_SERVICE_BINDED) && getUpdateService() != null) {
getCounts();
}
if (intent.getAction().equals(Helper.UpdateCounts)) {
HashMap<String, Integer> counts = (HashMap<String, Integer>) intent.getSerializableExtra(Helper.PARAM_LIST_COUNTS);
// Updating counts
}
}
};
For registering/uregistering this receiver i'm using this code:
#Override
public void onStart() {
super.onStart();
getCounts(true);
getActivity().registerReceiver(receiver, getIntentFilter());
}
#Override
public void onStop() {
super.onStop();
getActivity().unregisterReceiver(receiver);
}
getCounts() is a RetrofitRequest puted in UpdateService, which is getUpdateService() here
So, when retrofit request has been finished, it returns counts through Intent and then, as you see, i'm updating them. But if i go to next Activity and then returns, request will work fine, and it will send intent, but receiver wont get it. I think this can be caused by method service is binded in first place. So i have BaseFragment, which binds service for all Fragments needed
public abstract class BaseFragment<T> extends CustomListFragment<T> {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().getApplicationContext().bindService(new Intent(getActivity().getApplicationContext(),
WeekplanUpdateService.class), connection, Context.BIND_AUTO_CREATE);
}
}
When i go to next activity, it fragment will bind service, and my previous fragment will call request again, and will have counts. Maybe receiver has some limitations for how much he can get same intents, but i don't think so. Please help
Oh, i forgot to mention how i'm sending intent
sendBroadcast(new Intent(Helper.UpdateCounts).putExtra(Helper.PARAM_LIST_COUNTS, counts));
So, when i've started to use
sendStickyBroadcast(new Intent(Helper.UpdateCounts)
.putExtra(Helper.PARAM_LIST_COUNTS, counts));
instead of
sendBroadcast(new Intent(Helper.UpdateCounts)
.putExtra(Helper.PARAM_LIST_COUNTS, counts));
it worked.

send action from receiver to activity?

I am using broadcast receiver in my app to detect incomming call and it works fine. But problem is I can not send action to activity. I mean.. I want do something in activity not in receiver. I read many tutorial but they all are performing action in receiver. Any idea ?
You can declare a BroadcastReceiver as inner class of the Activity. In this case you can directly call activity's methods:
public class MyActivity extends Activity {
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activityMethod();
}
};
private final IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");
#Override
protected void onStart() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onPause();
unregisterReceiver(receiver);
}
private void activityMethod() {
}
}
You can start the Activity using an Intent and put a command code in the Intent extra fields. In your Activity you can then decide the behaviour based on the command code or resort to a default behaviour if none is present.
You can start an activity from your receiver via the normal means:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, YourActivity.class);
startActivity(i);
}
Note though that the user is going to expect that the phone application starts up since they are receiving a phone call. It is very likely a bad idea to hijack the phone call by dumping your own activity on top of the stock dialer app.

How to implement a BroadcastReceiver in Android

I am trying to implement a BroadcastReceiver but it is not working.
I want to use it to return progress from a class that implements network io, which is called from an AsyncTask inside my Activity.
Here is the code for my activity:
package com.ClinicalInterface;
public class TestActivity extends ListActivity {
static AsyncDataLoader mAsyncDataLoader;
static ProgressDialog dialog;
static ArrayList<String> list;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialog = new ProgressDialog(this);
dialog.setMessage("Loading...");
dialog.show();
mAsyncDataLoader = new AsyncDataLoader();
mAsyncDataLoader.execute();
}
public class AsyncDataLoader extends AsyncTask<Void, Integer, String> {
public class mTestReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
System.out.println( "I've received something!" );
publishProgress(2);
}
}
#Override
protected String doInBackground( Void ... params ) {
TestLoader tl = new TestLoader();
tl.setContext(getApplicationContext());
tl.setServeraddress("192.168.2.109");
list = tl.doLST(null);
return "COMPLETE!";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (values[0] == 2) {
dialog.setMessage("Loading data ...");
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dialog.dismiss();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(TestActivity.this, R.layout.list_item, list);
TestActivity.this.setListAdapter(adapter);
}
}
}
This is supposed to display a list, then overlay this with a progress dialog while the data for the list is returned from a server. And this works OK.
I would like to update the text in the progress dialog as the network io is done.
This is the code that implements the network io:
package com.ClinicalInterface;
public class TestLoader {
private Context mContext;
public void setContext(Context context) {
mContext = context;
}
public ArrayList<String> doLST(String arg) {
// Send intent to AsyncTask
Intent intent = new Intent(mContext, mTestReceiver.class);
intent.setAction("PROGRESS");
mContext.sendBroadcast(intent);
System.out.println( "message sent" );
// Code that actually does network io removed for brevity
}
}
In the Android manifest file I've added the following:
<activity android:name="TestActivity" android:label="TestActivity">
<receiver android:name=".AsyncDataLoader.mTestReceiver">
<intent-filter>
<action android:name="android.intent.action.PROGRESS" />
</intent-filter>
</receiver>
</activity>
I get the log print "message sent"
But not the log print "I've received something"
I am an Android newbie so I assume I've not implemented something correctly.
Any ideas?
Original post updated with intent-filter and set of action when creating the intent. Still not working.
Your <receiver> tag needs to contain an <intent-filter> to tell Android which broadcast intents you actually want to receive.
EDIT:
An Intent is not much more than a container for a message; it's the function that you call to send the Intent that determines which fields you need to set.
From the docs for Intent:
[Intent] can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.
Those functions are your options for sending Intents. startActivity and the startService/bindService functions use explicit Intents; sendBroadcast does not.
Notice that startActivity throws an exception if it can't find your Intent's target class, and startService will return null if it can't find your target class. sendBroadcast doesn't do anything like that because it doesn't even look at that field. sendBroadcast "Broadcasts the given intent to all interested BroadcastReceivers."
Since you are using Context.sendBroadcast() to send your intent, you should be setting an action on your Intent and your BroadcastReceiver should have an intent filter containing an entry for that action.
Ok
It seems like the answer is that its not possible to use the manifest to register the receiver.
If I change the code so that it uses registerReceiver then it works ok.
Code updated like this:
#Override
protected String doInBackground( Void ... params ) {
TestLoader tl = new TestLoader();
IntentFilter intentFilter = new IntentFilter("PROGRESS");
mReceiver mmReceiver = new mReceiver();
registerReceiver(mmReceiver, intentFilter);
tl.setContext(getApplicationContext());
tl.setServeraddress("192.168.2.109");
list = tl.doLST(null);
unregisterReceiver(mmReceiver);
return "COMPLETE!";
}
And remove anything to do with the receiver from the manifest.
Note: the code that sends the Broadcast is like this:
Intent intent = new Intent();
intent.setAction("PROGRESS");
mContext.sendBroadcast(intent);

Categories

Resources