The app I'm coding checks wether there is a special ZIP-File in a Directory under /sdcard and starts to download and unzip it if not. The download and unzip works finde, even with subdirectories. But I need to restart the App when it's done - and that does not work.
At first I have a special Activity "PreMainActivity.java" just for restart purposal:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class PreMainActivity extends Activity
{
/**
*
*/
public static Boolean ENABLE_RESTART = false;
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
PreMainActivity.ENABLE_RESTART = true;
restartMain();
}
#Override
public void onRestart()
{
super.onRestart();
restartMain();
}
/**
*
*/
public void restartMain()
{
if (PreMainActivity.ENABLE_RESTART == true)
{
final Intent mainIntent = new Intent(this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(mainIntent);
finish();
}
else
{
finish();
}
PreMainActivity.ENABLE_RESTART = false;
}
}
then I got some code within the DownloadFile.java
#Override
protected void onPostExecute(final String result)
{
MainActivity.mProgressDialogDownload.dismiss();
PreMainActivity.ENABLE_RESTART = true;
final Intent i = new Intent(MainActivity.this, PreMainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
}
As far as I have researched I need to pass the context of my MainActivity to the DownloadFile.java - but I still have no clue how. Can anyone gibe me a hint how to pass the context to a AsyncTask in a separate file within the same package? Or any other hint how to restart the whole app after a AsyncTask has finished ?
You will need to Create a constructor of the AsyncTask to pass Current Activity Context as:
public Context ctx;
public Your_AsyncTask_Class_Name (Context context){
super();
this.ctx=context;
}
......
#Override
protected void onPostExecute(final String result)
{
MainActivity.mProgressDialogDownload.dismiss();
PreMainActivity.ENABLE_RESTART = true;
final Intent i = new Intent(ctx, PreMainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
}
and from Activity you can pass context as:
AsyncTask_Class_Name asyktaskobj=new AsyncTask_Class_Name(this);
asyktaskobj.execute();
Just restart your main.activity like this:
Intent intent = getIntent();
finish();
startActivity(intent);
See question:
How do I restart an Android Activity
Related
I am working on an online radio app demo. I've created an error Activity which I want to take the user to, when an error occurs. In the error page, there is a refresh button, which is supposed to refresh the last Activity where an error occurred. But I don't know how to get the Intent of previous Activity which led to the error page to get it refresh on ButtonClick, I only know to make it return to a particular Activity.
You can use startActivityForResult in both calling activities
In MainActivity.java
int REFRESH = 1;
private void startErrorActivity() {
startActivityForResult(new Intent(this, ErrorActivity.class), REFRESH);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REFRESH) {
//do refresh
}
}
And in ErrorActivity.java
Button button = findViewById(R.id.refreshButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish(); //this will take you back to calling activities onActivityResult method
}
});
UPDATE:
I honestly think #sneharc's answer is better. Use that.
Try this:
public class ActivityA extends Activity {
public void myFunction(){
try{
// something bad happens here. need to go to ErrorActivity
}
catch (SomeException e){
Intent startErrorActivityIntent = new Intent(this, ErrorActivity.class);
startErrorActivityIntent.putExtra("sourceActivity", ActivityA.class.getSimpleName())
startActivity(this, startErrorActivityIntent)
}
}
}
public class ActivityB extends Activity {
public void myFunction(){
try{
// something bad happens here. need to go to ErrorActivity
}
catch (SomeException e){
Intent startErrorActivityIntent = new Intent(this, ErrorActivity.class);
startErrorActivityIntent.putExtra("sourceActivity", ActivityB.class.getSimpleName())
startActivity(this, startErrorActivityIntent)
}
}
}
public class ErrorActivity extends Activity {
private Intent mReceivedIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
mReceivedIntent = getIntent();
}
public void onClickRefresh(){
String retryActivityName = mReceivedIntent.getStringExtra("sourceActivity");
Intent retryActivityIntent = null;
if (!TextUtils.isEmpty(retryActivityName)){}
if (retryActivityName.equalsIgnoreCase(ActivityA.class.getSimpleName()))
retryActivityName = new Intent(this, ActivityA.class);
if (retryActivityName.equalsIgnoreCase(ActivityB.class.getSimpleName()))
retryActivityName = new Intent(this, ActivityB.class);
}
if (retryActivityIntent != null)
startActivityForResult(this, retryActivityIntent);
}
}
I have an activity in android application and from that I am calling a method of an AsyncTask class which is calling a webservice. I want to reset/reload my activity on the basis of the result i get from that method. How can I reset my activity from that class?
You can try the following
Pass calling Activity context to your AsyncTask in constructor and save it in a variable Context context.
Then in your PostExecute method of AsyncTask, write following lines :
Intent targetIntent = new Intent(context, TargetActivity.class);
// Add your data to intent
targetIntent.putExtra("intent_extra_key", "intent_extra_value");
context.startActivity(targetIntent);
((Activity) context).finish();
Revert back for any issue.
Example:
Note: Remove the comment and delete or use comment for startActivity(i); in onPostExecute(Boolean aBoolean) if you want to test code example below without changing it.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new LoadFromWebAsyncTask(this).execute();
}
private class LoadFromWebAsyncTask extends AsyncTask<Void, Void, Boolean> {
MainActivity activity;
LoadFromWebAsyncTask(MainActivity activity) {
this.activity = activity;
}
#Override
protected Boolean doInBackground(Void... params) {
return true;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
activity.finish();
Intent i = new Intent(MainActivity.this, MainActivity.class);
startActivity(i);
/* final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
activity.finish();
Intent i = new Intent(MainActivity.this, MainActivity.class);
startActivity(i);
}
}, 5*1000);*/
}
}
}
I have an android app. When the user clicks button A and intent is fired like this android-presudocode :)
//inside FirstActivity
#Override
public void onClick(View view) {
startActivity(new Intent(this, AnotherActivity.class));
}
So if I'm not mistaken, the onResume method in AnotherActivity should be called, right?
I use ActivityInstrumentationTestCase2<FirstActivity> to test my activity but I'm unable to instantiate AnotherActivity.
So the question is, how can I test this: 'When a button is pressed, the correct activity is resumed and the correct extras are passed to the intent'.
You can use the instrumentation to make an ActivityMonitor. This will monitor if a new activity has been started.
ActivityMonitor am = getInstrumentation().addMonitor(Activity3.class.getName(), null, true;
Then you want to use button.performClick() to "press the button". Finally, you check if the activity monitor has been hit.
am.waitForActivitywithTimeout(timeout);
assertEquals(1, am.getHits());
I haven't used ActivityInstrumentationTestCase2 in quite a while so I don't guarantee these steps are exactly right. In any case, I recommend that you take a look at Robolectric: a wonderful unit testing framework for Android that will change your life. It will help you overcome many situations that are difficult or impossible to test with any of the default instrumentation tests.
So after some time I want to post the solution that I use almost always.
Initially I liked #aleph_null's solution but it turns out that it makes tests unbearably slow so this is what I use now:
First, I have this interface
/**
* Simple interface to launch other activities.
*/
public interface ActivityLauncher {
/**
* Starts an activity with the Intent provided.
* #param intent an intent
*/
public void start(Context context, Intent intent);
/**
*
* Returns the intent as set by {#link #start(android.content.Context, android.content.Intent) start} or null if not yet
* called.
*
* #return an intent or null
*/
public Intent getIntent();
}
And I have two implementations for it:
/**
* Default implementation of ActivityLauncher
*/
public class DefaultActivityLauncher implements ActivityLauncher{
private Intent intent;
public DefaultActivityLauncher(){}
#Override
public void start(Context context, Intent intent) {
this.intent = intent;
context.startActivity(intent);
}
#Override
public Intent getIntent() {
return intent;
}
}
and
/**
* Mock implementation of ActivityLauncher that simply sets the intent but does not actually starts
* an activity.
*/
public class MockActivityLauncher implements ActivityLauncher {
private Intent intent;
#Override
public void start(Context context, Intent intent) {
this.intent = intent;
}
#Override
public Intent getIntent() {
return intent;
}
}
Then I use a dependency injection framework like Dagger or similar like this:
public class MyActivity {
#Inject ActivityLauncher launcher;
public void onCreate(Bundle bundle){
// some code omitted for brevity
findViewById(R.id.goToOtherActivityButton).setOnClick(new OnClickListener(){
Intent intent = new Intent(getContext(), MyOtherActivity.class);
launcher.start(getContext(), intent);
});
}
public ActivityLauncher getLauncher(){
return launcher;
}
}
Testing is then as simple as checkIntentIsValid(activity.geLauncher().getIntent())
This code might give you a good idea
If you are calling Activity1 --- > Activity2
You can send the UserName by this method
Intent intent = new Intent(getBaseContext(), Activity2.class);
intent.putExtra("UserName ", UserName );
startActivity(intent);
To retrive the Extra() in Activity2, you need this code
String UserName = (String) getIntent().getSerializableExtra("UserName ");
Hope this helps
Below Edit for Better Understanding
public class Activity2 extends Activity {
private String UserName;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_2);
UserName= (String) getIntent().getSerializableExtra("UserName");
Log.i(Tag, "UserName: "+ UserName);
}
// you can call this method from click or where ever you want
private void AnyMethod()
{
Intent intent = new Intent(getBaseContext(), Activity3.class);
intent.putExtra("UserName ", UserName );
startActivity(intent);
}
}
#Override
public void onClick(View view) {
startActivity(new Intent(this, AnotherActivity.class));
}
Your code is not correct in every time.
Example:
btn.setOnClickListener(new OnClickListener(
#Override
public void onClick(View view) {
startActivity(new Intent(this, AnotherActivity.class));
}
));
Please replace this = CurrentActivity.this
It looks like:
#Override
public void onClick(View view) {
startActivity(new Intent(CurrentActivity.this, AnotherActivity.class));
}
Make ensure, your Manifest has this code:
<Activity name=".AnotherActivity">
</Activity>
How do you change activities using DroidGap? Is there a way to get the current context even though we're using DroidGap?
public class MainActivity extends DroidGap {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (isOnline() == true) {
super.loadUrl("http://myurl.com");
}
else {
Intent myIntent = new Intent(SOME CONTEXT...DroidGap.getContext(), LoadScreen.class);
startActivity(myIntent);
finish();
}
}
This solved my problem Intent myIntent = new Intent(getContext(), LoadScreen.class);
I'm new to Android and I'm stuck on a conception problem.
I have an application with several activities, some of those activities are critical and require the user to be logged in a webApp.
When the user clicks a button to reach one of those critical activities, I call a background Service which ask if the user is still connected to the webApp (not timeout). If the user is logged in, the activity is started, otherwise a dialog pops up and ask for username and password. The problem is that there is several protected activities, and I want to use the same service to do the verification. The way I do it for the moment works but it's kind of kludgy.
public class A_Activity extends Activity {
Context context;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getApplicationContext();
setButtonClickListener();
}
private void setButtonClickListener() {
button_1 = (Button)findViewById(R.id.button1);
button_1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intentCall = new Intent(context,com.them.cp.ConnexionManagerService.class);
intentCall.putExtra("WHO_IS_CALLED","FIRST_ACTIVITY");
context.startService(intentCall);
}
});
button_2 = (Button)findViewById(R.id.button2);
button_2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intentCall = new Intent(context,com.them.cp.ConnexionManagerService.class);
intentCall.putExtra("WHO_IS_CALLED","SECOND_ACTIVITY");
context.startService(intentCall);
}
});
}
}
And my service
public class ConnexionManagerService extends Service{
public class IsConnectedAsync extends AsyncTask<String , Void, Void>{
protected Void doInBackground(String... whoIsCalled) {
String redirectedURL = getRedirectedURL();
if(redirectedURL.equalsIgnoreCase(IF_NOT_CONNECTED_URL)){
if(whoIsCalled[0].equalsIgnoreCase("FIRST_ACTIVITY")){
Intent trueIntent = new Intent(getBaseContext(), FirstActivity.class);
trueIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(trueIntent);
}
else if(whoIsCalled[0].equalsIgnoreCase("SECOND_ACTIVITY")){
Intent trueIntent = new Intent(getBaseContext(), SecondActivity.class);
trueIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(trueIntent);
}
}
else{
Intent falseIntent = new Intent(getBaseContext(), PopUpLoginActivity.class);
falseIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(falseIntent);
}
}
return null;
}
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d("service onCreate", "onCreate");
}
public int onStartCommand(Intent intent, int flags, int startId){
String whoIsCalled = intent.getStringExtra("WHO_IS_CALLED");
new IsConnectedAsync().execute(whoIsCalled);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
with my little knowledge I wish i could just send an intent, but it seems that it's not possible as it's not the UI thread.
My question is: What can I do to make this service more generic ?
I want to use the same service to do the verification.
If you don't destroy the service it will be the same service object. If an activity which started your service finishes or stops the service it could be destroyed if it was the unique activity that started the service. If you want to ensure that the service reminds on background start it on you application class (extending Application) and in each activity you need. When an activity stops the service or finishes the service will not be destroyed because your application class is still connected.
EDIT:
To avoid write putExtra again and again:
public class StartOrder1 extends Intent {
public StartOrder(Context ctx, String activity_name){
super(ctx, ServiceName.class);
if(activity_name != null)
super.putExtra("WHO", activity_name);
else
super.putExtra("WHO", "UNKNOWN");
}
public String getWho(){
reurn.getIntExtra("WHO");
}
}
To start it:
this.startService(new StartOrder1(this, "My activity name"));
The best solution:
public class StartOrder2 extends Intent {
public StartOrder(Activity a){
super(a, ServiceName.class);
super.putExtra("WHO", a.toString());
}
public String getWho(){
reurn.getIntExtra("WHO");
}
}
And you can override toString method in each Activity passing the activity name, class name, whatever you want. Then when you start an intent:
this.startService(new StartOrder2(this));
Or extends Activity with this utility:
public class EnhancedActivity extends Activity{
protected startMyService(String name){
Intent i = new Intent(this, MyService.class);
i.putExtra("who", name);
startService(i);
}
}
And call it on your final activity
[...]
super.startMyService("activity_name");
[...]