I want to launch app using my own app but not by giving the package name, I want to open a custom URL.
I do this to start an application.
Intent intent = getPackageManager().getLaunchIntentForPackage(packageInfo.packageName);
startActivity(intent);
Instead of package name is it possible to give a deep-link for example:
"mobiledeeplinkingprojectdemo://product/123"
Reference
You need to define a activity that will subscribe to required intent filters:
<activity
android:name="DeepLinkListener"
android:exported="true" >
<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="host"
android:pathPattern="some regex"
android:scheme="scheme" />
</intent-filter>
</activity>
Then in onCreate of your DeepLinkListener activity you can access the host, scheme etc.:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent deepLinkingIntent= getIntent();
deepLinkingIntent.getScheme();
deepLinkingIntent.getData().getPath();
}
Perform check on path and again fire a Intent to take the user to corresponding activity. Refer data documentation for more help.
Now fire a Intent:
Intent intent = new Intent (Intent.ACTION_VIEW);
intent.setData(Uri.parse(DEEP_LINK_URL));
Don't forget to handle the exception. If there is no activity that can handle the deep link, startActivity will return an exception.
try {
context.startActivity(
Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(deepLink)
}
)
} catch (exception: Exception) {
Toast.makeText(context, exception.localizedMessage, Toast.LENGTH_LONG).show()
}
Related
I have created a DynamicLink programatically which includes sub-domain syntax, some title and preview Image. I have also specified the IntentFilter which should open that activity when clicked. But when the link is clicked it open another Activity which also have Deep link. page.link domain is provided by google itself in Firebase Console
The code for creating Dynamic Link is
String e="https://learnandroid.page.link/?link=https://learn.android/&apn=com.learnandro&amv=16&st=Please view the ContentEvent&si="+some Image Url+"&afl=https://play.google.com/store/apps/details?id=app Package name";
Task<ShortDynamicLink> shortLinkTask = FirebaseDynamicLinks.getInstance()
.createDynamicLink()
.setLongLink(Uri.parse(e))
.buildShortDynamicLink()
.addOnCompleteListener(new OnCompleteListener<ShortDynamicLink>() {
#Override
public void onComplete(#NonNull Task<ShortDynamicLink> task) {
Uri get=task.getResult().getShortLink();
Intent sh=new Intent(Intent.ACTION_SEND);
sh.setType("text/plain");
sh.putExtra(Intent.EXTRA_TEXT,"Vi ew the Amazing Event "+get);
startActivity(Intent.createChooser(sh,"View"));
}
});
The Intent filter for Activity is given as
<activity android:name=".content.Home"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<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="learn.android"
android:scheme="https" />
</intent-filter>
</activity>
But when the link generated is clicked it opens some Another activity.
If you have deeplink in multiple activities then you should use android:pathPattern to differentiate them from each other.
Here is sample code
<data
android:host="learn.android"
android:pathPattern="/home"
android:scheme="https" />
and add /home to your link
String e="https://learnandroid.page.link/?link=https://learn.android/home/&apn=com.learnandro&amv=16&st=Please view the ContentEvent&si="+some Image Url+"&afl=https://play.google.com/store/apps/details?id=app Package name";
You can try below snippet :
val data: Uri? = intent?.data
if (Uri.EMPTY != data)
{
val id = intent.data?.getQueryParameter("ID")
intent = Intent(this, ActivityName::class.java)
startActivity(intent)
finish()
}
In getQueryParameter, you need to pass KEY name which contains data in URL
Define this set of code in Activity which is defined in Manifest file
My question is how to start app A within app B that appears app A is within app B through deep linking?
In the first picture below, the Debug app appears as a separate app from Slack (new code, Firebase deep linking). In the 2nd picture, the Debug app appears to be within the Slack app (old code, Android deep linking). I want to use Firebase deep linking and show the Debug app within other apps (Slack, Gmail etc).
Can anyone please go through my code below and let me know how I can achieve this?
Old code, Android deep linking:
AndroidManifest
<activity
android:name=".activity.SplashScreenActivity"
android:screenOrientation="portrait"
android:theme="#style/SplashTheme">
<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" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "abc://flights” -->
<data
android:host="sales"
android:scheme="abc" />
<data
android:host="deals"
android:scheme="abc" />
</intent-filter>
</activity>
Activity:
Intent intent = new Intent(SplashScreenActivity.this, BottomNavBarActivity.class);
//Deep Linking Content
Uri deepLinkData = getIntent().getData();
if (deepLinkData != null) {
intent.putExtra(EXTRA_DEEP_LINK, deepLinkData.getHost());
}
startActivity(intent);
overridePendingTransition(R.anim.splash_fade_in, R.anim.splash_fade_out);
finish();
New Code, Firebase deep linking:
AndroidManifest:
<activity
android:name=".activity.SplashScreenActivity"
android:screenOrientation="portrait"
android:theme="#style/SplashTheme">
<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" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="abc.app.goo.gl"
android:scheme="http"/>
<data
android:host="abc.app.goo.gl"
android:scheme="https"/>
</intent-filter>
</activity>
Activity:
FirebaseDynamicLinks.getInstance()
.getDynamicLink(getIntent())
.addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
#Override
public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
// Get deep link from result (may be null if no link is found)
Uri deepLink = null;
if (pendingDynamicLinkData != null) {
// Start the activity through intent, same as before.
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.v(TAG, "Firebase deep link failure");
}
});
Its dependent on the app which sends the intent, for example whether they pass FLAG_ACTIVITY_NEW_TASK or not. I suspect the difference here is how Slack is handling the links - they may treat web URLs differently than other format ones (your old links have non-standard schemes).
Create a method openApp(), and call it accorrding to your need.
public void openAnApp()
{
Boolean flag=false;
try{
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
final PackageManager packageManager = getActivity().getPackageManager();
Intent intent1 = new Intent(Intent.ACTION_MAIN, null);
intent1.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resInfos = packageManager.queryIntentActivities(intent1, 0);
ActivityInfo activity = null;
//getting package names and adding them to the hashset
for(ResolveInfo resolveInfo : resInfos) {
System.out.println("apap="+resolveInfo.activityInfo.packageName);
if(resolveInfo.activityInfo.packageName.equals("your.app.packagename"))
{
flag = true;
activity = resolveInfo.activityInfo;
break;
}
}
if (flag) {
// final ActivityInfo activity = app.activityInfo;
final ComponentName name = new ComponentName(activity.applicationInfo.packageName,activity.name);
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(name);
getActivity().startActivity(intent);
//startActivity(Intent.createChooser(intent , "Send image using.."));
} else {
Uri uri=Uri.parse("market://details?id=your.app.packagename");
Intent goToMarket=new Intent(Intent.ACTION_VIEW,uri);
try{
startActivity(goToMarket);
}catch(ActivityNotFoundException e){
Toast.makeText(getActivity(),"Couldn't launch the market",Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
Toast.makeText(getActivity(), "Something went wrong", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
I have StartActivity and MainActivity, in manifest scheme is already set.
<activity
android:name=".StartActivity"
android:label="#string/app_name"
android:theme="#style/AppThemeNoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="myApp" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:parentActivityName=".StartActivity" />
StartActivity:
public class StartActivity extends InstrumentedActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_start);
if (isLogin) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
}
}
The original design is after user pressed the url in browser, it open StartActivity and then go to MainActivity when user logined.
This works correctly in the first time (App is killed and user pressed the url).
But while the app is in the background (in MainActivity), after user press the url, it didn't go through StartActivity but only onResume of MainActivity.
Anyone know the reason? and how to make sure it go to StartActivity? Thanks.
when you open your Activity first time from URL ,that time Activity created so onCreate() method called .But if your Activity is in Background then
onNewIntent() will be called so Override this method And put you code here .
Add below method : IN MainActivity
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// add your code here
}
In Manifest :
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
/>
Start Activity :
Intent intent = new Intent(context, MainActivity.class);
startActivity(intent);
if you want pass any input value then you may pass in Intent through Bundle ,that is received into onNewIntent(Intent intent) ,and you can get just like we get data from Intent send from one Activity to next activity.
i've tried to sending data between App1 to App2 via Intent in Android
i used this code but i couldn't resolve my problem.
App1 MainActivity :
Intent i2 = new Intent("com.appstore.MainActivity");
i2.setPackage("com.appstore");//the destination packageName
i2.putExtra("Id", "100");
startActivity(i2);
App2 MainActivity :
Bundle data = getIntent().getExtras;
if(data!=null){
String myString = b.getString("Id");
}
Manfiest App2 MainActivity:
<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.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</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>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Final code:
App 1 :
Intent intent = new Intent();
intent.setClassName("com.appstore", "com.appstore.MyBroadcastReceiver");
intent.setAction("com.appstore.MyBroadcastReceiver");
intent.putExtra("KeyName","code1id");
sendBroadcast(intent);
App 2:
Reciver:
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Data Received from External App", Toast.LENGTH_SHORT).show();
}
}
Manifest :
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="first_app_packagename" />
</intent-filter>
</receiver>
MainActivity :
MyBroadcastReceiver mReceiver = new MyBroadcastReceiver();
registerReceiver(mReceiver,
new IntentFilter("first_app_packagename"));
My requirement was to send the "user id" from App1 to App2 and get "username" back to App1.
I needed to launch my app directly without any chooser. I was able to achieve this using implicit intent and startActivityForResult.
App1 > MainActivity.java
private void launchOtherApp() {
Intent sendIntent = new Intent();
//Need to register your intent filter in App2 in manifest file with same action.
sendIntent.setAction("com.example.sender.login"); // <packagename.login>
Bundle bundle = new Bundle();
bundle.putString("user_id", "1111");
sendIntent.putExtra("data", bundle);
sendIntent.setType("text/plain");
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(sendIntent, REQUEST_CODE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
Bundle bundle = data.getBundleExtra("data");
String username = bundle.getString("user_name");
result.success(username);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
I had two activity in App2 ie. MainActivity and LoginActivity.
App2 > AndroidManifest.xml
<activity android:name=".LoginActivity">
<intent-filter>
<!--The action has to be same as App1-->
<action android:name="com.example.sender.login" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Sorry for this I had a little mix up with Java and Kotlin. My second app was in Kotlin, not that it will effect in any way.
App2 > LoginActivity.java
override fun onResume() {
super.onResume()
var userId = "No data received"
val intent = intent
if (intent != null
&& intent.action != null
&& intent.action.equals("com.example.sender.login")
) {
val bundle = intent.getBundleExtra("data")
if (bundle != null) {
userId = bundle.getString("user_id")
userId = " User id is $userId"
}
}
tvMessage.text = "Data Received: $userId"
}
fun onClickBack(view: View) {
val intent = intent
val bundle = Bundle()
bundle.putString("sesion_id", "2222")
intent.putExtra("data", bundle)
setResult(Activity.RESULT_OK, intent)
finish()
}
When you do this:
Intent i2 = new Intent("com.appstore.MainActivity");
i2.setPackage("com.appstore");//the destination packageName
i2.putExtra("Id", "100");
startActivity(i2);
you are calling the single-argument constructor of Intent. In this constructor, the argument is interpreted as the Intent ACTION. You then set the package name in the Intent.
When you call startActivity() with this Intent, Android will look for an Activity that contains an <intent-filter> with the specified ACTION. There are no installed applications that have an Activity defined like this in the manifest:
<activity>
<intent-filter>
<action android:name="com.appstore.MainActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
So Android will not be able to find and launch the Activity that you want.
As you want to specify explicitly the component that you want to use, instead of using the 1-argument Intent constructor, you should do this instead:
Intent i2 = new Intent();
i2.setClassName("com.appstore", "com.appstore.MainActivity");
i2.putExtra("Id", "100");
startActivity(i2);
Using setClassName() you provide the package name and the class name of the component that you want to launch.
This should work:
APP1
Intent i2 = new Intent();
i2.setComponent(new ComponentName(PACKAGE,ACTIVITY));//the destination packageName
i2.putExtra("Id", "100");
startActivity(i2);
APP2
String myString = getIntent().getStringExtra("Id");
Using Bundle.putSerializable(Key,Object); and Bundle.putParcelable(Key, Object);
the former object must implement Serializable, and the latter object must implement Parcelable.
Content providers:
Content providers are the standard interface that connects data in one process with code running in another process.
See Android Docs.
Content provider working demo here.
I have option in my app to start browser and load imdb website.
I'm using ActionView for this.
Intent intent1 = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse(website));
try {
activity.startActivity(intent1);
} catch (Exception e) {
Toast.makeText(activity, R.string.no_imdb, Toast.LENGTH_SHORT)
.show();
}
The problem occurs when I tap on back button.
When default browser app is launched everything is ok.
When Opera Mini app is launched, when I tap on back button, it seems like my app receives two back actions, and finish my current activity.
How to prevent this?
Try starting the intent in a new task:
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Or
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Please add this code to your android manifest for activity that you need return
<activity
android:name="YourActivityName"
android:launchMode="singleTask">
<intent-filter>
<action android:name="schemas.your_package.YourActivityName" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.ALTERNATIVE" />
</intent-filter>
</activity>
and add this to your web page
click to load app
because only one app has this action name (schemas.your_package.YourActivityName) on your phone, web page directly return to app
Also You can Use Airbnb DeepLink lib
Example
Here's an example where we register SampleActivity to pull out an ID from a deep link like example://example.com/deepLink/123. We annotated with #DeepLink and specify there will be a parameter that we'll identify with id.
#DeepLink("example://example.com/deepLink/{id}")
public class SampleActivity extends Activity {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent.getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {
Bundle parameters = intent.getExtras();
String idString = parameters.getString("id");
// Do something with idString
}
}
}