android Loosing context on web view when creating new task - android

I have two applications. The first one A has a web view with a link to another application and a timestamp.
In this web view, I have a link that opens another application B. In B, I have a button. The click on the button should take me back to app A,
without reloading it, and executing a javascript code that should populate some other fields in the web view.
As a result, App A should be brought back, timestamp should not be changed and the javascript called and fields properly populated.
The problem is if I do this scenario and I start app B from A using only StartActivity(), it doesn't work. I'm able to do A-B and B-A but my javascript is not called
because A is not called with the proper intent. In other words, when calling A from B, I should find in the intent object the action and the data that took me to A but instead the action in the intent is NULL
If in the other hand, I add a flag when starting Activity on B : FLAG_ACTIVITY_NEW_TASK. it works one time. A->B->A but after that I'm not able to call B again.
Another test I made: If I start calling B from the home screen and than A and than B. It works. So I guess it has to do with the fact that B is different if called using intent from A or from home screen.
Anyway, I couldn't make it open the app, call the js and keep the context all in the same time.
I only tried on emulator.
Here is Manifest for App A
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cgi.csb.launcher"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application android:label="#string/app_name" android:icon="#drawable/ic_launcher">
<activity android:name=".Activity1" launchMode="singleTask">
<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.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:host="localhost" android:scheme="myactivity"></data>
</intent-filter>
</activity>
</application>
</manifest>
Here is the manifest for App B
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.CallerApp"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application android:label="#string/app_name">
<activity android:name=".Activity2" launchMode="singleTask">
<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.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:host="dummy"
android:scheme="testintentapp"/>
</intent-filter>
</activity>
</application>
</manifest>
To call B from A :
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.addCategory("android.intent.category.DEFAULT");
startActivity(intent);
return true;
}
To call A from B :
case R.id.button:
Intent intent = new Intent();
intent.setData(Uri.parse("myactivity://localhost"));
intent.putExtra("firstKeyName","FirstKeyValue");
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
break;
The code I use to differentiate when A is called from home or from App B to call the javascript
Intent intent = getIntent();
if ("myactivity://localhost".equals(intent.getDataString())) {
Log.d(TAG, "*** Call JS with action : " + intent.getAction());
_jsHandler.javaFnCall("Hardcoded params");
} else {
Log.d(TAG, "***Just call the app with action :" + intent.getAction());
}
Thanks a lot !

Related

Jumping back with App Links closes CustomTab

so what I'm trying to achieve is the following:
In App 1, I'm loading a website in a CustomTab, this website jumps to App 2 via App Links. In App 2, after performing a task, I want to jump back to App 1, where the CustomTab still needs to be open as it needs to do some processing. I have this working where I jump back to App 1 via the package name, but I need to get it working via App Links as well.
However, what currently happens is that the CustomTab seems to get closed when I jump back via App Links. My first thought is that I'm not retaining the app / starting the activity correctly.
AndroidManifest of App 1:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.secret.package.name">
<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="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="some.secret.url" />
</intent-filter>
</activity>
</application>
</manifest>
Opening the CustomTab in App 1:
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(MainActivity.this, Uri.parse(url));
Code in App 2 to jump back:
private void performAppSwitch() {
Intent intentWithURI = new Intent(Intent.ACTION_VIEW, Uri.parse(APP_LINKS_URL));
PackageManager packageManager = context.getPackageManager();
if (intentWithURI.resolveActivity(packageManager) != null) {
intentWithURI.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentWithURI);
} else {
Intent intentWithPackageID = packageManager.getLaunchIntentForPackage(PACKAGE_NAME);
if (intentWithPackageID != null) {
List<ResolveInfo> activities = packageManager.queryIntentActivities(intentWithPackageID, 0);
boolean isIntentSafe = !activities.isEmpty();
if (isIntentSafe) {
intentWithPackageID.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentWithPackageID);
}
}
}
}
Any ideas as to why it's working when I switch via package name but not when I switch via App Links?
I have tried every possible variant of launchMode
The issue was that the CustomTab was starting an activity of its own, and I had to make sure that App 1 did not redraw.
So in App 1, adding the following to onCreate of my main activity would do the trick:
if (!isTaskRoot()) {
finish();
return;
}

how to open other app activity from myapp?

I'm developing an app that opens other apps with intents and it works perfectly, but now I need to open a specific activity and I don't know if it's even possible.
already installed both app and I am not able to open specific activity from my app.
btnCallActivity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
Intent intent = new Intent();
intent.setClassName("com.rayvatapps.flatplan", "com.rayvatapps.flatplan.LoginActivity");
intent.putExtra("WEBVIEW_URL", "https://google.com/");
startActivity(intent);
} catch (Exception e) {
Toast.makeText(mContext, "oops...app is not found", Toast.LENGTH_SHORT).show();
}
}
});
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rayvatapps.flatmaps">
<application
android:allowBackup="true"
android:exported="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=".LoginActivity"
android:label="Other App"
android:exported="true">
<intent-filter>
<action android:name="com.rayvatapps.flatplan.app.LoginActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
i am getting following error
Error: No Activity found to handle Intent { act=com.rayvatapps.flatplan.app.LoginActivity }
E/Error: Permission Denial: starting Intent { cmp=com.rayvatapps.flatplan/.LoginActivity (has extras) } from ProcessRecord{4310b06 9701:com.rayvatapps.appdemotest/u0a384} (pid=9701, uid=10384) not exported from uid 10378
Any help will be highly appreciated.
In Manifest.xml of Second Apps Activity add Intent Filter -> android.intent.category.DEFAULT
<activity
android:name="com.myapp.ActivityName"
android:exported="true">
<intent-filter>
<action android:name="com.demo.any_name" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Then from your app
Intent launch = new Intent("com.demo.any_name");
startActivity(launch);
Your package and class names do not match. Based on the manifest of the app you want to start, you need to change this:
intent.setClassName("com.rayvatapps.flatplan", "com.rayvatapps.flatplan.LoginActivity");
into this:
intent.setClassName("com.rayvatapps.flatmaps", "com.rayvatapps.flatmaps.LoginActivity");
You also don't need the <intent-filter> on the Activity in the app you are trying to start, as you are using an explicit Intent to start it. If you remove the <intent-filter> make sure that you keep the android:exported="true" for the Activity, otherwise you won't be able to launch it from another application.

