Here is my activity structure: SplashActivity -> MainActivity. My MainActivity has a Spinner that is populated from ContentProvider. Based on Spinner selection, I present different content to the user. The content map perfectly to the content on my website. My website has long been indexed and is working fine. Now I want to index said content in my app.
Here is my manifest
<activity android:name=".activities.SplashActivity"
android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity"/>
<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="www.business.com"
android:scheme="http"/>
<data
android:host="www.business.com"
android:scheme="https"/>
<data
android:host="business.com"
android:scheme="http"/>
<data
android:host="business.com"
android:scheme="https"/>
<data
android:host="/*"
android:scheme="business"/>
<data android:scheme="android-app"
android:host="com.business.android" />
</intent-filter>
</activity>
Here is the app-indexing portion of my MainActivity
#Override
public void onStart() {
super.onStart();
appIndexingTask();
}
private void appIndexingTask() {
new AsyncTask() {
#Override
protected Object doInBackground(Object[] params) {
try {
if(null == mNdxClient){
mNdxClient = new GoogleApiClient.Builder(MainActivity.this)
.enableAutoManage(MainActivity.this, MainActivity.this)
.addApi(AppInvite.API).addApi(AppIndex.API)
.build();
}
if(!mNdxClient.isConnected()){
mNdxClient.blockingConnect();
}
if (mNdxClient != null && mNdxClient.isConnected()) {
HashMap<Uri, Action> indexedActions = new HashMap<>();
List<Content> contentList = getAllFromContentProvider();
for(Content c: contentList){
Uri uri = Uri.parse(FirebaseUtils.appIndexingLink(c.getUrl()));
Action action = getAction(c.getName(), c.getDescription(), uri);
AppIndex.AppIndexApi.start(mNdxClient, action);
indexedActions.put(uri, action);
}
for (Action action : indexedActions.values()) {
AppIndex.AppIndexApi.end(mNdxClient, indexedActions.get(action));
}
}
} catch (Exception e) {
//abandon task
}
return null;
}
public Action getAction(String title, String description, Uri uri) {
Thing object = new Thing.Builder()
.setName(title)
.setDescription(description)
.setUrl(uri)
.build();
return new Action.Builder(Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
.build();
}
}.execute();
}
Here is the Utility method
public static String appIndexingLink(String urlString){
String appNdx= new StringBuilder("android-app://").append(BASE_URL).append(urlString).toString();
return appNdx;
}
Finally, in gradle I am using
classpath 'com.google.gms:google-services:3.0.0'//project level
//app level
compile 'com.google.android.gms:play-services-appindexing:9.0.0'
compile 'com.google.firebase:firebase-core:9.0.0'
compile "com.google.firebase:firebase-messaging:9.0.0"
compile "com.google.firebase:firebase-invites:9.0.0"
Some important points
App-Invite works: I can send an invite and then open the invite (code not shown)
Deep Linking works, if I send myself a link to my site, when I open the link on my android phone, it opens it with the app perfectly.
Google Search has not indexed my app
Fetch as Google fails with “URI unsupported” whether I point to Play Store or local apk.
Notice the filter
<data android:scheme="android-app"
android:host="com. business.android" />
I don’t see it anywhere in documentations. But nothing else works. So I added it. It’s still not working.
Although I am not showing logging. I am logging and so I know that the app-indexing code runs.
Related
I want to implement deep linking for facebook app post.
Firstly I want to share my App content on Facebook Post and when user tap on the post then if User already has the app installed then open app otherwise It will open app link.
I follow https://developers.facebook.com/docs/applinks/android and https://developers.facebook.com/docs/sharing/android#linkshare but It's not working
how to share this data using LinkShare on facebook
target_url: "https://developers.facebook.com/android"
extras:
fb_app_id: [YOUR_FACEBOOK_APP_ID]
fb_access_token: "[ACCESS_TOKEN]"
fb_expires_in: 3600
To implement deep linking and sharing together, need to implement this feature using branch.io
Add dependency :
compile 'com.google.android.gms:play-services-appindexing:9.+'
Add this code in the manifest file inside Launcher Activity
<!-- Branch URI Scheme -->
<intent-filter>
<data android:scheme="androidexample" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<!-- Branch App Links (optional) -->
<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="example.app.link" />
<data android:scheme="https" android:host="example-alternate.app.link" />
</intent-filter>
Add this code to your Launcher Activity, You will get your link and data in this method
#Override
public void onStart() {
super.onStart();
// Branch init
Branch.getInstance().initSession(new Branch.BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
Log.i("BRANCH SDK", referringParams.toString());
// Retrieve deeplink keys from 'referringParams' and evaluate the values to determine where to route the user
// Check '+clicked_branch_link' before deciding whether to use your Branch routing logic
} else {
Log.i("BRANCH SDK", error.getMessage());
}
}
}, this.getIntent().getData(), this);
}
Add this code in MyApplication class
// Branch logging for debugging
Branch.enableLogging();
// Branch object initialization
Branch.getAutoInstance(this);
You can create deep link using this code
LinkProperties lp = new LinkProperties()
.setChannel("facebook")
.setFeature("sharing")
.setCampaign("content 123 launch")
.setStage("new user")
.addControlParameter("$desktop_url", "http://example.com/home")
.addControlParameter("custom", "data")
.addControlParameter("custom_random",
Long.toString(Calendar.getInstance().getTimeInMillis()));
buo.generateShortUrl(this, lp, new
Branch.BranchLinkCreateListener() {
#Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
Log.i("BRANCH SDK", "got my Branch link to share: " + url);
}
}
});
refer this for Android
refer this for ios
Problem: Why is "Short dynamic links" created programatically wont open/launch the app directly?
I want to launch app directly when user clicks the dynamic url created dynamically by android app.
When clicking dynamic short link created dynamically by android app the following things happen,
1.Option show two options one is through chrome other is through app
2.if i choose chrome option, browser opens, shows a loading dialog box and launch app with PendingDynamicLinkData data
3.but if i choose app option, app lauches app but PendingDynamicLinkData is lost or null.
Any Help would be great. my manifest setting is below
<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:host="myapp.page.link" android:scheme="http"/>
<data android:host="myapp.page.link" android:scheme="https"/>
</intent-filter>
You should handle your PendingDynamicLinkData in activity to override onCreate and onNewIntent. Like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent != null) {
handleDeepLink(intent);
}
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null) {
handleDeepLink(intent);
}
}
private void handleDeepLink(Intent intent) {
FirebaseDynamicLinks.getInstance().getDynamicLink(intent).addOnSuccessListener(pendingDynamicLinkData -> {
if (pendingDynamicLinkData != null) {
Uri deepLink = pendingDynamicLinkData.getLink();
if (deepLink != null) {
// todo .....
}
}
});
}
I don't know the correct solution but I have found a trick that works.
First make sure that you have added the following intent filter to the activity that is supposed to handle the dynamic link:
<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:host="example.com"
android:scheme="http" />
<data
android:host="example.com"
android:scheme="https" />
</intent-filter>
Source
Then in your activity, use the following code to get the link:
String link=null;
if (getIntent().getData()!=null){
link=getIntent().getData().toString();
}
In the manifest, add the following intent filter to the activity that will handle the url:
override OnStart method of the target Activity:
public override fun onStart() {
super.onStart()
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) {
deepLink = pendingDynamicLinkData.getLink();
}
// ...
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "getDynamicLink:onFailure", e);
}
});
The complete guide here.
For some reason, i couldn't make it work in the same activity that as action MAIN.
I'm new on flutter and never used intent filter. so far I have everything working in my app. but I'm stuck in importing the file to app by open with dialog. I need the user when it click on the file it will go to the page and display the information in the file. I'm using ImportFile plugin and it work fine but it make it harder for the users to put the file they receive.
my app is list it in the open with dialog but when i click it, it just open the app I want it to open the app and view the text in the view text page not the homepage
AndroidManifest.xml
<
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.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<data android:pathPattern="*.*\\.txt" />
</intent-filter>
MainActivity.java
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
}
}
new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler(new MethodChannel.MethodCallHandler() {
#Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
if (methodCall.method.contentEquals("getSharedText")) {
result.success(sharedText);
sharedText = null;
}
}
});
}
void handleSendText(Intent intent) {
sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
}
Thank you in advance
FlutterView has a setInitialRoute method you can use to specify a non-default route on launch.
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();
}
}
I want to open my application on link click instead of the browser if the application is installed on the device , and open Google play otherwise.
so after searching .. This is my manifest
<activity
android:name="example.com.MyActivity"
android:label="#string/title_activity_open_event_details" >
<intent-filter>
<data
android:host="play.google.com"
android:scheme="http"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
and this is my activity
public class MyActivity extends Activity {
private int EventId;
private TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_open_event_details);
tv = (TextView) findViewById(R.id.testtv);
Uri data = getIntent().getData();
if ( data != null )
{
String scheme = data.getScheme();
String host = data.getHost();
List<String> params = data.getPathSegments();
String first = params.get(0);
String second = params.get(1);
int size = params.size();
// EventId = params.get(size-1);
String third = params.get(size-1);
tv.setText(data.toString());
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my_activity, menu);
return true;
}
}
when I click on this link https://play.google.com/store/apps/details?id=example.com&evid=117
MyActivity opens successfully but the link that appears in the textview is only https://play.google.com/store/apps/details?id=example.com without &evid=117 which I need to get some data and display it in my activity
could you please help me to know what I am missing ?
Thanks in advance
To get that id try this code:
Uri data = getIntent().getData();
if (data != null) {
String url = data.toString();
try {
List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), "UTF-8");
for (NameValuePair para : params)
if (para.getName().equals("evid")) {
String id = para.getValue(); //my id (117)
Log.v("myId",id);
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
Also you are not including the https protocol. Add
<data android:host="play.google.com" android:scheme="https"/>
EDIT
I've tested this code and it's working. I've created a simple activity with the code I provided above and for the intent filter:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<action android:name="android.intent.action.VIEW"/>
<data android:host="play.google.com" android:scheme="http"/>
<data android:host="play.google.com" android:scheme="https"/>
</intent-filter>
The output result is, as expected, 117