Go back to the First/Main activity without reloading it - java

I am developing an android app. I need to call my MainActivity without reloading it as it has huge amount of data fetch from internet.
Suppose, I am on third activity now and I want to go back to MainActivity.
If I use:
Intent i = new Intent(Third.this,Main.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
it will load MainActivity but I don't want to reload it. like from Second Activity I call finish() and it does exactly want i need.

This is how to do it:
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);

metntion it in your AndroidManifest.xml file
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation">
do nothing inside the method onResume() and onstart() when coming back to this activity
and try intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); instead of addFlags() method

In Third activity when you want to go to first activity, put finish() mwthod there.
In Second activity, after onCreate() method, put
#Override
public void onResume(){
super.onResume();
finish();
}
I think this code will work for you, jus try it.

Try adding this to your manifest:
android:configChanges="keyboard|keyboardHidden|orientation">
add this line to the activity in your manifest like this:
<activity android:name=".Main"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Related

Can't get NDEF_DISCOVERED action when opening the application with NFC tag

So I programmed an NFC tag to launch my application that I'm currently working on. I used the following service to do that:
https://play.google.com/store/apps/details?id=com.wakdev.wdnfc&hl=en
What I want to do is to switch from one activity to another whenever the NFC tag opens my application.
Under the manifest tag in my AndroidManifest.xml I have:
<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
And my MainActivity looks like this:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Since the NFC tag opens the MainActivity first, I want to see whether it's been opened by NFC. If it has, switch to another activity.
The problem is that getIntent().getAction() always returns android.intent.action.MAIN while I'm expecting android.nfc.action.NDEF_DISCOVERED.
At the moment I'm performing this check (debugging basically) under onResume() method with the following code:
#Override
protected void onResume() {
super.onResume();
System.out.println(getIntent().getAction());
}
And I've tried performing this check under onCreate() and onStart() methods. All of them return android.intent.action.MAIN result while I expect android.nfc.action.NDEF_DISCOVERED.
I'm fresh in Android development and I'm just trying to make this work for a small prototype. Would appreciate if you guys could help me!
Edit: I got it working! I researched this question a lot and I believe that my NFC tag needed some extra data of a text/plain type (I did not specify this mimeType before as well so seems like it's mandatory). I also had put NDEF_DISCOVERED under LAUNCHER category while trying to debug the application and then changed it back to DEFAULT. I'm finally getting my desired results!
getIntent() returns the Intent that was used to create the activity. In your case, that is the home screen launcher Intent.
When you scan the NFC tag, a new Intent will be delivered to that activity. That Intent is passed to an onNewIntent() method that you can override.
Depending on how your activity is being used, you might need to handle both cases:
Where the user launched your app by scanning the NFC tag, so your activity was created with the NDEF Intent
Where the user launched your app by other means before scanning the NFC tag, so your activity was created with some other Intent and you get the NDEF Intent in onNewIntent()

Intent is not working for moving fragment to activity

I'm having trouble moving intent class fragment to activity. I'm trying to send intent from one Fragment to another Activity.
Here is the code:
Intent intent = new Intent(getActivity(), MainActivity.class);
getActivity().startActivity(intent);
Here is my Manifest File
<activity android:name=".activities.MainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustNothing"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
but it's not working for me and on another side, I have done some RND but all are same for me.
How can I Solve the issue
Thanks In Advance.
remove this android:launchMode="singleTask"
which looks like this
<activity android:name=".activities.MainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:windowSoftInputMode="adjustNothing"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
if your current activity is mainactivity and you are launching it again , it will not work because launchmode is set to single task in manifest
Solution :- remove this tag
android:launchMode="singleTask"

The scope of loading a sub activity on onCreate()

I just need some information regarding the scope of execution. On my
To understand what is happening you need to know the Activity lifecycle
As you can see, when the app is launched, the first thing that's going to run is your onCreate() in this case, onCreate() has a method that inflates the view of your Activity, that method is called setContentView().
so, if you execute your code below setContentView, it will first inflate the view of MainActivity or the class you are in, and then just go to your other Activity.
If you want to start your Activity right when your app launches, just move your startActivity(...) above setContentView() in your onCreate(), but it will be better to do this in your manifest rather than just using a class to open another one.
To launch your WelcomeActivity just do this in your Manifest
<activity
android:name=".WelcomeActivity"
android:label="#string/app_name"
android:screenOrientation="sensorLandscape">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:screenOrientation="sensorLandscape"/>
<activity
So this
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
will define that WelcomeActivity executes first, then in WelcomeActivity do an intent to your MainActivity
Rather than load another activity within an activity, perhaps you should consider using a Fragment which are platform-defined modular sections of an activity with its own lifecycle and optional user-interface. See this for more info: https://developer.android.com/training/basics/fragments/fragment-ui
My advice would be to use support Fragments within your activity rather than another activity.

Prevent Android system from resuming task if the new Intent is the same with initial Intent that launches the app

This question is related to deep link. For example, I have four activities in my app, namely MainActivity, FirstActivity, SecondActivity, and DeepLinkActivity. Here are the activities in the manifest file.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".FirstActivity" />
<activity android:name=".SecondActivity" />
<activity android:name=".DeepLinkActivity"
android:theme="#android:style/Theme.NoDisplay">
<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:scheme="launch" />
</intent-filter>
</activity>
DeepLinkActivity will launch whether FirstActivity, SecondActivity, or MainActivity depending on the URI received:
public class DeepLinkActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
launchIntent(getIntent());
}
private void launchIntent(Intent intent) {
Intent newIntent = null;
switch (intent.getData().getHost()) {
case "first":
newIntent = new Intent(this, FirstActivity.class);
break;
case "second":
newIntent = new Intent(this, SecondActivity.class);
break;
default:
newIntent = new Intent(this, MainActivity.class);
break;
}
startActivity(newIntent);
finish();
}
}
The problem is, Android system seems to record the initial Intent that launched the app, then uses it to resume whatever Activity is currently running in the foreground -if- the new Intent is the same with initial Intent.
Consider the following case:
User click launch://first deep link → FirstActivity is opened.
User minimize the app then click launch://second → SecondActivity is opened on top of FirstActivity.
User minimize the app again then click launch://first.
After step 3, what I expect is the OS open FirstActivity. But actually it resumes the task, so SecondActivity (from step 2) reappears. This happens because the deep link on step 1 and 3 is the same, hence the OS regards them as the same Intent.
How can I prevent the Android system from resuming task in this particular case?
After some trials this is what I did to get it working.
Setting the Flags for the newIntent before starting it:
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
However, setting the flags alone didn't do the job, the app is still resumed to the last activity. Then I add the launchMode to DeepLinkActivity:
<activity android:name=".DeepLinkActivity"
android:theme="#android:style/Theme.NoDisplay"
android:launchMode="singleTask">
Now the the app is restarted and open the expected activity! Note that the launchMode can be singleInstance as well.
You can try defining something on the Activities OnPause function, to reset the intent every time the activity is paused.

