I am currently working on an android project and I have an activity, lets call it MyActivity and this activity calls a standard Java class called MyClass.
I need MyClass to finish the MyActivity activity but I can't find out how to do this. I thought I might be able to pass the context to the standard java class and call context.finish() but this doesn't appear to be available.
How can I do this, thanks for any help you can offer.
You can pass the Context, but you will need to cast it to an Activity (or simply pass the Activity itself), although this in general seems like a bad practice.
The most secure solution uses listener and a Handler. It is complex, but ensures a non direct call to finish activity.
Your listener:
interface OnWantToCloseListener{
public void onWantToClose();
}
Class that should close activity.
class MyClass {
private OnWantToCloseListener listener;
public void setWantToCloseListener(OnWantToCloseListener listener){
this.listener = listener;
}
private void fireOnWantToClose(){
if(this.listener != null)
listener.onWantToClose();
}
}
When you want to close your activity you must call fireOnWantToClose() method.
public MyActivity extends Activity{
public void onCreate(){
final int CLOSE = 1; //number to identify what happens
MyClass my_class = new MyClass();
final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what == CLOSE)
MyActivity.this.finish();
}
});
my_class.setOnWantToCloseListener(new OnWantToCloseListener(){
public void onWantToClose(){
handler.sendEmptyMessage(CLOSE);
}
});
}
}
This is secure because Activity is not finished directly by MyClass object, it is finished through a listener that orders a handler to finish activity. Even if you run MyClass object on a second thread this code will works nice.
EDIT: CLOSE var added I forget to declare and initialize this.
Pass the MyActivity to MyClass as an Activity. From there you can call myActivity.finish();
For example:
private Activity myActivity;
public MyClass(Activity myActivity){
this.myActivity = myActivity;
}
public void stopMyActivity(){
myActivity.finish();
}
And in MyActivity:
MyClass myClass = new MyClass(this);
This is risky, because you're holding a reference to an Activity, which can cause memory leaks.
If your java class is a nested inner class, you can use:
public class MyActivity extends Activity {
public static class JavaClass {
public void finishActivity() {
MyActivity.finish();
}
}
}
Otherwise you'll have to pass the java class a Context (i.e. pass it a reference to this, since Activity extends Context) and store it as a private instance variable.
Related
I have an Activity:
public class MyActivity extends Activity {
#Override
protected void onDestroy() {
// TODO: send event to other class
}
}
and a separate class:
public class MyClass{
MyClass(Context context){
// I have the context of activity
}
// This needs to be called by MyActivity in all other instantiates
void onActivityDestroy(){
}
}
MyClass is instantiated in other places and I want onActivityDestroy to be called in those instantiates. The place where MyClass is instantiated is not accessible.
I am looking for a solution that uses interfaces, listener, messages... but not static fields.
You can maintain the list of MyClass instances at application level then access that list in OnDestroy method of activity. And execute onActivityDestroy() version of each instance.
You should maintain list of instances in your Application class, whenever MyClass instance is created, you push that instance to the list maintained at Application Class
// this is to push the MyClass instance.
Context.getApplication().getMyClassInstanceList().add(new MyClass());
public class MyActivity extends Activity {
#Override
protected void onDestroy() {
List<Myclass> myClassObjects = Context.getApplication.getMyClassInstaceList();
for(Myclass myclass : myClassObjects)
{
myclass.onActivityDestroy();
}
}
}
I have an Activity in whose onCreate() method i call a Utility function.
This utility functions requires a callback class instance as a parameter, in which it returns the info that i need. this is:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Utility.functionA(new functionACallBack() {
/**
*
*/
private static final long serialVersionUID = -7896922737679366614L;
#Override
public void onResponse(String error) {
((MyActivity) AppClass.getAppContext()).finish();
}
});
}
Once I have obtained that info, I want to close the activity. so i called finish() from inside the anonymous class that i created for the callback.
But the activity is not getting finished. I thought maybe i need to call finish() from UI thread so i did runOnUiThread(), in inside it also i tried calling finish(). But it just doesn't work.
Could someone please help me with this issue?
UPDATE:
I am storing APP context and then trying to use that but to no avail.
public class AppClass extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
AppClass.mContext = getApplicationContext();
}
public static Context getAppContext(){
return AppClass.mContext;
}
}
Simply call something like this:
#Override
public void onResponse(String error) {
((Activity) context).finish();
}
As this is a static function, you'll have to be able to access your Context in a static way. You can save that as a Class variable, but you'll have to be aware about its handling as it might lead to memory leaks.
To avoid them, you can declare a class that extends Application and save here your context, so this way you won't ever have a memory leak.
Try using this code:
((Activity) ActivityClass.this).finish();
Remember, use the Activity class, not the Application one.
I simply have not found a solution to share a real-time data between the activitys. My first activity receives real-time object (type double, a random numbers). And i want to pas this numbers to second activity. It all works, only the second Activity shows only one time the data. I have to refresh the activity by going back to first activity and only then the second activity show the latest data. I implemented a Singelton pattern:
public class FirstActivity extends Activity{
public double xAxis;
public double yAxis;
public static FirstView instance;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.device_view);
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
int data1 = msg.arg1;
xAxis = (double) data1;
dataX.setText(String.valueOf(xAxis));
int data2 = msg.arg2;
yAxis = (double) data2;
dataY.setText(String.valueOf(yAxis));
}
};
secondview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent nextScreen = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(nextScreen);
}
});
}
public static void initInstance(){
if(instance == null)
{
instance = new FirstActivity();
}
}
public static FirstActivity getInstance(){
return instance;
}
}
SecondView class
public class SecondActivity extends Activity{
private double valueX;
private double valueY;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.linegraph);
valueX = FirstActivity.getInstance().xAxis;
valueY = FirstActivity.getInstance().yAxis;
}
}
Application class
package com.bluetoothcomm;
import android.app.Application;
public class MyApplication extends Application {
#Override
public void onCreate(){
super.onCreate();
initSingeltons();
}
public void initSingeltons(){
FirstActivity.initInstance();
}
}
You may implement a background service capable of providing the real time data to Activity1 and also to Activity2. I am guessing that your problem ocurrs if you are passing data from Activity1 to Activity2 through an Intent with putExtras, on this way it will only do this at the moment you start Activity2.
I have found my problem and the solution is to use Application. Only this dose not solves my problem. The problem is that the static variable instance public static FirstView instance is bound to the class loader, the first class that initilize that. So when the static variable inside any class has been initilized by an Activity and when the second Activity is started the first Activity is destroyed, so this means the static variable is also uninitilized. Thats why the SecondActivity dose not gets the up to date data or real time data, it catches only static constant data.
I changed my code a littele bit with the combination of Singelton and Application, couse this way the static variable should never be uninitilized when SecondActivity is activated. But i still get the same results, the static variable instance is uninitilized when i swtich to Second Activity. I am doing somethink wrong, does any one sees it. I added my code.
#Max Rasguido, #Orabig
You should use the intent process. docs
How is your data supposed to change when activity2 is shown, if you say that it's received by activity1 ?
However, I would use a preference, or an attribute of your application class (which is a singleton itself), but you give too little informations to fully understand your needs...
I have a public void in one class and I want to call it in another class when it creates but nothing seems to be working. here is the code of my first activity
public class activityone extends Activity {
public void actionC() {
//actions
}
Does anyone know how to call it in my second class?
In general, you need to have an instance of your activityone class in order to call an instance method.
To create an instance, you generally use a constructor like:
activityone a = new activityone();
a.actionC();
I'm not sure this is what you want though, because Activitys are generally created by the Android system itself and you should handle the onCreate method instead.
Here is what you can do:
public class activityone extends Activity {
/*public void actionC() {*/ //Instead on normal method, write your actions in onCreate()
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//actions
}
and in your second activity, do this:
Intent intent = new Intent(getApplicationContext(),activityone.class);
startActivity(intent);
Hope it helps !!!
I've got one question regarding the intent action ACTION_CALL.
What is the correct way of getting back to the own application/activity after the user ends the call?
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" +m1));
startActivity(intent);
I have made the call using the above code. Please provide me with a solution to call my own activity after the call action.
unfortunately some phones have settings to force going into for example the Call Log after a call...
However, you can run a loop after your startActivity to check TelephonyManager.getCallState, and when it's again TelephonyManager.CALL_STATE_IDLE, you can restart your own Activity
be sure to add some sleep to the loop
AFter the endofcall.......it just had to come back to the activity..!! you can handle that one onRestart();
I run with the same problem, and ended up solving it like this:
Make a Callback interface with single (or multiple if you want)
methods
Implement that interface in your activity
Make a reference to that interface inside PhoneStateListener class
Call a method within that interface when the call ended
public class CallTracker extends PhoneStateListener implements Runnable {
private Context mActivity;
private Callback mCallback;
public interface Callback {
void onCallEnded();
}
public CallTracker(Activity activity) {
super();
mActivity = activity;
if (mActivity instanceof Callback) {
mCallback = (Callback) mActivity;
}
}
#Override public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_IDLE) {
mCallback.onCallEnded();
}
}
public class CallerActivity extends AppCompatActivity implements
CallTracker.Callback {
#Override public void onCallEnded() {
Toast.makeText(this, "Call ended!", Toast.LENGTH_SHORT).show();
}
}