Deep linking does not open a new app

I have two apps. From the first, I want to launch the second one by deep linking. It works but the problem is that the second one starts inside the first one. I would like to start the second one in a new instance.
The code of the first app to open the second app:
String uri = "deeplinkTestTom://token/123456";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);
The manifest of the second app:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data
android:scheme="deeplinkTestTom" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
</application>
When I try to launch Facebook app from my first app (String uri = "facebook://facebook.com/inbox";), it launch facebook in a new app and not inside my first app. So I suppose that something is missig in the manifest of my second app, but I can't find what.
What should I do ?
I believe you're talking about new Task instead of "new app".
Read Tasks and Back Stack
You need to use Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) to start an Activity in a new Task.
For your case, use
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

How to hide android app from launcher

I would like to hide my android app from the launcher, but be able to call it from within another app. I am lost on what to remove from the android manifest.
Already tried removing...
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
...but then it doesn't open when called from another app.
Here is what how I am calling this hidden
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage("org.xbmc.xbmc");
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
Here is the top of the manifest
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_TASKS" />
<application android:label="#string/app_name" android:icon="#drawable/ic_launcher" android:hasCode="true" android:debuggable="true">
<activity android:theme="#*android:style/Theme.NoTitleBar.Fullscreen" android:name=".Splash" android:finishOnTaskLaunch="true" android:launchMode="singleInstance" android:screenOrientation="sensorLandscape" android:configChanges="touchscreen|keyboard|keyboardHidden|navigation|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
You need to remove the following line from your AndroidManifest.xml:
<category android:name="android.intent.category.LAUNCHER"/>
This will remove the application from the default launcher. However, you also need to add the following line such that your BroadcastReceiver is not completely ignored:
<category android:name="android.intent.category.DEFAULT"/>
You should NOT remove the line below - it is used to specify which Activity should launch first when your app is opened:
<action android:name="android.intent.action.MAIN"/>
EDIT
In order to launch the application discussed above from another application, you cannot use the calls shown in your question. You are trying to open the application by creating an Intent with the CATEGORY_LAUNCHER tag (i.addCategory(Intent.CATEGORY_LAUNCHER)) when you have explicitly removed the following line from your AndroidManifest.xml file:
<category android:name="android.intent.category.LAUNCHER" />
The absence of the above line means that the application you are trying to call will ignore the launch Intent. In order to launch your application you will need to act upon another Intent. Here is an example that shows how to open an application, which doesn't contain a launch intent filter, by responding to a SMS Intent: How to launch an Android app without "android.intent.category.LAUNCHER"
Which intent you choose to use is up to you - just make sure you add it to your AndroidManifest.xml file.
Try this code:
PackageManager p = getPackageManager();
p.setComponentEnabledSetting(getComponentName(),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
and check this link.
hope this helps.

Reload Just the Main Activity not the Launcher Activity

I'm using this code to refresh MainActivity.java when a Refresh button is pressed.
Intent intent = getIntent();
finish();
startActivity(intent);
MainActivity.java has the category default and there is another Launcher activity. So whenever I press the Refresh button the Launcher Activity also starts again. I only need to start the MainActivity class. Below is the manifest
<application
android:allowBackup="true"
android:icon="#drawable/play_icon"
android:label="#string/app_name"
android:theme="#style/CustomActionBarTheme" >
<activity
android:name="com.theanilpaudel.joshilo.FirstScreen"
android:configChanges="orientation|screenSize"
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="com.theanilpaudel.joshilo.MainActivity"
android:configChanges="orientation|screenSize"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light.DarkActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAINACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
What you are looking for in this case is an explicit Intent that launches MainActivity.
You can do this like so:
Intent mainIntent = new Intent(this, MainActivity.class);
startActivity(mainIntent);
This will ensure that the Intent only launches MainActivity.
However, I highly recommend re-evaluating why you need to completely restart the Activity to refresh it. There are much cheaper (faster and less resource intensive) methods of updating data displayed in an Activity.
I guess I know the culprit. Try using the following code once.
Intent intent = getIntent();
startActivity(intent);
finish();
As far as I know startActivity() uses context to run. In case if you call finish() before startActivity() that may lead to destroy context of MainActivity and will get the application's context i.e. fires the activity with behavior LAUNCHER or MAIN.
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Let me know if it helps or you still have difficulty reloading activity.
Cheers

Categories

Resources