Skip to content

Commit 6788247

Browse files
authored
fix(app-launcher): improvements on canOpenUrl and openUrl (#2476) (#2478)
1 parent 550622c commit 6788247

3 files changed

Lines changed: 63 additions & 20 deletions

File tree

app-launcher/README.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ On iOS you can only open apps if you know their url scheme.
66

77
On Android you can open apps if you know their url scheme or use their public package name.
88

9-
**Note:** On [Android 11](https://developer.android.com/about/versions/11/privacy/package-visibility) and newer you have to add the app package names you want to query in the `AndroidManifest.xml` inside the `queries` tag.
9+
**Note:** On [Android 11](https://developer.android.com/about/versions/11/privacy/package-visibility) and newer you have to add the app package names or url schemes you want to query in the `AndroidManifest.xml` inside the `queries` tag.
1010

1111
Example:
1212
```xml
1313
<queries>
14-
<package android:name="com.getcapacitor.myapp" />
14+
<!-- Query by package name -->
15+
<package android:name="com.twitter.android" />
16+
<!-- Query by url scheme -->
17+
<intent>
18+
<action android:name="android.intent.action.VIEW"/>
19+
<data android:scheme="twitter"/>
20+
</intent>
1521
</queries>
1622
```
1723

@@ -27,14 +33,26 @@ npx cap sync
2733
```typescript
2834
import { AppLauncher } from '@capacitor/app-launcher';
2935

30-
const checkCanOpenUrl = async () => {
31-
const { value } = await AppLauncher.canOpenUrl({ url: 'com.getcapacitor.myapp' });
32-
36+
const checkCanOpenTwitterUrl = async () => {
37+
const { value } = await AppLauncher.canOpenUrl({ url: 'twitter://timeline' });
3338
console.log('Can open url: ', value);
3439
};
3540

36-
const openPortfolioPage = async () => {
37-
await AppLauncher.openUrl({ url: 'com.getcapacitor.myapp://page?id=portfolio' });
41+
const openTwitterUrl = async () => {
42+
const { completed } = await AppLauncher.openUrl({ url: 'twitter://timeline' });
43+
console.log('openUrl completed: ', completed);
44+
};
45+
46+
// Android only
47+
const checkCanOpenTwitterPackage = async () => {
48+
const { value } = await AppLauncher.canOpenUrl({ url: 'com.twitter.android' });
49+
console.log('Can open package: ', value);
50+
};
51+
52+
// Android only
53+
const openTwitterPackage = async () => {
54+
const { completed } = await AppLauncher.openUrl({ url: 'com.twitter.android' });
55+
console.log('openUrl package completed: ', completed);
3856
};
3957
```
4058

@@ -68,6 +86,12 @@ This method always returns false for undeclared schemes, whether or not an
6886
appropriate app is installed. To learn more about the key, see
6987
[LSApplicationQueriesSchemes](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/plist/info/LSApplicationQueriesSchemes).
7088

89+
On Android the URL can be a known URLScheme or an app package name.
90+
91+
On [Android 11](https://developer.android.com/about/versions/11/privacy/package-visibility)
92+
and newer you have to add the app package names or url schemes you want to query in the `AndroidManifest.xml`
93+
inside the `queries` tag.
94+
7195
| Param | Type |
7296
| ------------- | --------------------------------------------------------------- |
7397
| **`options`** | <code><a href="#canopenurloptions">CanOpenURLOptions</a></code> |

app-launcher/android/src/main/java/com/capacitorjs/plugins/applauncher/AppLauncherPlugin.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.content.Context;
44
import android.content.Intent;
55
import android.content.pm.PackageManager;
6+
import android.content.pm.ResolveInfo;
67
import android.net.Uri;
78
import com.getcapacitor.JSObject;
89
import com.getcapacitor.Logger;
@@ -35,36 +36,48 @@ public void canOpenUrl(PluginCall call) {
3536
} catch (PackageManager.NameNotFoundException e) {
3637
Logger.error(getLogTag(), "Package name '" + url + "' not found!", null);
3738
}
38-
39-
ret.put("value", false);
39+
if (!canResolve(pm, new Intent(Intent.ACTION_VIEW, Uri.parse(url)))) {
40+
ret.put("value", canResolve(pm, new Intent(url)));
41+
} else {
42+
ret.put("value", true);
43+
}
4044
call.resolve(ret);
4145
}
4246

47+
private boolean canResolve(PackageManager pm, Intent intent) {
48+
ResolveInfo resolve = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
49+
return resolve != null;
50+
}
51+
4352
@PluginMethod
4453
public void openUrl(PluginCall call) {
4554
String url = call.getString("url");
4655
if (url == null) {
4756
call.reject("Must provide a url to open");
4857
return;
4958
}
50-
5159
JSObject ret = new JSObject();
5260
final PackageManager manager = getContext().getPackageManager();
5361
Intent launchIntent = new Intent(Intent.ACTION_VIEW);
5462
launchIntent.setData(Uri.parse(url));
55-
56-
try {
57-
getActivity().startActivity(launchIntent);
58-
ret.put("completed", true);
59-
} catch (Exception ex) {
60-
launchIntent = manager.getLaunchIntentForPackage(url);
61-
try {
62-
getActivity().startActivity(launchIntent);
63+
if (!canLaunchIntent(launchIntent)) {
64+
if (!canLaunchIntent(manager.getLaunchIntentForPackage(url))) {
65+
ret.put("completed", canLaunchIntent(new Intent(url)));
66+
} else {
6367
ret.put("completed", true);
64-
} catch (Exception expgk) {
65-
ret.put("completed", false);
6668
}
69+
} else {
70+
ret.put("completed", true);
6771
}
6872
call.resolve(ret);
6973
}
74+
75+
private boolean canLaunchIntent(Intent intent) {
76+
try {
77+
getActivity().startActivity(intent);
78+
return true;
79+
} catch (Exception ex) {
80+
return false;
81+
}
82+
}
7083
}

app-launcher/src/definitions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export interface AppLauncherPlugin {
1111
* appropriate app is installed. To learn more about the key, see
1212
* [LSApplicationQueriesSchemes](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/plist/info/LSApplicationQueriesSchemes).
1313
*
14+
* On Android the URL can be a known URLScheme or an app package name.
15+
*
16+
* On [Android 11](https://developer.android.com/about/versions/11/privacy/package-visibility)
17+
* and newer you have to add the app package names or url schemes you want to query in the `AndroidManifest.xml`
18+
* inside the `queries` tag.
19+
*
1420
* @since 1.0.0
1521
*/
1622
canOpenUrl(options: CanOpenURLOptions): Promise<CanOpenURLResult>;

0 commit comments

Comments
 (0)