Okey, this is weird.
I have two activities (well, more than two, but they don't matter) - AppActivity and PopupActivity. AppActivity is my main application activity and it contains my app's settings. PopupActivity is a dialog that gets opened when user clicks the button in the notification (it's a RemoteViews notification). Well, it works. Works great. But only if user closed the AppActivity by clicking the back button. If they clicked home, PopupActivity opens after a few seconds after clicking the button. Same thing happens when user closes the PopupActivity with a home button. Clicking the button in the notification doesn't open the PopupActivity instantly, but it takes a few seconds to kill the previous activity that still exists somewhere in the background.
I've tried calling finish() in the onStop and onPause methods, but it doesn't fix my problem.
Edit: Here's the code I have:
Manifest:
<activity
android:name="cc.lupine.quicksocial.AppActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize" android:noHistory="true" android:clearTaskOnLaunch="true" android:finishOnTaskLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:configChanges="orientation|screenSize"
android:excludeFromRecents="true"
android:showOnLockScreen="false"
android:theme="#android:style/Theme.Holo.Light.Dialog.NoActionBar.MinWidth"
android:name="cc.lupine.quicksocial.PopupActivity"
android:noHistory="true"
android:launchMode="singleInstance"
android:taskAffinity=""
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service android:name="cc.lupine.quicksocial.ShareService"></service>
ShareService.java (just a function that gets called when user clicks a button in the notification):
public static void startSharing(Context ctx, int n) {
Log.d("sn", "startsharing called in shareservice");
if(n == 1 || n == 2)
{
Intent i = new Intent(ThisApplication.getAppContext(), PopupActivity.class);
i.putExtra("shareType", n);
i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY|
Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_SINGLE_TOP|
Intent.FLAG_ACTIVITY_CLEAR_TASK|
Intent.FLAG_FROM_BACKGROUND|
Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(i);
} else if(n == 3) {
// doesn't matter for now
}
}
PopupActivity.java (fragments):
public class PopupActivity extends Activity implements OnDataPass {
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("sn", "oncreate called in popupactivity");
super.onCreate(savedInstanceState);
instanceOfPopupActivity = this;
setContentView(R.layout.activity_popup);
ShareFragment sfrag = new ShareFragment();
Bundle args = new Bundle();
Bundle extras = getIntent().getExtras();
try {
//doesn't matter
} catch(Exception e) { e.printStackTrace(); finish(); }
sfrag.setArguments(args);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.contFragment, sfrag);
fragmentTransaction.commit();
}
#Override
public void onPause()
{
Log.d("sn", "onpause called in popupactivity");
finish();
super.onPause();
}
#Override
public void onStop() {
Log.d("sn", "onstop called in popupactivity");
super.onStop();
}
#Override
public void onDestroy()
{
Log.d("sn", "ondestroy called in popupactivity");
super.onDestroy();
}
}
And if I open the popup for the first time:
05-26 14:37:14.149: D/sn(7218): startsharing called in shareservice
05-26 14:37:14.179: D/sn(7218): oncreate called in popupactivity
But when I close the popup with a home button and try to open it again:
05-26 14:38:11.620: D/sn(7218): startsharing called in shareservice
05-26 14:38:14.103: D/sn(7218): oncreate called in popupactivity
It takes a lot of time for onCreate to be called. And now, what's the reason?
I think you are focusing on the wrong problem (killing the activity) instead of focusing on the real problem (10 seconds to start it again).
First you need to understand WHY it is taking 10 seconds to open it if you exited the other acitivty with the home key!
If you posted more details (with source code) it would have been easier to understand and help you!
call finish() when you want to close app. Call finish() on both activities and watch out popup window has to be focusable to handle click.
Related
I have created this simple splash screen ;
public class Splashscreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splashscreen);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(Splashscreen.this, MainActivity.class);
startActivity(i);
finish(); } }, 1000);
}
}
I declared the splash screen to be the first screen that opens like this;
<activity android:name="com.androidhunger.opendagapp.Splashscreen"
android:noHistory="true"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"><intent-
filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter></activity>
After the splash screen my mainactivity opens a fragment with menu code inside of it, but I don't think the problem lays there. My problem is, when I open my app and the splash screen is done, and i've loaded my first screen, when I press back once, it takes me to a blank page. I can't recreate it here with easely, but I hope someone recognizes the issue.
you need to clear your activity stack before you start new activity
Intent i = new Intent(Splashscreen.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
I have the following Problem: I want to create a Splash Screen, that I can call during my Game Loop (it is a "Next-Level" splash screen).
When I call the Splash Screen, it works with animation and everything but the app minimizes itself after 5 seconds. This Splash Screen call happens after the main activity was already started.
My SplashActivity looks like this:
public class SplashActivity extends AppCompatActivity {
private ImageView logo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
logo = findViewById(R.id.logo);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 5000);
Animation anim = AnimationUtils.loadAnimation(this, R.anim.viewanimation);
logo.startAnimation(anim);
}
}
And I want to call it in my GameLoop with the following call:
Intent i = new Intent(gamePanel.getContext(), SplashActivity.class);
gamePanel.getContext().startActivity(i);
The SplashScreen opens and the animation works, but then the MainActivity should be present again (not started new).
Try this one Splash.java
public class Splash extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
Thread myThread=new Thread(){
#Override
public void run() {
try {
Animation anim = AnimationUtils.loadAnimation(this, R.anim.viewanimation);
logo.startAnimation(anim);
//sleep time after animation
sleep(3000);
//to end the splash screen and call next activity with Intent
finish();
Intent intent = new Intent(Splash.this,MainActivity.class);
startActivity(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
myThread.start();
}
}
In your manifest file, Splash.java will be your first activity to launch,
<activity android:name=".Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Hope it helps.
using finishActivity() instead of finish().
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) is used to finish another activity that you had previously started with startActivityForResult(Intent, int)
I have an app with two activities: MainActivity, which contains a URL entry field where the user can enter a YouTube video URL and press a submit button, to start the second activity, VideoActivity, which displays some information about this video (fetched from another web server).
The app also has a feature to receive intent via the Youtube application. When user presses the share button within the Youtube app, my app appears in the share list. Upon pressing share from the Youtube app, MainActivity should be brought to the front, and the URL should be posted within the MainActivity's URL field.
However, this only happens correctly on the first share. If the app is in the background when user shares from Youtube app, they are taken to whatever the last visible activity was, whether it is MainActivity or VideoActivity, (and even if it is MainActivity, the URL is not posted into the URL field, but the field is left in whatever state it was in when the app was last visible).
Here is my current AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youcmt.youdmcapp">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<activity
android:name=".VideoActivity"
android:parentActivityName=".MainActivity"/>
<service
android:name=".FetchVideoService"
android:exported="false"/>
</application>
</manifest>
Here is my MainActivity.java code:
public class MainActivity extends AppCompatActivity {
private ResponseReceiver mReceiver;
private EditText mUrlEditText;
private Button mSearchButton;
private ProgressBar mProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
super.onCreate(savedInstanceState);
mUrlEditText = findViewById(R.id.url_search_et);
Intent intent = getIntent();
if (intent.getType()!=null &&
intent.getType().equals("text/plain")) {
Bundle extras = getIntent().getExtras();
String value = extras.getString(Intent.EXTRA_TEXT);
if(value!=null)
{
mUrlEditText.setText(value);
}
}
mProgressBar = findViewById(R.id.progress_bar);
mSearchButton = findViewById(R.id.search_button);
mSearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
askForVideo(mUrlEditText.getText().toString());
mSearchButton.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
} catch (Exception e) {
mUrlEditText.setText("");
mUrlEditText.setHint(e.getMessage());
e.printStackTrace();
}
}
});
}
#Override
protected void onResume() {
super.onResume();
//register the ResponseReceiver
mReceiver = new ResponseReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(FETCH_VIDEO_INFO);
registerReceiver(mReceiver, intentFilter);
}
private void askForVideo (String url) throws Exception {
try {
Intent intent = FetchVideoService.newIntent(this, url);
startService(intent);
} catch (Exception e) {
mUrlEditText.setText(e.getMessage());
}
}
public class ResponseReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(EXTRA_VIDEO_STATUS, FAIL);
mProgressBar.setVisibility(View.INVISIBLE);
mSearchButton.setVisibility(View.VISIBLE);
if(status==FAIL)
{
mUrlEditText.setText("");
mUrlEditText.setHint("Error retrieving video!");
}
else if(status==SUCCESS) {
Video video = intent.getParcelableExtra(EXTRA_VIDEO);
Intent videoActivityIntent =
VideoActivity.newIntent(getApplicationContext(), video);
startActivity(videoActivityIntent);
}
}
}
#Override
protected void onPause() {
unregisterReceiver(mReceiver);
super.onPause();
}
}
I do not think any of the other files will be useful in understanding the problem. Although this seems like something many app creators should have to deal with, I can find no answers to this problem. Please comment if you feel I should add any additional information and thank you in advance for any help!
Update: testing demonstrates that after the first use of "Share" from YouTube (and considering app remains in the background), the MainActivity no longer receives any new intent on further shares. However, my app is still brought to the foreground somehow. This is very confusing to me.
When you share from another app, your MainActivity is brought to the front and onNewIntent() is called on it. You don't override onNewIntent() so you never see the share Intent.
I'm testing my mobile phone how many intents can be created in parallel but only one is created...
This is my app manifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".IntentExamples"
android:exported="false"
android:launchMode="standard"
android:parentActivityName=".MainActivity">
</activity>
</application>
And this is the class where I do all the calls...
public class IntentExamples extends AppCompatActivity {
// Numbers of intents created
static int COUNTER = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_examples);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// When a intent is created +1 to the counter
COUNTER++;
((TextView) findViewById(R.id.intent_counter)).setText("NUMBER OF INTENTS: " + COUNTER);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.another_intent:
Intent intent = new Intent(IntentExamples.this, IntentExamples.class);
startActivity(intent);
case android.R.id.home:
this.finish(); break;
default:
return false;
}
return true;
}
#Override
protected void onDestroy() {
super.onDestroy();
// When a intent is completely destroy, -1 to the counter
COUNTER--;
}
The main activity just have a copy pasted code from the menu's code...
When I hit the item menu that creates another intent, in the TextView shows 1 intent created, I hit it again, shows 2 intents created and when I hit the button a 3rd time it got stuck in 2 intents created... I don't understand the reason why the counter doesn't reach 3 intents created or more.
Take a look at this code from onOptionsItemSelected()
switch(item.getItemId()){
case R.id.another_intent:
Intent intent = new Intent(IntentExamples.this, IntentExamples.class);
startActivity(intent);
case android.R.id.home:
this.finish(); break;
default:
return false;
}
There is no break; after startActivity(), so the Activity finishes. So eventually (not necessarily immediately!) onDestroy() is called and COUNTER-- is executed.
Because the Activity has called finish(), it is not possible to reach it once more by pressing BACK - and this "misbehaviour" was what I could not explain in the first place. I was ready to believe that the Runtime would keep at most two Activity instances alive and store all the others in the BackStack. But not being able to go back? There had to be an explanation for this - and I'm kind of relieved I've found it :)
Now why does COUNTER show 1 instead of 2 after rotating the device?
That's because an orientation change (like all configuration changes) causes all Activity instances to be destroyed, and the one which was shown is instantly recreated.
Assume i have activity A that act as the root activity for my app . and form this activity i go to activity B.
I want to be able to go back from B to A Without creating new instance of Activity A.
this code is in Activity B
public void onBackPressed() {
super.onBackPressed();
// Intent intent= new Intent(getBaseContext(), MainActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Intent myIntent = new Intent(getBaseContext(), MainActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(myIntent);
Log.d("Back", "TEST");
}
but it sill call the onCreate on activity A . What i want to do is have A in the background when activity b is started and whenever it is finished switch back to activity A
this is the manifest
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:screenOrientation="unspecified"
android:launchMode="singleTask"
android:stateNotNeeded="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:label="#string/app_name"
android:name=".SubmenuActivty" >
</activity>
According to android activity life cycle, when you launch an activity A :
Life Cycle method list :
Activity A.onResume();
Activity A.onStart();
Activity A.onCreate();
Activity Status :
Activity A : Resumed
When you launch the activity B now :
Life Cycle method list :
Activity A.onStop();
Activity B.onResume();
Activity B.onStart();
Activity B.onCreate();
Activity A.onPause();
...
...
...
Activity Status :
Activity A : Stopped
Activity B : Resumed
And when you again start A now :
Life Cycle method list :
Activity B.onDestroy();
Activity B.onStop();
Activity A.onResume();
....
....
....
Activity Status :
Activity B : Destroyed
Activity A : Resumed
This is the life cycle of an activity :
You can find the details here
According to default behavior, activity A goes to onStop() state and doesn't alive and need to create a new instance on coming back to activity A. All I know - there is no way to keep alive of the A instance.
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Try it... It makes old activity to front without new instance...
You Dont need do anything. Just remove your onBackPressed() method from Activity B.
By default when you move from Activity A to Activity B, Android adds the Activity A to the backstack. When you press the back button from Activity B or finish it, it automatically restore the Activity A from backstack.
If you wish to finish your Activity B programmatically call activity's finish() method when you want to do it.
Try this
public void onBackPressed() {
super.onBackPressed();
Log.d("Back", "TEST");
}
And thats all, what you need.
Use moveTaskToBack(true);
public void onBackPressed() {
// TODO Auto-generated method stub
moveTaskToBack(true);
super.onBackPressed();
}
or You can also use finish()
Why you start an activity in onBackPressed anyway?
You should super.onBackPressed(); instead of starting new activity. Or call finish() method in you onBackPressed() method:
public void onBackPressed() {
finish();
Log.d("Back", "TEST");
}