Access the "main activity" from a context passed to a BroadcastReceiver? - android

How would I get access to the "main" activity from inside a BroadcastReceiver?
public void onReceive(Context context, Intent intent)
UPDATE: I am trying to get a reference to the activity from within the Broadcast Receiver executes.
( Android newbie here... please be gentle :)

"Main" activity can mean lot of things - it can be the currently foreground Activity; the Activity that is launched from the app's icon on the home screen; or an tabbed Activity that holds another Activities as tabs. I presume that by "access" you mean to hold an reference to the Activity object.
In any case, if the Activity is know to have only one meaningful instance constructed at any given moment, you can make it singleton.

Related

Why is 'this' passed while creating an instance of Intent?

I am new to android app development.
I am trying to understand what is intent and its uses.
My question is that while starting another activity, why is 'this' keyword passed as the context parameter for the intent?
Intent foo = new Intent(this, viewContacts.class);
I understand that the any activity extends Context class, but why is it that we are passing the activity context and not the application context?
My Point-
When another activity starts the current activity will get destroyed but its context will be passed to the other one. Referring to this article, it says that
The most obvious way of avoiding context related memory leak is to avoid escaping the context outside of its own scope.
So aren't we passing the context of current activity to another one where the first one goes out of scope?
Isn't it an example of memory leak?
why is it that we are passing the activity context and not the application context?
Either would work here. this is less typing and faster to execute than is getApplicationContext().
When another activity starts the current activity will get destroyed but its context will passed to the other one.
You are assuming that the Intent holds onto this Context. It does not.
So aren't we passing the context of current activity to another one where the first one goes out of scope?
No.
An Intent can either be implicit or explicit. An explicit Intent is one that has a ComponentName attached, identifying the specific app (by package name) and Java class (by fully-qualified class name) of the component for which this Intent is intended. The two-parameter constructor, providing the Context and Class object, is used to build that ComponentName. Neither the Intent nor the ComponentName hold onto the Context after the constructor work is completed.

Get root view of one activity from another activity

Is there a way to get a root view of one activity from another lets say there are two activity A and B i want root view of activity A from B.please Help
Edit: I am Trying to make change in Main Activity from Preference Activity for ex i want to change the text of TextView in Main Activity as soon as i select a checkboxpreference from preference activity.
A stopped, or hidden activity may no longer be present, to free up resources. It is not a good idea to reference objects from other Activities.
To send an event/data from one Activity to another Activity you may use:
Start newer activity using startActivityForResult(). And get results back via onActivityResult().
Share some data is a third object, accessible to all activities. Most likely a singleton or Application class.
Use EventBus and post sticky events. New subscribers will automatically get these events. This method works for all kinds of objects, not just activities.
I'm not sure what you would need this for, it sounds a little dangerous, but the root view probably won't exist without running first, but you MAY be able to get the root view while it's running and pass it to Activity B, but the view shouldn't be active while it's not running, thus will be null.
Create it as static and pass the rootView to it on OnCreate, or pass it to the Application class so it persist between entire application. Verify if its null before doing operations.
I never tryed it, but my guess is that while activity is not finished the rootView can be accesed (its status stays on pause while another activity is active).
Look like you are trying to trigger an action across activities when your preference changed. I suggest to use LocalBroadcastManager to send the message from ActivityB to ActivityA. I assume that your ActivityB is the preference and active activity, and ActivityA is in the back stack:
ActivityB.java
mListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// create your broadcast intent and pass the value of changed preference
Intent intent = ...
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
};
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(mListener);
ActivityA.java
mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// handle your change to ActivityA here
}
};
// create intent filter for your preference change broadcast
IntentFilter intentFilter = ...
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);
Given that your ActivityA is not yet destroyed, it will be able to catch the broadcast and you can achieve what you want.

How to get the activity reference from the ComponentName

I have the ComponentName of a foreground screen activity. I am able to get the context object from the same. But I need the activity instance.
How can I get the activity reference from the ComponentName.
All this code will be written in a service.
Thanks in advance.
You can not get Activity instance from it's component name.You can store Activity instance as static field in a class(when onCreate method of Activity invoked) and get that field in service.
Also what do you want to do with instance of Activity in a Service?
I'd need a little more clarity on what your attempting to do, but possibly a:
class ActivityWatcher using the onActivityStarted method (or similar)
to call a class that watches your view Hierarchy
Watch the parent view and then iterate thru the child views.
This would at least give you all the views from the activities layout that are defined at the time the activity is instantiated.

How to find reference of an Activity from a library and close(finish()) the activity?

