Start an app within another app Android - android

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();
}
}

Related

Facebook deferred deep linking not working when ad preview is clicked

<activity
android:name=".MainActivity"
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>
<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" />
<!-- Accepts URIs that begin with "memoryc://cerebrotrial” -->
<data
android:host="cerebrotrial"
android:scheme="memoryc" />
</intent-filter>
</activity>
When I test my ad from the Ad Helper in Facebook, the deferred link is successfully transmitted. But when I click the ad preview from the Facebook app, the deferred deep link is null. I try to catch the deep-link with the below implementations. I first try to get the deep link from the AppLinkData, then from the most basic getIntent() implementation and finally by the bolts.Applinks. The ApplinkData is null, the intent does not return anything and the targetUrl is null.
// Suggested Facebook implementation
FacebookSdk.setAutoInitEnabled(true);
FacebookSdk.fullyInitialize();
AppLinkData.fetchDeferredAppLinkData(this,
new AppLinkData.CompletionHandler() {
#Override
public void onDeferredAppLinkDataFetched(AppLinkData appLinkData) {
// Process app link data
if (appLinkData != null) {
ConfigAPI.setRefererURL(appLinkData.getTargetUri().toString());
JsonObject jsonParams = ConfigAPI.getPayLoad();
new CallAPI(jsonParams).execute();
}
}
}
);
//persist deep link data
Intent intent = getIntent();
Uri data = intent.getData();
if (data != null) {
Log.i("DEEP LINK", data.toString());
ConfigAPI.setRefererURL(data.toString());
JsonObject jsonParams = ConfigAPI.getPayLoad();
new CallAPI(jsonParams).execute();
}
// using the bolts.Applinks
Uri targetUrl = AppLinks.getTargetUrlFromInboundIntent(this, getIntent());
if (targetUrl != null) {
ConfigAPI.setRefererURL(targetUrl.toString());
JsonObject jsonParams = ConfigAPI.getPayLoad();
new CallAPI(jsonParams).execute();
}

Unable to fetch referral code after install android app from app store

