Skip to content
This repository was archived by the owner on Oct 26, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';

var { NativeModules } = require('react-native');
module.exports = NativeModules.ChromeCustomTabsClient;
module.exports = NativeModules.ChromeCustomTabsClient;
7 changes: 7 additions & 0 deletions ChromeCustomTabsClient.ios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

var { Linking } = require('react-native');

// Fall back to Linking.openURL on iOS.
module.exports.launchCustomTab = Linking.openURL;
module.exports.mayLaunchUrl = function(url) {};
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,26 @@ project(':ReactNativeChromeCustomTabs').projectDir = new File(rootProject.projec
4. Import and register the module in your `MainActivity.java` file:
```java
import com.dstaley.ReactNativeChromeCustomTabs.ChromeCustomTabsPackage; // <-- Import
```

### For React Native >= v0.29

```java
public class MyReactNativeHost extends ReactNativeHost {
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
...
new ChromeCustomTabsPackage(), // <-- Register
...
);
}
}
```

### For React Native v0.19 - v0.28

```java
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {

private ReactInstanceManager mReactInstanceManager;
Expand Down Expand Up @@ -53,6 +72,27 @@ ChromeCustomTabsClient.mayLaunchUrl('http://i.imgur.com/6ogeF96.gif');
ChromeCustomTabsClient.launchCustomTab('http://i.imgur.com/xjdem.gif');
```

## Customization

You can supply a `CustomTabsIntentEditor` to customize the CustomTabsIntent produced by
this package.

```java
new ChromeCustomTabsPackage(new CustomTabsIntentEditor() {
@Override
public void customize(Context context, CustomTabsIntent.Builder builder) {
builder
.addDefaultShareMenuItem()
.setShowTitle(true)
.enableUrlBarHiding();
}
})
```

For a full description of the available options, see the official documentation for
[CustomTabsIntent.Builder](https://developer.android.com/reference/android/support/customtabs/CustomTabsIntent.Builder.html)
and the [custom tabs implementation guide](https://developer.chrome.com/multidevice/android/customtabs#implementationguide).

## License

MIT
3 changes: 1 addition & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ android {

dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.android.support:customtabs:23.1.0"
compile "com.android.support:customtabs:25.1.0"
compile "com.facebook.react:react-native:0.17.+"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,43 @@

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.net.Uri;
import android.widget.Toast;
import android.support.annotation.Nullable;
import android.support.customtabs.CustomTabsIntent;
import android.support.v7.app.AppCompatActivity;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.Map;
import java.util.HashMap;

import com.dstaley.ReactNativeChromeCustomTabs.CustomTabActivityHelper;

public class ChromeCustomTabsModule extends ReactContextBaseJavaModule implements CustomTabActivityHelper.ConnectionCallback {

Activity mActivity;
private CustomTabActivityHelper mCustomTabActivityHelper;
private ReactApplicationContext mContext;
private CustomTabsIntentEditor mIntentEditor;

public ChromeCustomTabsModule(ReactApplicationContext reactContext, Activity activity) {
ChromeCustomTabsModule(
ReactApplicationContext reactContext,
@Nullable CustomTabsIntentEditor intentEditor) {
super(reactContext);
mActivity = activity;
mContext = reactContext;
String packageName = CustomTabsHelper.getPackageNameToUse(mActivity);
mIntentEditor = intentEditor;
mCustomTabActivityHelper = new CustomTabActivityHelper();
mCustomTabActivityHelper.setConnectionCallback(this);
mCustomTabActivityHelper.bindCustomTabsService(mActivity, reactContext.getApplicationContext());
mCustomTabActivityHelper.bindCustomTabsService(reactContext.getApplicationContext());
}

private void sendEvent(String eventName) {
if (mContext.hasActiveCatalystInstance()) {
mContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, null);
try {
if (mContext.hasActiveCatalystInstance()) {
mContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, null);
}
} catch (RuntimeException e) {
// Work around a race condition in RN < 0.38.0, resulting in
// a RuntimeException of "Attempt to call JS function before JS bundle is loaded."
// Fixed in react-native#6a45f05.
}
}

Expand Down Expand Up @@ -71,7 +69,22 @@ public void mayLaunchUrl(String url) {

@ReactMethod
public void launchCustomTab(String url) {
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder(mCustomTabActivityHelper.getSession()).build();
mCustomTabActivityHelper.openCustomTab(mActivity, customTabsIntent, Uri.parse(url), null);
Activity activity = getCurrentActivity();
if (activity == null) {
return;
}

CustomTabsIntent.Builder builder =
new CustomTabsIntent.Builder(mCustomTabActivityHelper.getSession());
if (mIntentEditor != null) {
mIntentEditor.customize(activity, builder);
}
CustomTabActivityHelper.openCustomTab(activity, builder.build(), Uri.parse(url),
new CustomTabActivityHelper.CustomTabFallback() {
@Override
public void openUri(Activity activity, Uri uri) {
activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
}
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,29 @@

public class ChromeCustomTabsPackage implements ReactPackage {

Activity mActivity;
private final CustomTabsIntentEditor mIntentEditor;

public ChromeCustomTabsPackage() {
this((CustomTabsIntentEditor) null);
}

public ChromeCustomTabsPackage(CustomTabsIntentEditor intentEditor) {
mIntentEditor = intentEditor;
}

/**
* @deprecated
* The activity parameter is no longer used.
*/
@Deprecated
public ChromeCustomTabsPackage(Activity activity) {
mActivity = activity;
this((CustomTabsIntentEditor) null);
}

@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new ChromeCustomTabsModule(reactContext, mActivity));
modules.add(new ChromeCustomTabsModule(reactContext, mIntentEditor));
return modules;
}

Expand All @@ -39,4 +52,4 @@ public List<Class<? extends JavaScriptModule>> createJSModules() {
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.asList();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ public void setConnectionCallback(ConnectionCallback connectionCallback) {
* Binds the Activity to the Custom Tabs Service.
* @param activity the activity to be binded to the service.
*/
public void bindCustomTabsService(Activity activity, Context context) {
public void bindCustomTabsService(Context context) {
if (mClient != null) return;

String packageName = CustomTabsHelper.getPackageNameToUse(activity);
String packageName = CustomTabsHelper.getPackageNameToUse(context);
if (packageName == null) return;

mConnection = new ServiceConnection(this);
Expand Down Expand Up @@ -170,4 +170,4 @@ public interface CustomTabFallback {
void openUri(Activity activity, Uri uri);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dstaley.ReactNativeChromeCustomTabs;

import android.content.Context;
import android.support.customtabs.CustomTabsIntent;

/**
* Callback for customizing the creation of a CustomTabsIntent.
* This is called just before a custom tab is opened.
*/
public interface CustomTabsIntentEditor {

void customize(Context context, CustomTabsIntent.Builder builder);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected void onCreate(Bundle savedInstanceState) {
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.addPackage(new ChromeCustomTabsPackage(this))
.addPackage(new ChromeCustomTabsPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
Expand Down