I use BroadcastReceiver for manage my app behaviour when incoming call.
I need to access to object instantiated in my MAIN activity.
In my main activity I create an object with any method that I need to execute in BroadcastReceiver.
How can I access to it ?
Any object you add in intent and send through broadcast, your object must implement Parcelable
Try to create a new class which extends Application, in this class create a global variable with getter and setter methods
public class MyApplication extends Application
{
private YourTypeObject object;
public void setObj(YourTypeObject obj )
{
object=obj;
}
public YourTypeObject getObj()
{
return object;
}
...
}
In your MAIN activity you can use
...
YourTypeObject myobj=....
MyApplication application = (MyApplication) this.getApplication();
application.setObj(myobj);
...
Now in your another Activity you can use
...
MyApplication application = (MyApplication) this.getApplication();
YourTypeObject obj=getObj();
...
Related
In manifest file, I set:
<application android:name=".MyApplication" />
But in activity when I call:
getApplication()
it returns android.app.Application instance not MyApplication instance.
I think it causes by I am using Dagger2. I am new to dagger2
The better way to access to application instance — property in your Application class.
Java example:
class App extends Application {
private static App instance;
#Override
public void onAttachBaseContext(Context newBase) {
super.onAttachBaseContext(newBase);
this.instance = this;
}
public static App getInstance() {
return this.instance;
}
}
Your MyApplication is a child class of android.app.Application, getApplication() returns it as an Application instance, but it is actually your class. That's use of inheritance. You need to process it further, by
MyApplication myApp = null;
Application app = getApplication();
if (app instanceOf MyApplication) {
myApp = (MyApplication) app;
}
or you can simply do
MyApplication myApp = (MyApplication) getApplication();
I have extended the Application object as MyApplication and the design is as follows
public class MyApplication extends Application {
private MyObject myObject;
public MyApplication () {
mInstance = this;
}
public static MyApplication getInstance() {
return mInstance;
}
public MyObject getMyObject(){
return myObject;
}
public setMyObject(MyObject object){
myObject = object;
}
}
I am accessing the myObject value in Activities as well as Services as MyApplication.getInstance().getMyObject(). I don't see any issue with this normally, but in production for few users sometimes suddenly getMyObject() is returning null i.e getting reset. First I was under the impression that the OS might be killing and re-creating the app due to which I am observing null. I am not avoiding the memory low scenario, however if that is the case it should be killing the Activities and the Services too before destroying the Application object.
Inside an Activity I am keeping a reference of MyApplication as
private MyApplication myApp = MyApplication.getInstance();
So this is how my observation from logs regarding the getMyObject() value.
myApp.getMyObject() prints != null
then a Service MyService gets called and inside that
MyApplication.getInstance().getMyObject() prints == null
again back in the activity myApp.getMyObject() or MyApplication.getInstance().getMyObject() prints != null
myObject has been initialized before printing these logs and in between these logs there is no myObject reset code getting called.
Can it happen that the Application object got re-created but the Acitivty is still active?
or
Can Service get a different instance of Application than that of the Activity thread?
As per my understanding in a app life-cycle myApp should always be equal to MyApplication.getInstance() as OS should maintain single instance of Application.
Note: Also would like to add that I am getting this un-usual behavior in Samsung Tab 4.
Don't store Data in the Application Object
The applicataion object will not stay in memory forever. When a user sends your application to the background by e.g. pressing the home button the application object might be killed if the system requires the memory. This might happen after minutes but could take hours. When the user then resumes the application the application object might not be the same as before and mMyObject will be null if it has no initial value.
Solutions
Make null checks and act accordingly
Use some form of data-storage
Initialize your object in the application constructor
public MyApplication () {
mInstance = this;
mMyObject = new MyObject()
}
You don't wanna have public constructor, but a onCreate() method.
You also want a static instance of the class.
public class MyApplication extends Application {
private MyObject myObject;
private static MyApplication mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static MyApplication getInstance() {
return mInstance;
}
public MyObject getMyObject(){
return myObject;
}
public setMyObject(MyObject object){
myObject = object;
}
}
And of course change your manifest to tell that's this is your class that will handle the application (if not done yet)
<application
android:name="com.XXX.MyApplication"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
Is it possible to make an activity singleton?
I have found many resources that just tell to use android:launchMode="singleInstance" or singleTask, but I would constructor to be called only once.
Ideally, I would like to be able to specify custom constructor/builder method e.g. getInstance()
You could store your references in Application instead of an Activity. The application class is de facto a singleton. You only need to define your access methods.
public class BaseApplication extends Application {
private static BaseApplication sInstance = null;
public synchronized static BaseApplication getInstance() {
return sInstance;
}
public synchronized static void setInstance(BaseApplication app) {
sInstance = app;
}
public BaseApplication() {
}
#Override
public void onCreate() {
super.onCreate();
setInstance(this);
}
Now you can access it by calling BaseApplication.getInstance(). As a bonus the Application extends Context so now you have an application context reference anywhere you want (safe to use pretty much everywhere except inflating layouts).
Don't forget to define this class as the base application class in your manifest:
<application
android:name="com.yourapp.BaseApplication">
Usually they do as follows:
1) define what comprise the Activity state
2) Save the state in onSaveInstanceState
3) Restore the state in onCreate or in onRestoreInstanceState
Good day,
I have my main activity with an object,
public Network netConnection = null;
in my main activity i then call:
netConnection = new Network(new Network.OnMessageReceived() {
#Override
// here the messageReceived method is implemented
public void messageReceived(String message) {
// this method calls the onProgressUpdate
publishProgress(message);
}
});
netConnection.run();
Now i create a new activity and i run it with this code:
case R.id.menu_packet: {
Intent intent = new Intent(this, PacketActivity.class);
String id = "" + hashCode();
intent.putExtra("id", id);
startActivity(intent);
return true;
}
I have tried doing things with putExtra() in the intent etc. But i have not come right.
Is there not an easy way to just pass a reference to PacketActivity of my netConnection ?
I don't want to copy it or any thing. just be able to access the netConnection object from the PacketActivity?
Thanks
You can extend Application, create setter and getter method in your extended application, and then call it from new activity.
here a tutorial
useful links:
Extending Application
Extending Application to share variables globally
Android extends Application basics
e.g.
public class myApplication extends Application{
private myType myObj;
public void set_myObj(myType theThing){
myObj = theThing;
}
public myType get_myObj(){
return myObj;
}
}
then from you main activity:
((myApplication)getApplication()).set_myObj(myObj);
and from second activity:
myType myObj = ((myApplication)getApplication()).get_myObj();
and be careful with memory leaks..!
This sounds like a use case for a service:
http://developer.android.com/reference/android/app/Service.html
The thing is once the activity from which you created the Network object is destroyed e.g. to launch the new Activity then the Network object will also be garbage collected so I don't think passing a reference would help...
I have created a custom application class like this:
class A extends android.app.Application{
public String abc = "xyz";
}
And I have a simple java class
class B {
private appContext;
// This constructor is called from activity.
B(Context ctx){
this.appContext = ctx;
}
private void foo(){
// want to access Class A's abc String vairable Here...HOW TO DO THAT?????
}
}
How to access Class A's abc String vairable in foo method.
You can get the Application class with getApplicationContext from Context with the good casting
((A) this.ctx.getApplicationContext()).abc;
The Application class in Android is a singleton and therefore so is your derived class. Android will create just one instance of your class A when it starts your application. Just change
class A extends android.app.Application {
public String abc = "xyz";
}
to
class A extends android.app.Application {
public static String abc = "xyz";
}
and you can reference it from anywhere like this:
String foo = A.abc;
Instead of passing a Context, try passing an instance of the Application class instead.
Something like:
class B {
private Application app;
// This constructor is called from activity.
B(Application ctx){
this.app = ctx;
}
private void foo(){
app.abc; //Do what you want
}
}
And call B like:
B b = new B(getApplication());
Make sure that this is in onCreate() or later.
Looks like you are already passing the application context as a parameter and initializing it in the constructor. So all you have to now is to use the context variable to access abc of A like the following way: ((A) this.appContext).abc;