A.java
public class A extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(A.class.getName(), "OnCreate");
Intent intentB = new Intent(this, B.class);
intentB.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intentB);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(A.class.getName(), "onActivityResult");
}
}
B.java
public class B extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(B.class.getName(), "OnCreate");
Intent imagesIntent = new Intent(Intent.ACTION_GET_CONTENT);
imagesIntent.setType("image/*");
Intent openGalleryIntent = Intent.createChooser(imagesIntent, "pic");
startActivityForResult(openGalleryIntent, 2);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(B.class.getName(), "onActivityResult");
Log.d(B.class.getName(), data.getData().toString());
}
}
AndroidMenifest.xml
<uses-sdk android:minSdkVersion="8" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".A"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="B"></activity>
</application>
The problem is after selecting image from gallery, onActivityResult() method of class B class does not execute.
Though if intentB.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY) is removed from intentB instance then onActivityResult() of class B executes fine.
This is the correct behavior. When you select FLAG_ACTIVITY_NO_HISTORY as the flag while calling the next activity. The child activity is removed from the stack and hence once you move out it would simply finish.
Reference
The question is why do you even want to use that flag?
Related
So I am authenticating the user via GitHub account using OAuth from browser. But after I fire the Intent from LoginActivity, the onResume() gets executed before the user opens the browser, thus returning the value of uri equals null.
Here is the LoginActivity:
public class LoginActivity extends AppCompatActivity {
Button loginButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
loginButton = findViewById(R.id.button);
final String url = "oauth url...";
Log.d("called","oncreate");
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("called","onclick");
attemptLogin(url);
}
});
}
private void attemptLogin(String url){
Log.d("called","onattempt");
Intent intent = new Intent(this, BrowserActivity.class);
intent.putExtra("URL", url);
startActivityForResult(intent, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = data.getData();
String code = uri.getQueryParameter("code");
Log.d("called",code);
}
}
BrowserActivity:
public class BrowserActivity extends AppCompatActivity {
public static String CALLBACK_URL = "callback url..";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_browser);
Intent intent = getIntent();
if(intent != null){
String url = intent.getStringExtra("URL");
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
}
#Override
protected void onResume() {
super.onResume();
Uri uri = getIntent().getData();
if(uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String code = uri.getQueryParameter("code");
Intent intent = new Intent();
intent.putExtra("code",code);
setResult(RESULT_OK, intent);
finish();
}
}
}
LoginActivity in AndroidManifest.xml:
<activity
android:name=".ui.activities.LoginActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activities.BrowserActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="callback"
android:scheme="app"
/>
</intent-filter>
</activity>
First, you start the browser with
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivityForResult(intent, 1);
this intent does not return any result. It only request the browser to show the url. So the browser does not returning any result.
However, after authentification, the browser trigger an intent and request for a new instance of LoginActivity. onCreate() is called of course
It is like LoginActivity(#1) -> Browser -> LoginActivity(#2)
you can call this portion of code inside onCreate() it will work:
Uri uri = getIntent().getData();
String code = uri.getQueryParameter("code");
Log.d("called",code);
But two different intents(launcher and action_view) can reach the same activity for two different purposes. You'd better create two different activities. First your usual LoginActivity and a second one (which inherit from the first) BrowserActivity wich redifine onCreate. So far, your Manifest will look like
<activity
android:name=".ui.activities.LoginActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.activities.BrowserActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="callback"
android:scheme="app"
/>
</intent-filter>
</activity>
The LoginActivity code should look like this:
public class LoginActivity extends AppCompatActivity {
Button loginButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
loginButton = findViewById(R.id.button);
final String url = "oauth url...";
Log.d("called","oncreate");
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("called","onclick");
attemptLogin(url);
}
});
}
private void attemptLogin(String url){
Log.d("called","onattempt");
// open the browser with url
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
// no onResult
}
And this is the BrowserActivityCode:
public class BrowserActivity extends LoginActivity {
// this will be triggered after authentification
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
processIntent();
}
protected void processIntent() {
Intent intentFromBrowser = getIntent();
if (intentFromBrowser != null) {
Uri uri = intentFromBrowser.getData();
if(uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String code = uri.getQueryParameter("code");
Log.d("code value", code);
}
}
}
}
I have created several activities via Intent's in the past, yet this error baffles me.
This is a simple tutorial given on Developer.Android's website for creating a new Activity
Problem:
The error is thrown before onPause() and after calling startActivityForResult() all in the same Activtiy
Error:
E/ActivityThread: Performing pause of activity that is not resumed: {wrap302.nmu.assignment_6_task_2_server/wrap302.nmu.assignment_6_task_2_server.MainActivity}
java.lang.RuntimeException: Performing pause of activity that is not resumed: {wrap302.nmu.assignment_6_task_2_server/wrap302.nmu.assignment_6_task_2_server.MainActivity}
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3398)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3386)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3361)
at android.app.ActivityThread.-wrap13(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1374)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5471)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Minimal Working Example:
public class MainActivity extends Activity {
public static String isHost = "isHost";
private Context mContext;
private Button btnHostGame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.activity_main);
btnHostGame = (Button) findViewById(R.id.btnHostGame);
btnHostGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startGameActivity(true);
}
});
}
private void startGameActivity(boolean isHosting) {
Intent intent = new Intent(mContext, GameConnector.class);
intent.putExtra(isHost, isHosting);
startActivityForResult(intent, 0); //Exception occurs after this method
}
#Override
protected void onResume() {
super.onResume();
getActionBar().hide();
}
// Exception occurs before this method is called
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Toast.makeText(mContext, "Did you win?", Toast.LENGTH_SHORT).show();
}
}
This is quite strange to me, any advice?
UPDATE
AndroidManifest request
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="wrap302.nmu.assignment_6_task_2_server">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<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.NoActionBar">
<activity android:name=".MainActivity"
android:label="#string/title_game">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".GameConnector"
android:label="#string/title_gameconnector">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".Game"
android:label="#string/title_game">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
yes, GameConnector does get created without a problem.
However, the Exception is thrown before the GameConnector.onCreate method is called.
UPDATE 2
GameConnector code request
public class GameConnector extends Activity implements FragmentFinishListener{
public static String GameType = "GameType", GameConnect = "GameConnect";
public static String PlayerName = "PlayerName";
private FragmentManager fragmentManager;
private Fragment gameTypeFragment;
private Intent gameIntent;
private boolean isHosting;
private Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gameconnector);
mContext = this;
gameIntent = getIntent();
if (gameIntent.hasExtra(MainActivity.isHost))
isHosting = gameIntent.getBooleanExtra(MainActivity.isHost, false);
fragmentManager = getFragmentManager();
gameTypeFragment = (isHosting)
? new FragmentHostGame().setOnFragmentFinishListener(this)
: new FragmentJoinGame().setOnFragmentFinishListener(this);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmentContainer, gameTypeFragment, GameType);
fragmentTransaction.commit();
}
#Override
public void finished(Bundle bundle) {
GameConnection gameConnection = null;
if (bundle != null){
if (bundle.containsKey(GameConnect))
gameConnection = (GameConnection) bundle.getSerializable(GameConnect);
}
fragmentManager.beginTransaction().remove(gameTypeFragment).commit();
startGame(isHosting, gameConnection);
}
private void startGame(boolean isHosting, GameConnection gameConnection) {
Intent intent = new Intent(mContext, Game.class);
intent.putExtra(MainActivity.isHost, isHosting);
intent.putExtra(GameConnect, gameConnection);
startActivityForResult(intent, 0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null){
switch (requestCode){
case 0:{
if (resultCode == 0){
finishActivity(resultCode);
}
else {
setResult(resultCode, data);
finishActivity(1);
}
break;
}
}
}
setResult(resultCode, null);
finishActivity(1);
}
}
I'm calling startActivityForResult from a child activity to MainActivity but never pass for onActivityResult
secondActivty this is the call
private void bringMainActivityToTop() {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bun= new Bundle();
bun.putParcelable("value",new ListData("HelloDummy",longi,lati,"data"));
intent.putExtra("bundle",bun);
setResult(RESULT_OK, intent);
startActivityForResult(intent, 111);
}
And I want see the call in here on the MainActivity I don't care the code I just want to see the call.
#Override
protected void onActivityResult(int requestCode, int responseCode, Intent data) {
super.onActivityResult(requestCode, responseCode, data);
System.out.println("HelloWorld");
Log.i(TAG,"HelloWorld");
}
and the manifest
<activity
android:name="com.test.mppqvat.activity.MainActivity"
android:label="#string/main_act_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
onActivityResult() belongs to your second activity (if its not then it must to), not the MainActivity. onActivityResult() method wont trigger in MainActivity just cuz MainActivity is started for result. Do you realize that?
Also your MainActivity if being started for result must SET the result using setResult() method and than it has to be finished using finish()method, that way the result will be passed from your MainActivity to your caller SeconActivity activity and its onActivityResult() will be fired.
MainActivity.java(in onCreate)
button1=(Button)findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent, 2);// Activity is started with requestCode 2
}
});
(outside onCreate)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 2
if(requestCode==2)
{
String message=data.getStringExtra("MESSAGE");
//use resulted message
}
}
SecondActivity.java(in onCreate)
button1=(Button)findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
String message=editText1.getText().toString();
Intent intent=new Intent();
intent.putExtra("MESSAGE",message);
setResult(2,intent);
finish();//finishing activity
}
});
Your called Activity must call setResult(Activity.RESULT_OK) or setResult(Activity.RESULT_OK, data)
I've an app.
When my app start, I show and splash screen. When my splash screen finish, I start my main activity.
But I've a problem. When I rotate my app in splash screen, my app restart and four senconds later, start my new activity. If I rotate my splash screen three time, start three main activity.
I want start only one activity, how I can do it?
This is my splash screen code:
public class Splash extends Activity {
public static final int seconds=4;
public static final int miliseconds=seconds*1000;
private ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
progressBar=(ProgressBar) findViewById(R.id.progressBar);
progressBar.setMax(seconds-1);
progressBar.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
startAnimation();
}
public void startAnimation(){
new CountDownTimer(miliseconds,1000){
#Override
public void onTick(long millisUntilFinished) {
//progressbar update--->1 second
progressBar.setProgress(getMiliseconds(millisUntilFinished));
}
#Override
public void onFinish() {
Intent i = new Intent(Splash.this, MainActivity.class);
Splash.this.startActivityForResult(i,1);
}
}.start();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//when I return to the MainActivity, finish my app
if(requestCode==1) finish();
}
public int getMiliseconds(long milis){
return (int) ((milisegundos-milis)/1000);
}
}
Use configchanges in your activity tag in manifest.xml
Example
<activity
android:name=".Splash"
android:label="#string/app_name"
android:configChanges="keyboardHidden|orientation" />
you can use this tag on another activities as well if you want to avoid onCreate again and again
Try this
Intent i = new Intent(Splash.this, MainActivity.class);
startActivity(i);
finish();
In AndroidManifest.xml, you need to set the orientation to a specific orientation. Add in android:screenOrientation="portrait" under the stuff for your activity. For example, my activity might look like this now:
<activity
android:name=".SplashScreen"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
If you are in landscape mode, use android:screenOrientation="landscape".
If this doesn't work, in your onFinish() method, use the following:
#Override
public void onFinish() {
Intent i = new Intent(Splash.this, MainActivity.class);
startActivity(i);
finish();
}
I am trying to use the intent to select a video which I want to play using videoplayer. I am not able to get the intent working instead i am getting the Source Not Found error.
Thanks for your help.
This is my code :
Manifest
<application
android:label="#string/app_name"
android:icon="#drawable/ic_launcher">
<activity
android:name="SurfaceActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
Code:
public class SurfaceActivity extends Activity implements TextureView.SurfaceTextureListener, OnPreparedListener, MediaController.MediaPlayerControl
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loadVideo = (Button) findViewById(R.id.Load);
// surface.setSurfaceTextureListener(this);
loadVideo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Video File to Play"), 0);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == 0)
{
if (resultCode == RESULT_OK)
{
Uri sourceUri = data.getData();
String source = getPath(sourceUri);
//startPlayback(source);
startPlaying(source);
}
}
}
}