Hierarchy of launching activities in android - android

I have a confusion with how android starts its launcher activities.
If I am declaring a launcher activity in the manifest file like this
<activity android:name=".Activities.Home">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and I have an Application class which calls an activity based on a check like
if(ParseUser.getCurrentUser() == null){
Intent intent = new Intent(context,Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}else{
Intent intent = new Intent(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
which one has the precedence ? The manifest or the Application. What is the flow of events ? e.g. Application->Manifest (or) Manifest->Application (or) Application overrides Manifest ?
If I am receiving a notification in Android, my Application class is called. This makes the activities in the application class to be started, like shown above. Is there a way to detect who calls the Application class ? I mean whether the user starts it, or it starts from the notification which comes in ?
If there is a way to figure this out. How do I prevent the activity in the Application class to be called when I receive a notification ?
Thanks in advance.

Just pass the boolean extras from application and make the diffrence in the call from Application class and User Launch.
Intent intent = new Intent(context,Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("APP_CALL",True);
startActivity(intent);
Now in your Home activity Just check for APP_CALL if it is called from Application class then bool value will be true else false.
Also you can write in splash activity for checking login .

Related

Android - reopen main activity from notification

Launcher activity for my app is called LaunchActivity. Inside this activity I check if the user is logged. If yes, then a network call is made to validate the user and if everything is fine MainActivity is started. If user runs app for first time or user validation fails, LoginActivity runs.
Inside LaunchActivity there is function that runs appropriate activity:
private void start(Class<? extends Activity> startActivity) {
Intent intent = new Intent(this, startActivity);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
finish();
startActivity(intent);
}
App is receiving notifications. After notification click i want to open app or bring it top if it is on background.
Code responsible for notification intent:
Intent intent = new Intent(context, LaunchActivity.class);
intent.putExtra("SHOW_NOTIFICATION_LIST", "");
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent notificationIntent = PendingIntent.getActivity(
context,
0,
intent,
0);
builder.setContentIntent(notificationIntent);
Notification notification = builder.build();
The problem is that with my current implementation after click, LaunchActivity is reopened even when MainActivity is on background. I can not figure out how to make the pending intent reopen just MainActivity (without LaunchActivity and valdation) if it is on background OR start LaunchActivity when there are no activity running on background ( app is not running ). I would be very grateful for any kind of help.
edit:
Activities declaration inside manifest:
<activity android:name=".activities.LaunchActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.MainActivity"
android:launchMode="singleTop"
android:screenOrientation="userPortrait" />
<activity
android:name=".activities.LoginActivity"
android:excludeFromRecents="true"
android:launchMode="singleTop"
android:noHistory="true"
android:screenOrientation="userPortrait"
android:windowSoftInputMode="adjustResize" >
</activity>
The reason for the absurd behavior is that because you are finishing the LaunchActivity when you call start()
private void start(Class<? extends Activity> startActivity) {
....
finish(); // This is the culprit
....
}
Remove finish() from start() and it will work fine as expected.
If you can't remove finish() because of your app behavior, then change your PendingIntent to launch MainActivity instead of LaunchActivity
Intent intent = new Intent(context, MainActivity.class);
And in MainActivity's onCreate() check if the user is already logged in . If not then navigate him to your LoginActivity.
Create a BroadcastReceiver which reacts to three different intents
ACTION_CREATED: set flag to true
ACTION_DESTROYED: set flag to false
ACTION_LAUNCH: if flag, start MainActivity, otherwise start LaunchActivity
(flag can be e.g. a boolean in sharedpreferences or a static field)
in MainActivity:
in onCreate: send ACTION_CREATED broadcast
in onDestroy: send ACTION_DESTROYEDbroadcast
The notification should send an ACTION_LAUNCHbroadcast.
Note: actions can be named as whatever you want. They also should start with you package name, so you don't interfere with other apps.

Determine how Activity was started

I have an app that starts an activity that isn't the MainActivity first, but it is possible within the course of the app to start the activity on its own. I would like code that runs when the activity is closed to be able to determine if it should go the front of the application(first run) or if it should go back to the previous Activity on the stack(all other runs). Is it possible to determine how an Activity was started inside of it?
You said:
I would like to determine within the course of the Child
Activity what Parent Activity started the Child. In my case that will
either be the Launcher or the MainActivity.
Unfortunately, there is no way to find out what Activity launched your Activity. This information is not available. However...
You can tell if the launcher started your Activity by checking the Intent for ACTION = MAIN and CATEGORY = LAUNCHER:
Intent intent = getIntent();
if (Intent.ACTION_MAIN.equals(intent.getAction()) && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) {
// started by launcher
}
You can also check if the Activity was launched from the list of recent tasks by checking for Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY like this:
Intent intent = getIntent();
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
// Launched from recent task list
}
If this isn't enough for you, then you can always add an "extra" yourself when launching the child Activity from the parent, so that it can tell what Activity started it. For example:
Intent intent = new Intent(this, ChildActivity.class);
intent.putExtra("startedFromMainActivity", true);
startActivity(intent);
and then in your child Activity you can check like this:
Intent intent = getIntent();
if (intent.hasExtra("startedFromMainActivity") {
// started from MainActivity
}
You can store a value in the intent launching your activity, and once opened read it to adapt your behaviour:
intent.putExtra(key,value);
And on the activity side (in onCreate for eg):
getIntent().getExtra(key,defaultValue);
Default value is what you get if no value is found.
getExtra depends o the type of the data stored, so there is getIntExtra ,booleanExtra ,stringExtra ...
Learn more here
your manifesto file exchange mainactivity DEFAULT...
<activity
android:name="com.example.iiintent.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.example.iiintent.al">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</activity>

Sending the user to another application in android

I'm new to android and am trying to make an application that when the user presses a particular button in App A, he is sent to App B. The user can then come back to App A by pressing another button in App B. No content is transferred from one app to another.
I want to accomplish this by making custom intents for both the applications. How should I start with this? Also what exactly is Broadcastreceiver and do I need to use it for the above mentioned problem?
Thanks!
Switching between another Application can be by two ways that is
1.) If you know the MainActivity of the Application to Call, you use
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName(
"package_name","package_name.MainActivity"));
startActivity(intent);
2.) If you don't know the MainActivity to Call you just use PackageName, you use
Intent LaunchIntent = getPackageManager()
.getLaunchIntentForPackage("package_name");
startActivity(LaunchIntent);
I don't think you need a BroadCastReceiver here as it is what you use when you want to catch some event/action for eg- Low Battery. For further details check my answer here
See Code to launch external app explicitly (especially this answer). You'll have to create a custom intent for each of the applications, and then call that intent explicitly.
In App A Manifest:
<intent-filter>
<action android:name="com.mycompany.APP_A" />
</intent-filter>
In App B Manifest:
<intent-filter>
<action android:name="com.mycompany.APP_B" />
</intent-filter>
In App A Button Press:
Intent intent = new Intent();
intent.setAction("com.mycompany.APP_B");
startActivity(intent);
In App B Button Press:
Intent intent = new Intent();
intent.setAction("com.mycompany.APP_A");
startActivity(intent);

Launch Main Activity with Implicit Intent in Service

I have an implicit intent in a service that sends information to my main activity, as well as to another class. I also now want that intent to launch my main activity. I've looked at the myriad posts related to this, and tried lots of different things--addCategory, setAction(MAIN; the activity's name; you name it, I've tried it...), category.DEFAULT in the manifest, and several other things that either resulted in ActivityNotFoundExceptions (most commonly) or behavior that was otherwise undesirable.
Here's where the intent is set up and the relevant part of the manifest. The receiver for the intent is registered in the main activity.
final String NEW_DOSES = "changed to protect the innocent";
Intent bluetoothBroadcast = new Intent();
several putExtra lines here
bluetoothBroadcast.setAction(NEW_DOSES);
sendBroadcast(bluetoothBroadcast);
<activity
android:name=".AsthmaAppActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Is it possible to get this intent to launch my main activity with relatively minor changes? Thanks in advance.
Yes it is possible but no with sendBroadcast(bluetoothBroadcast); sendBroadcast does not launch an activity. You must use startActivity to achieve this. For example here is what a launcher application will do in order to launch an application:
public static void LaunchApplication(Context cx, String packagename) {
PackageManager pm = cx.getPackageManager();
Intent i = pm.getLaunchIntentForPackage(ai.packageName);
if (i != null) cx.startActivity(i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
You can easily adjust the extras and the data needed in order to launch the activity. For example if your activity is named myActivity then you can go like this:
Intent i = new Intent(cx, myActivity.class);
//Put the extras and the data you want here...
//If you are launching the activity from a receiver component you must use
//i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
cx.startActivity(i);
Hope this helps...

Start Activity Using Custom Action

I am looking to start an activity in my app using a custom action. I have found a few answers but everything I try it throws java.lang.RuntimeException saying No Activity found to handle Intent { act=com.example.foo.bar.YOUR_ACTION }.
This is the activity in my manifest file:
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
</intent-filter>
</activity>
And this is how I'm starting the activity:
Intent intent = new Intent("com.example.foo.bar.YOUR_ACTION");
startActivity(intent);
Any help would be greatly appreciated.
I think what you need is to add a default category to your intent-filter,
eg.
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
see this answer for more info.
I think you are creating your intent wrong. Try like this:
String CUSTOM_ACTION = "com.example.foo.bar.YOUR_ACTION";
//Intent i = new Intent(this, FeedBackActivity.class); // <--- You might need to do it this way.
Intent i = new Intent();
i.setAction(CUSTOM_ACTION);
startActivity(i);
Just add and intent-filter category as Default.
Implicit intent works perfectly and in many cases its better to use a implicit intent with Intent-action to call a service/Activity than using class-name.
Before startActivty() / startService() with proper context you cane use this method 'queryIntentActivities(Intent intent, int flags)' from package manager class.
It helps the ActivityManager (responsible for launching activities) to check whether the Android system is getting any match with you Intent.
If it doesn't it returns a list size 0 or else >0.
By this you can also check if your app is getting the call,and in this case even if your app is not installed / has got some problem, it will not crash but will throw a warning in Log. Users will face no big trouble apart from app not being launched.
(users will never forgive you if tour app crashes).
Hope this will help !!!
Happy Coding. :)
I faced the same problem when trying to launch the activity residing in the dynamic feature module and starting through action String as the Activity is not resolvable by name at compile time.
So I set the action but the activity crashes every time (No Activity found to handle intent bla bla.. ) until I set the correct package name.
Context c = getApplicationContext();// flag would be require Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
Intent i = new Intent(action_string);
i.setPackage(context.getPackageName());//this did the trick actually
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
In the Manifest : add catrgory default to the intent filters
from google docs:
<category android:name="android.intent.category.DEFAULT"/>
Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare it in your intent filter, no implicit intents will resolve to your activity.

Categories

Resources