Open intent from URL using Java Script is not working on production - DeepLink

I have a little mystery here, I have this code in my onCreate method:
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Log.i(TAG, "ACTION_VIEW START");
Uri uri = intent.getData();
SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();
tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
tEditor.putString("GuestSurname", uri.getQueryParameter("a"));
tEditor.apply();
//it shows an alert to the user
GuestLogin(uri.getQueryParameter("h"), uri.getQueryParameter("a"));
Log.i(TAG, "ACTION_VIEW END");
}
And I have this code in my manifest:
<activity
android:name="epinom.jm.smarthotel.vcMainScreen"
android:label="#string/title_activity_home"
android:launchMode="standard"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="epinom.jm.smarthotel.vcMainScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<data android:scheme="com.guestperience" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And from a web page I'm executing this JS:
window.location = "com.guestperience://?h=x&a=x";
So here comes the funny part, if I plug my phone, and then in Android Studio, I click on the Play or Debug button, and then I go to the Mail App and tap over a hyperlink that takes me to my web page in Chrome that have the JS instruction, it opens My App and open the intent using the onCreate and onStart method like I expect and add it to the stack of intents in My App, this means that if I'm on any intent of my app and I execute the JS, the app comes to the front and it creates the intent and do what it is supposed to do and shows an alert to the user.
But if I pull the plug or I use the .apk that I have in the Play Store in Beta, this functionality does not work, and I don't understand the difference because to me is the same code, so this is what happens when I'm not connected to Android Studio:
If the app is close, I click on the link, it opens Chrome and the the app is started, and the first intent of the app that is the same that I'm calling, do what it is supposed to do and shows the alert.
Once the app is open if I repeat the steps it never shows the intent and it does not matter if I'm in the initial intent or in another intent.
I have tried to change the code to the onStart but it is almost the same behavior:
If the app is close, I click on the link, it opens Chrome and the the app is started, and the fist intent of the app that is the same that I'm calling, do what it is supposed to do and shows the alert.
Once the app is open if I repeat the steps it only shows the alert when I'm in the main intent (the same that I'm calling), if I'm in another intent it never shows the intent, but if I navigate to the intent the Alert is shown every time I call it. (on every onStart, this can be controlled with a bool).
At the end, I don't understand why the behavior is different when I'm plugged to Android Studio.
Maybe is some permission that I'm missing or something that I have to configure, but I'm lost.
Any help will be appreciated.
Thanks.
UPDATE 1:
I have detected this:
If I plug the phone and press play and keep the plug everything works like a charm.
If I plug the phone and press play and remove the plug everything works like a charm.
If I plug the phone and press play and close the app (the plug can be plugged or not) if I start the app with the link works like a charm, but if the app is started stops working on any intent.
There is something that Android Studio is doing that makes it work, I'm thinking that it has to be with permissions but I'm really lost.
UPDATE 2:
I have tried all the options of this examples and I still have the same result, if the app is open i can't get to the intent, but if the app is closed or is plugged to Android Studio works like a charm.
<!-- Allow web apps to launch Barcode Scanner by linking to http://zxing.appspot.com/scan. -->
<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:scheme="http" android:host="guestperience.com" android:path="/Main"/>
</intent-filter>
<!-- Support zxing://scan/?... like iPhone app -->
<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:scheme="com.guestperience" android:host="Main" android:path="/"/>
</intent-filter>
I have tried to attach it to the launcher intent and nothing seems to work.
<category android:name="android.intent.category.LAUNCHER"/>
I have tried to launch the app from an href, to see if a user action is needed and still the same result.
CLICK HERE TO LOGIN
https://developer.chrome.com/multidevice/android/intents
https://github.com/zxing/zxing/blob/master/android/AndroidManifest.xml
UPDATE 3:
I have added this to track the action that is called once the app is open:
Log.i(TAG, intent.getAction().toString());
If I open my app for the first time the value is:
"com.guestperience://Main/"
But if I open another intent and open the app through the link again the result is the last action I have called i.e.:
"epinom.jm.smarthotel.vcMainScreen"
And of course if I open the app with Android Studio I always get this value:
"com.guestperience://Main/"
Because all the app is configurable through JSON files all my activities have intent filters so all my calls are like:
Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen"); //replacing this "epinom.jm.smarthotel.vcMainScreen" with the JSON string var of course
startActivity(tIntent);
finish();
I have read this too, and as far as I can tell I'm not missing anything:
http://developer.android.com/intl/es/training/app-indexing/deep-linking.html
After doing a lot of tests and reading a lot, I have ended doing a base class that extends Activity and my Main Activity extends from the Base Activity.
public class BaseActivity extends Activity {
}
public class vcMainScreen extends BaseActivity {
}
Then on the onStart() of the Base Activity I have added this code to handle the call from the browser:
#Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
SharedPreferences.Editor tEditor = getSharedPreferences("UserFormPreferences", MODE_PRIVATE).edit();
tEditor.putString("GuestRoomNumber", uri.getQueryParameter("h"));
tEditor.putString("GuestSurname", uri.getQueryParameter("a").replace("/",""));
tEditor.apply();
Intent tIntent = new Intent("epinom.jm.smarthotel.vcMainScreen");
tIntent.putExtra("Login", "true");
startActivity(tIntent);
finish();
}
}
As you can see it calls the Main Activity an there in the onStart() I have added this lines to call my login method:
#Override
protected void onStart() {
super.onStart();
if (getIntent().getExtras() != null && getIntent().getExtras().getString("Login") != null && getIntent().getExtras().getString("Login").equals("true")) {
SharedPreferences tPrefs = getSharedPreferences("UserFormPreferences", MODE_PRIVATE);
GuestLogin(tPrefs.getString("GuestRoomNumber", ""), tPrefs.getString("GuestSurname", ""));
getIntent().putExtra("Login", "false");
}
}
And in the Manifest I have added this code:
<activity
android:name="epinom.jm.smarthotel.BaseActivity"
android:label="#string/title_activity_home"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<data android:scheme="com.guestperience" android:host="Main" android:path="/"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="epinom.jm.smarthotel.vcMainScreen"
android:label="#string/title_activity_home"
android:launchMode="standard"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="epinom.jm.smarthotel.vcMainScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Is important that the Base Activity has a launchMode="singleTask", and a the end I have to use a URL like this:
CLICK HERE TO LOGIN
And I'm using this GIT to handle my DeepLink with some changes:
https://github.com/hampusohlsson/browser-deeplink
I'm sure that this is not the correct way of doing this, but I hope this helps someone in the future.
Happy coding to all.

Categories