In my application have a referral program.I want when a customer share app link, that link redirect to playstore and after install app referral code retrieve from playstore. I already do that link but I don't understand how can i receive that referral code after install.
public static void shareMyApp(Context context) {
String link = "https://play.google.com/store/apps/details?id="+context.getPackageName();
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/*");
sharingIntent.putExtra(Intent.EXTRA_TEXT, link);
context.startActivity(Intent.createChooser(sharingIntent, "Share Via"));
}
For that, you have to use below the library
implementation 'com.android.installreferrer:installreferrer:1.0'
https://developer.android.com/google/play/installreferrer/library
https://developer.android.com/training/app-links/deep-linking.html
Thanks, it may help you
Create a link with referral code and send to others friends and users...
String link = http://yourdomain.com/testrefer.php?refercode=ABCD // http or https
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_TEXT, link);
context.startActivity(Intent.createChooser(sharingIntent, "Share Via"));
and in testrefer file to create app store link and append refercode and then redirect to play store using below link and then you can get referral code.
https://play.google.com/store/apps/details?id="+context.getPackageName()+"&referrer=ABCD
in Manifest file in your launching screen to write below code
<activity
android:name=".activity.SplActivity"
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="yourdomain.com"
android:pathPrefix="/testrefer.php"
android:scheme="https" /> <!-- https or http -->
</intent-filter>
</activity>
InstallRefererReciever is a file name that you have created BroadcastReceiver
<receiver
android:name=".common.InstallRefererReciever"
android:exported="true"
android:permission="android.permission.INSTALL_PACKAGES">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
Create BroascatReceiver and write below code :
public class InstallRefererReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
Bundle extras = intent.getExtras();
if (extras != null) {
String referral = extras.getString("referrer");
Logger.e("ReferCode --> ", referral);
if (referral != null) {
if (!referral.equals("utm_source=google-play&utm_medium=organic")) {
if (!referral.equals("com.android.chrome")) {
String referralCode = referral; // Store in sharedpreferences
}
}
}
}
}
}
}

Block mobile website to open my app android deeplink - Google Chrome

I have supported deeplinks in my app
<activity android:name=".DeepLinkActivity" android:noHistory="true"></activity>
<activity-alias
android:name="com.example.Launcher"
android:targetActivity=".DeepLinkActivity">
<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" />
<data android:scheme="http" />
<data android:scheme="#string/SCHEMA" />
<data android:host="#string/WEB_DOMAIN" />
<data android:host="#string/WWW_WEB_DOMAIN" />
<data android:path="/" />
<data android:path="/x" android:pathPattern="/x/.*" />
</intent-filter>
</activity-alias>
So whenever user clicks on www.example.com the android app asks to open as app or web that is fine, but I do not want when my users are on mobile site they should be asked to open in app. I have gone through many stackoverflow posts but everyone says its not possible but still many websites are handling this scenario.
As per this Article the behaviour depends on user gestures, if user is clicking on any link then Chrome displays a chooser while if user is typing url on browser then it doesn't.
After lot of research I have solved it. You can use either way.
Handle in mobile website : So if you want to render your user to Chrome always when they are on your msite you can achieve this by redirecting all your urls to
googlechrome://navigate?url=https://www.example.com
intent://www.example.com/x#Intent;scheme=https;package=com.android.chrome;S.browser_fallback_url=https://www/example.com/x;action=android.intent.action.VIEW;end;
Handle in app
Create single transparent activity to handle all your deeplinks
Handle all the links using pathpattern = '.*'
Redirect user back to Chrome for urls you do not want to handle in app.
AndroidManifest.xml
<activity
android:name=".DeepLinkActivity"
android:noHistory="true"
android:theme="#style/Theme.Transparent">
<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" />
<data android:scheme="http" />
<data android:scheme="#string/SCHEMA" />
<data android:host="#string/WEB_DOMAIN" />
<data android:host="#string/WWW_WEB_DOMAIN" />
<data android:pathPattern="/.*" />
</intent-filter>
</activity>
DeepLinkActivity
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
try {
if (Intent.ACTION_VIEW.equals(getIntent().getAction())) {
Uri uri = getIntent().getData();
if (uri == null) throw new IllegalArgumentException("Uri can not be null");
Intent intent = null;
if (getString(R.string.SCHEMA).equals(uri.getScheme()) || uri.toString().matches(Links.REGEX)) {
intent = linkIntent(uri);
}
if (intent == null) SystemUtil.launchUrlInDefaultBrowser(uri, this); else startActivity(intent);
}
} catch (IllegalArgumentException e) {
Toast.makeText(this, R.string.can_not_open_url, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, R.string.can_not_open_url, Toast.LENGTH_SHORT).show();
} finally {
finish();
}
}
/**
* This will open the provided url in browser except the current app.
* #param url Uri
* #param context Activity Context
*/
public static void launchUrlInDefaultBrowser(Uri url, Context context) {
try {
ResolveInfo packageInfo = null;
final Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
browserIntent.setData(url);
// Try to find anything that we can launch the URL with. Pick up the first one that can.
final List<ResolveInfo> resolveInfoList = context.getPackageManager().queryIntentActivities(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
if (!resolveInfoList.isEmpty()) {
for (ResolveInfo list : resolveInfoList) {
if (!BuildConfig.APP_PACKAGE_NAME.equals(list.activityInfo.packageName)) {
packageInfo = list;
break;
}
}
}
if (packageInfo != null) {
browserIntent.setClassName(packageInfo.activityInfo.packageName, packageInfo.activityInfo.name);
context.startActivity(browserIntent);
} else {
Toast.makeText(context, R.string.can_not_open_url, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Toast.makeText(context, R.string.can_not_open_url, Toast.LENGTH_SHORT).show();
}
}

How to transfer files with Android NFC

I am trying to use Android Beam to transfer large files between apps. The sending part is working well and files are appearing in the 'beam/' directory. The Notification status bar displays "Beam complete". However, the receiving app does not get notified after the files are renamed into the beam/ directory and onNewIntent() never gets called on the receiving end. What am I missing with the intent-filter? Also is it possible to specify a Android Application Record while using createBeamUris()? TIA
// sending app
nfcAdapter.setBeamPushUrisCallback(this, this);
...
#Override
public Uri[] createBeamUris(NfcEvent event) { // send files
File dir = Environment.getExternalStorageDirectory();
File file = new File(dir, "test.txt");
file.setReadable(true, false); // readable=true, ownerOnly=false
return new Uri[] { Uri.fromFile(file) };
}
My Manifest.xml:
<activity
android:name=".BeamDemo2"
android:label="#string/app_name"
android:launchMode="singleTop" >
<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:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.txt" />
<data android:host="*" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.example.beamdemo2" />
</intent-filter>
</activity>
I have also tried enableForegroundDispatch():
#Override
public void onResume() {
super.onResume();
try {
PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndefIntent = new IntentFilter("android.intent.action.VIEW");
ndefIntent.addCategory("android.intent.category.DEFAULT");
ndefIntent.addDataType("*/*");
IntentFilter[]mIntentFilters = new IntentFilter[] { ndefIntent };
String[][] mNFCTechLists = new String[][] { new String[] { NfcF.class.getName() } };
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilters, mNFCTechLists);
} catch (Exception e) {
Log.e("onResume", e.toString());
}
}
Short answer, there is no answer :-(. After the Beam finishes, one needs to pull down the "Beam Complete" notification and select "View File". This causes a Chooser to appear, and then a VIEW intent is dispatched to the activity. I was hoping to avoid this manual step, but it seems to be unavoidable. I'd also like to avoid the Chooser to select an application for VIEW, but that too seems unavoidable. EnableForegroundDispatch seems to be only for android.nfc.action.NDEF_DISCOVERED.
After choosing the app, things work as expected. I see onNewIntent(), followed by onResume(). One weirdness, the received intent seems to stick and keeps reappearing. After processing the VIEW intent in onResume(), I had to kill it by calling setIntent(null).
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
#Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
processIntent(intent); //
setIntent(null); // kill this event
}
}

How to launch an app using a deeplink in android

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()
}

Categories

Resources