Scenario :
An activity is displayed. It has a text box and a button. If you enter a special code in the textbox and click the button the activity closes after comparing the text logic. Simple! This has been implemented in the OnCLick() of the the activity.
Problem :
I have a library that handles all the the SMS receiver functionalities. The receiver remotely listens for a special incoming SMS. Once the special sms arrives, a library function (closeActivity) should either
finish() the activity(described above) straightaway
imitate the action of entering text + clicking button by getting a reference to the activity somehow?
I am fine with either. which ever is simpler and safer!
I just need to know how/where/what code to write in the library so that it can finish() the activity!
Assumption: The activity is always displayed and the system is not stacking it automatically!
Why dont you try to use intents? esp broadcast intents.. Fire the broadcast intent from library and get it in ur activity /another class registered as intent reciever . You can get the instance of activity in the broadcast reciever easily.
public static <Your activity class> activitySingleTon
and set the singleton in appropriate lifecycle method.
OnCreate(){ activitySingleTon = this; }
and use in broadcast reciever like this
if(<your activity class>.activitySingleTon)
{ <your activity class>.activitySingleTon.finish(); }
Can there be several instances of the Activity?
If not, make it a singleton, then reference it from anywhere with MyActivity.getInstance().
Best regards.

Difference between Activity Context and Application Context

This has me stumped, I was using this in Android 2.1-r8 SDK:
ProgressDialog.show(getApplicationContext(), ....);
and also in
Toast t = Toast.makeText(getApplicationContext(),....);
using getApplicationContext() crashes both ProgressDialog and Toast .... which lead me to this question:
What is the actual differences between a activity context and application context, despite sharing the wording 'Context'?
They are both instances of Context, but the application instance is tied to the lifecycle of the application, while the Activity instance is tied to the lifecycle of an Activity. Thus, they have access to different information about the application environment.
If you read the docs at getApplicationContext it notes that you should only use this if you need a context whose lifecycle is separate from the current context. This doesn't apply in either of your examples.
The Activity context presumably has some information about the current activity that is necessary to complete those calls. If you show the exact error message, might be able to point to what exactly it needs.
But in general, use the activity context unless you have a good reason not to.
I found this table super useful for deciding when to use different types of Contexts:
An application CAN start an Activity from here, but it requires that a new task be created. This may fit specific use cases, but can create non-standard back stack behaviors in your application and is generally not recommended or considered good practice.
This is legal, but inflation will be done with the default theme for the system on which you are running, not what’s defined in your application.
Allowed if the receiver is null, which is used for obtaining the current value of a sticky broadcast, on Android 4.2 and above.
This obviously is deficiency of the API design. In the first place, Activity Context and Application context are totally different objects, so the method parameters where context is used should use ApplicationContext or Activity directly, instead of using parent class Context.
In the second place, the doc should specify which context to use or not explicitly.
The reason I think is that ProgressDialog is attached to the activity that props up the ProgressDialog as the dialog cannot remain after the activity gets destroyed so it needs to be passed this(ActivityContext) that also gets destroyed with the activity whereas the ApplicationContext remains even after the activity gets destroyed.
You can see a difference between the two contexts when you launch your app directly from the home screen vs when your app is launched from another app via share intent.
Here a practical example of what "non-standard back stack behaviors", mentioned by #CommonSenseCode, means:
Suppose that you have two apps that communicate with each other, App1 and App2.
Launch App2:MainActivity from launcher. Then from MainActivity launch App2:SecondaryActivity. There, either using activity context or application context, both activities live in the same task and this is ok (given that you use all standard launch modes and intent flags). You can go back to MainActivity with a back press and in the recent apps you have only one task.
Suppose now that you are in App1 and launch App2:MainActivity with a share intent (ACTION_SEND or ACTION_SEND_MULTIPLE). Then from there try to launch App2:SecondaryActivity (always with all standard launch modes and intent flags).
What happens is:
if you launch App2:SecondaryActivity with application context on Android < 10 you cannot launch all the activities in the same task. I have tried with android 7 and 8 and the SecondaryActivity is always launched in a new task (I guess is because App2:SecondaryActivity is launched with the App2 application context but you're coming from App1 and you didn't launch the App2 application directly. Maybe under the hood android recognize that and use FLAG_ACTIVITY_NEW_TASK). This can be good or bad depending on your needs, for my application was bad.
On Android 10 the app crashes with the message
"Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?".
So to make it work on Android 10 you have to use FALG_ACTIVITY_NEW_TASK and you cannot run all activities in the same task.
As you can see the behavior is different between android versions, weird.
if you launch App2:SecondaryActivity with activity context all goes well and you can run all the activities in the same task resulting in a linear backstack navigation.
I hope I have added some useful information
I think when everything need a screen to show ( button, dialog,layout...) we have to use context activity, and everything doesn't need a screen to show or process ( toast, service telelphone,contact...) we could use a application context
Use getApplicationContext() if you need something tied to a Context that itself will have global scope.
If you use Activity, then the new Activity instance will have a reference, which has an implicit reference to the old Activity, and the old Activity cannot be garbage collected.

Categories

Resources