I want to call an Activity A from a Service in Android(and pass some Strings to it). This activity A inturns calls another activity B with startActivityForResult(). Basically, I want my service to wait till the result from activity B is obtained. Please give me some idea of how this implementation can be done(and which flag to set in intent)?
Service:
Intent intent = new Intent(getBaseContext(),ActivityA.class);
intent.putExtra("code",script);
intent.putExtra("type", type);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
ActivityA:
Intent intent = new Intent(this,ActivityB.class);
intent.putExtra("code",code);
intent.putExtra("type", type);
startActivityForResult(intent,REQUEST_CODE);
First Create an interface
public interface MyActions {
public void doActions();
}
Now let your service class implement that interface
public class MyService extends Service implements MyActions{
and override the method
#Override
public void doActions() {
//Some code
}
Now your Activity A is calling B via the startActivityForResult method so override the onActivityResult of A
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Some code
}
In this A class now create a static instance of the interface
static MyActions mActions;
and now write a static method like this
public static void setMyListener(MyActions act){
mActions = act;
}
Now in the onActivityResult that you overrided for class A add this line of code
mActions.doActions();
so you get
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mActions.doActions();
}
Now in your Service class in the onStart() method write this line before calling the activity
ActA.setMyListener(this);
Thats it done now when from Activity B the call goes to onActivityResult of A and from A the Serivce can listen to the overrided method of doActions()
Write all your code in doActions() method of service that you wanted to do
Here is the code
1st Activity : ActA.java
public class ActA extends Activity {
static MyActions mActions;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.act1);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startActivityForResult(new Intent(ActA.this,ActB.class), 15);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("Response","requestCode" + requestCode + " resultCode" + resultCode);
mActions.doActions();
}
public static void setMyListener(MyActions act){
mActions = act;
}
}
2nd Activity : ActB.java
public class ActB extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.act2);
}
}
The MainActivity when app launchs
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Start the service
startService(new Intent(this, MyService.class));
}
}
The Interface : MyActions.java
public interface MyActions {
public void doActions();
}
The Serivce class : MyService.java
public class MyService extends Service implements MyActions{
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("Response", "Started");
ActA.setMyListener(this);
startActivity(new Intent(this,ActA.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
#Override
public void doActions() {
Log.d("Response", "Listener working");
}
}
Related
I have a FragmentActivity that is starting another activity for result. When the called activity finishes, onActivityResult is not called. Does it make a difference that I am using a AppCompatActivity activity (which extends from FragmentActivity)? The documentation says that results will be returned to the calling fragment, and in this case it's not a fragment, it's an activity. Here is the code, very simple:
MainActivity:
public class SMSEmailActivityNew extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setup activity....
Intent i = new Intent(this, EulaActivity.class);
i.putExtra(Globals.keyFileName,Globals.FILE_EULA );
startActivityForResult(i,RESULT_OK);
}
//this method is never called
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//dowork .....
}
}
Called activity:
EulaActivity extends AppCompatActivity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set up activity ....
}
public void onClick(View v) {
Intent result = new Intent();
if (bPermissionGranted) {
setResult(Activity.RESULT_OK, result);
// Determine if EULA was accepted this time
getSharedPreferences().edit().putBoolean(Globals.KEY_EULA_ACCEPTED, true).apply();
} else {
setResult(Activity.RESULT_CANCELED, result);
}
finish();
}
}
According to documentation you need to pass requestId bigger or equal thant 0. In your case RESULT_OK is -1. Also RESULT_OK acts like result code, not like request code and startActivityForResult needs a request code.
Something like this startActivityForResult(intent, 0);
Also finish EulaActivity using finishActivity(yourPreviousRequestCode);, in this case 0.
Try this solution:-
MainActivity.java
//Define variable
public static int REQUEST_CODE = 233;
public class SMSEmailActivityNew extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setup activity....
Intent i = new Intent(this, EulaActivity.class);
i.putExtra(Globals.keyFileName,Globals.FILE_EULA );
startActivityForResult(i, REQUEST_CODE); //Change here
}
//this method is never called
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE) {
if(resultCode == RESULT_OK) {
if(data != null && data.hasExtra("MESSAGE")) {
String resStr = data.getStringExtra("MESSAGE");
Toast.makeText(MainActivity.this, resStr, Toast.LENGTH_SHORT).show();
}
}else if(resultCode == RESULT_CANCELED)
Toast.makeText(MainActivity.this, "Canceled", Toast.LENGTH_SHORT).show();
}
}
}
EulaActivity.java
EulaActivity extends AppCompatActivity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set up activity ....
}
public void onClick(View v) {
Intent result = new Intent();
result.putExtra("MESSAGE","Eula Accepted Set");
if (bPermissionGranted) {
setResult(Activity.RESULT_OK, result);
// Determine if EULA was accepted this time
getSharedPreferences().edit().putBoolean(Globals.KEY_EULA_ACCEPTED, true).apply();
} else {
setResult(Activity.RESULT_CANCELED, result);
}
finish();
}
}
I've got a class which handles a question sequence. It doesn't extend Activity. In the class there is the method:
public class QuizMaster {
public void startQuiz(Activity activity, Model model) {
//switch - case statement using model
Intent intent = new Intent(activity, QuestionTextActivity.class)
activity.startActivityForResult(intent, requestCode);
//other case statements with other intents
}
}
When I call this method from a working activity with
mQuizMaster.startQuiz(this, mModel);
And I finish() the child activity:
Intent returnIntent = new Intent();
returnIntent.putExtra(ARG_SELECTED_CHECKBOX, checkedBox);
setResult(RESULT_CODE, returnIntent);
finish();
it doesn't execute the parent activity's
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
Log.d(LOG_TAG, "OnActivityResult called in SignDetailsActivity. Resultcode is: ");
}
But when I execute the
Intent intent = new Intent(activity, QuestionTextActivity.class)
activity.startActivityForResult(intent, requestCode);
in the actual parent activity file, it does execute the onActivityResult method.
Why doesn't the child activity run the onActivityResult in the parent activity if sent with a non-activity class? How do i fix this?
I haven't found anyone with the same problem with executing new Intent() in a non-activity class like this. If there is someone, i didn't use the right search keywords and some others might type in the same as I did and come on this page.
You need to call setResult(int) before call finish(). This is from Activity documentation:
When an activity exits, it can call setResult(int) to return data back
to its parent. It must always supply a result code, which can be the
standard results RESULT_CANCELED, RESULT_OK, or any custom values
starting at RESULT_FIRST_USER. In addition, it can optionally return
back an Intent containing any additional data it wants. All of this
information appears back on the parent's Activity.onActivityResult(),
along with the integer identifier it originally supplied.
Here is my implementation, which worked:
MainActivity.java (parent activity)
public class MainActivity extends AppCompatActivity {
private Sample sample;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sample = new Sample();
sample.startActivity(MainActivity.this);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("TEST", "DONE");
}
}
LaunchActivity.java (child activity)
public class LaunchActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch);
Button btn = (Button) findViewById(R.id.button2);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setIntent(new Intent());
finish();
}
});
}
}
Sample.java (class start activity)
public class Sample {
public Sample () {}
public void startActivity (Activity a) {
Intent it = new Intent(a, LaunchActivity.class);
a.startActivityForResult(it, 0);
}
}
I have an Activity A that uses an intent to go to Activity B. Sometimes Activity A start also another activity, Activity C.
Is there a way for Activity A to know from which Activity (B or C) it is restarted when these activities finish?
You could use method startActivityForResult instead of startActivity to start your activity B or C. If B or C than returns a result that identifies itself you can read it.
From your Activity A, call following methods, suppose you have two buttons and on click of them start Activity B or Activity C:
public void StartOtherActivityB() {
Intent aIntent = new Intent(LauncherActivity.this, OtherActivityB.class);
startActivityForResult(aIntent, REQUEST_ACTIVITY_B);
}
public void StartOtherActivityC() {
Intent aIntent = new Intent(LauncherActivity.this, OtherActivityC.class);
startActivityForResult(aIntent, REQUEST_ACTIVITY_C);
}
and implement onActivityResult() method as follows
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_ACTIVITY_B){
//class restarted from ACTIVITY_B
}else if (requestCode ==REQUEST_ACTIVITY_C){
//class restarted from ACTIVITY_C
}
}
Use a static variable to store the last activity started, so when activity A is resumed, you can check it.
private boolean isB = false;
public void startActivity(Class<?> activityName){
Intent intent = new Intent(this, activityName);
isB = activityName.getName().equals(B.class.getName());
startActivity(intent);
}
like Juanjo Vega said,
use the activitylifecycle methods to do this.....
take a look at the methods....
LifecycleMethods-android
you can set up a global variable or something (as per your logic) in the onResume() method of the activity which you want to get notified. onResume() will cal after onPause which trigger your logic...
for setting up globals you can use singleTons or the Application class
check out your self , you will come to know easily
public class MainActivity extends Activity {
Button clikBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("onCreate", "111111111");
Toast.makeText(MainActivity.this,"onCreate...",Toast.LENGTH_LONG).show();
setContentView(R.layout.activity_main);
clikBtn = (Button)findViewById(R.id.clickBtn);
/*clikBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
}
});*/
}
public void clickButton(View v){
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
#Override
protected void onStart() {
super.onStart();
Toast.makeText(MainActivity.this,"onStart...",Toast.LENGTH_LONG).show();
Log.e("onStart","999999999");
}
#Override
protected void onPause() {
super.onPause();
Toast.makeText(MainActivity.this,"onPause...",Toast.LENGTH_LONG).show();
Log.e("onPause", "222222222");
// notify("onPause");
}
#Override
protected void onResume() {
super.onResume();
Toast.makeText(MainActivity.this,"onResume...",Toast.LENGTH_LONG).show();
Log.e("onResume", "333333333");
//notify("onResume");
}
#Override
protected void onStop() {
super.onStop();
Toast.makeText(MainActivity.this,"onStop...",Toast.LENGTH_LONG).show();
Log.e("onStop", "444444444");
//notify("onStop");
}
#Override
protected void onDestroy() {
super.onDestroy();
Toast.makeText(MainActivity.this,"onDestroy...",Toast.LENGTH_LONG).show();
Log.e("onDestroy", "55555555");
//notify("onDestroy");
}
#Override
protected void onRestart() {
super.onRestart();
Toast.makeText(MainActivity.this,"onRestart...",Toast.LENGTH_LONG).show();
Log.e("onRestart","66666666");
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Toast.makeText(MainActivity.this,"onRestoreInstanceState...",Toast.LENGTH_LONG).show();
Log.e("onRestoreInstanceState", "777777777");
//notify("onRestoreInstanceState");
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Toast.makeText(MainActivity.this,"onSaveInstanceState...",Toast.LENGTH_LONG).show();
Log.e("onSaveInstanceState", "8888888888");
//notify("onSaveInstanceState");
}
}
I put setResult(200) in onCreate() at the child activity.
But once I call finishActivity() from the parent, I got resultCode 0.
I Don't know How to explain this situation.
04-25 11:52:55.191: D/TEST(28141): onActivityResult 1000 : 0 : null
The parent is :
public class Main extends Activity {
Button b;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(Main.this, Popup.class);
startActivityForResult(intent, 1000);
new Timer().schedule(new TimerTask() {
#Override
public void run() {
Main.this.finishActivity(1000);
}
}, 1000);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("TEST", "onActivityResult " + requestCode + " : " + resultCode + " : " + data);
super.onActivityResult(requestCode, resultCode, data);
}
}
Child :
public class Popup extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(200);
}
}
UPDATE :
I got understand that onActivityResult() will be called, when the child activity ends.
And calling finishActivity() won't get the ActivityResult of child activity.
But I want to know correct way to get the ActivityResult(resultCode and intent data) once the child activity is destroyed by parent activity.
And Is there any reason to shouldn't do this like bellow code? (I'm just curious.)
Because It seems work fine.
I coded like this :
public class Main extends Activity {
Button b;
public static boolean closePopup = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
closePopup = false;
Intent intent = new Intent(Main.this, Popup.class);
startActivityForResult(intent, 1000);
new Timer().schedule(new TimerTask() {
#Override
public void run() {
closePopup = true;
}
}, 1000);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("TEST", "onActivityResult " + requestCode + " : " + resultCode + " : " + data);
super.onActivityResult(requestCode, resultCode, data);
}
}
public class Popup extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCloseHandler.sendEmptyMessage(0);
}
Handler mCloseHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (Main.closePopup == true) {
Popup.this.finish();
} else {
mCloseHandler.sendEmptyMessageDelayed(0, 100);
}
}
};
#Override
public void finish() {
setResult(200);
super.finish();
}
}
In your Popup activity use
if(null != getParent())
getParent().setResult(200);
else
setResult(200);
instead of just setResult(200);
As you need to bind the data to parent activity and set the Result.
UPDATE:
Understand the difference between finish() and finishActivity (int requestCode)
finish ()
Call this when your activity is done and should be closed. The
ActivityResult is propagated back to whoever launched you via
onActivityResult().
finishActivity (int requestCode)
Force finish another activity that you had previously started with
startActivityForResult(Intent, int).
So in your case you are calling finishActivity on Main which is finishing the child activity Popup. Hence you are getting result code as 0 and intent as null (default values) as the data is not propagated back to Main (Parent).
I suggest you to modify your code as follows and try:
Remove timer block ie. call to finishActivity.
call finish() after setResult(200); in Popup.
if(null != getParent())
getParent().setResult(200);
else
setResult(200);
finish();
UPDATE 2 :
Let me explain it further.
When you start the activity with the startActivityForResult() method call, and once the sub-activity ends, the onActivityResult() method on the sub-activity is called and you can perform actions based on the result.
The started activity(sub-activity) can also set a result code which the caller can use to determine if the activity was canceled or not.(Your case)
The sub-activity uses the finish() method to create a new intent and to put data into it. It also sets a result via the setResult() method call.
If the sub-activity is finished, it can send data back to its caller via an Intent. This is done in the finish() method. So you can override finish method as follows.
#Override
public void finish() {
// Prepare data intent
Intent data = new Intent();
// Put data in intent
// Activity finished, return the data
setResult(200, data);
super.finish();
}
My application have 3 tabs. In this one tab have multiple activities(means this tab have navigation to the child tabs). I used the startActivityforResult() in one child activity. But control never goes to onActivityResult() method. How to implement this. please can anybody help me.
code
public class Activity_1 extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View contentView = LayoutInflater.from(getParent()).inflate(R.layout.static_search_filters, null);
setContentView(contentView);
states_tv = (TextView)findViewById(R.id.state);
states_tv.setOnClickListener(states_etListener);
}
private OnClickListener states_etListener = new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(getParent(), RB_CategoriesMList.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent,GET_SEL_STATES_LIST);
}
};
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//I do some stuff here
}
}
//Activity_2
public class RB_CategoriesMList extends ListActivity
{
public Button sbtn;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.categories_list);
sbtn =(Button)findViewById(R.id.submit_categories);
sbtn.setOnClickListener(sbtn_listener);
}
private OnClickListener sbtn_listener = new View.OnClickListener()
{
public void onClick(View v)
{
Intent state_intent = getIntent();
state_intent.putExtra("selected_states", "");
setResult(RESULT_OK,state_intent);
finish();
}
};
}
Dont call
super.onActivityResult(requestCode, resultCode, data);
When you receive the onActivityResult, check if the request code is your and then do your stuff. In the other cases you should call the super.
So:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == GET_SEL_STATES_LIST) {
// Do your stuff
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
getParent().startActivityForResult(yourNewIntent, yourResult);