Skip to content

Commit

Permalink
Support android.
Browse files Browse the repository at this point in the history
  • Loading branch information
miyabi committed Feb 19, 2018
1 parent c1182c2 commit 79562c7
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 24 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"warn",
"never"
],
"no-unused-vars": ["warn", { "args": "none" }]
"no-unused-vars": ["warn", { "args": "none" }],
"no-console": "off"
}
}
15 changes: 8 additions & 7 deletions PassKit.android.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
/**
* @flow
*/
/* global module */
'use strict'

import { NativeModules } from 'react-native'
import type EmitterSubscription from 'EmitterSubscription'

const nativeModule = NativeModules.RNPassKit

export default {
canAddPasses: (): Promise<boolean> => (
Promise.resolve(false)
),
...nativeModule,

presentAddPassesViewController: (base64Encoded: string): Promise<void> => (
Promise.resolve()
),
presentAddPassesViewController: (base64Encoded: string): Promise<void> => {
console.warn('PassKit.presentAddPassesViewController is deprecated. Use PassKit.addPass instead.')
return nativeModule.addPass(base64Encoded)
},

addEventListener: (
eventType: string,
Expand Down
6 changes: 5 additions & 1 deletion PassKit.ios.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* @flow
*/
/* global module */
'use strict'

import { NativeModules, NativeEventEmitter } from 'react-native'
Expand All @@ -13,6 +12,11 @@ const nativeEventEmitter = new NativeEventEmitter(nativeModule)
export default {
...nativeModule,

presentAddPassesViewController: (base64Encoded: string): Promise<void> => {
console.warn('PassKit.presentAddPassesViewController is deprecated. Use PassKit.addPass instead.')
return nativeModule.addPass(base64Encoded)
},

addEventListener: (
eventType: string,
listener: Function,
Expand Down
77 changes: 67 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,80 @@
# react-native-passkit-wallet
React Native module to handle PassKit.
React Native module to handle PassKit pass.

## Installation

1. Install library from `npm`

```shell
npm install --save react-native-passkit-wallet
```

1. Link native code

```shell
react-native link react-native-passkit-wallet
```


### Android configuration

1. Add following lines to AndroidManifest.xml

```diff
<manifest ...>
<application ...>
...
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.mybdesign.RNPassKit.fileprovider"
+ android:grantUriPermissions="true"
+ android:exported="false">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/passkit_file_paths" />
+ </provider>
</application>
</manifest>
```

1. Create passkit_file_paths.xml

Create `passkit_file_paths.xml` file in your project's `android/src/main/res/xml` directory.
pkpass file will be created in your app's cache directory.

```xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="passkit" path="/"/>
</paths>
```

## Usage

```jsx
import PassKit, { AddPassButton } from 'react-native-passkit-wallet'
```
### Check whether the device supports adding passes
```jsx
PassKit.canAddPasses()
.then((result) => {
console.log(result)
})
```
### Display a button that enables users to add passes to Wallet
For Android, `true` will be returned if apps that can open pkpass files are installed.
### Prompt the user to add the pass to the pass library
```jsx
PassKit.addPass(base64EncodedPass)
```
For Android, a dialogue box will appear to choose an app to open the pass.
### Display a button that enables users to add passes to Wallet (iOS only)
```jsx
class App extends Component<{}> {
render() {
Expand All @@ -29,12 +89,8 @@ class App extends Component<{}> {
}
```
### Show a pass and prompt the user to add that pass to the pass library
```jsx
PassKit.presentAddPassesViewController(base64EncodedPass)
```
### Handle events (iOS only)
### Handle events
```jsx
class App extends Component<{}> {
// To keep the context of 'this'
Expand All @@ -57,9 +113,10 @@ class App extends Component<{}> {
}
```
### Constants
### Constants (iOS only)
- *PassKit.AddPassButtonStyle* - The appearance of the add-pass button
- *black* - A black button with white lettering
- *blackOutline* - A black button with a light outline
- *black* - A black button with white lettering
- *blackOutline* - A black button with a light outline
- *PassKit.AddPassButtonWidth* - Default add-pass button width
- *PassKit.AddPassButtonHeight* - Default add-pass button height
17 changes: 17 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 26
buildToolsVersion "26.0.1"

defaultConfig {
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
}

dependencies {
provided 'com.facebook.react:react-native:+'
}
3 changes: 3 additions & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mybdesign.RNPassKit">
</manifest>
69 changes: 69 additions & 0 deletions android/src/main/java/com/mybdesign/RNPassKit/RNPassKitModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.mybdesign.RNPassKit;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.FileProvider;
import android.util.Base64;

import com.facebook.react.bridge.JSApplicationCausedNativeException;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import java.io.File;
import java.io.FileOutputStream;
import java.util.UUID;

public class RNPassKitModule extends ReactContextBaseJavaModule {
private final String FILE_PROVIDER = "com.mybdesign.RNPassKit.fileprovider";
private final String PKPASS_TYPE = "application/vnd.apple.pkpass";

public RNPassKitModule(ReactApplicationContext reactContext) {
super(reactContext);
}

@Override
public String getName() {
return "RNPassKit";
}

private Intent intentWithContentUri(Uri uri, String type) {
return new Intent(Intent.ACTION_VIEW)
.setDataAndType(uri, type)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

@ReactMethod
public void canAddPasses(Promise promise) {
try {
Intent intent = this.intentWithContentUri(Uri.parse("content://"), PKPASS_TYPE);
boolean canAddPass = intent.resolveActivity(getReactApplicationContext().getPackageManager()) != null;
promise.resolve(canAddPass);
} catch (Exception e) {
promise.reject(new JSApplicationCausedNativeException(e.getMessage()));
}
}

@ReactMethod
public void addPass(String base64Encoded, Promise promise) {
try {
Context context = getReactApplicationContext();

File file = new File(context.getCacheDir(), UUID.randomUUID().toString() + ".pkpass");
FileOutputStream stream = new FileOutputStream(file, true);
stream.write(Base64.decode(base64Encoded, 0));
stream.flush();
stream.close();

Uri uri = FileProvider.getUriForFile(context, FILE_PROVIDER, file);
Intent intent = this.intentWithContentUri(uri, PKPASS_TYPE);
context.startActivity(intent);
promise.resolve(null);
} catch (Exception e) {
promise.reject(new JSApplicationCausedNativeException(e.getMessage()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.mybdesign.RNPassKit;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RNPassKitPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}

@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();

modules.add(new RNPassKitModule(reactContext));

return modules;
}
}
2 changes: 1 addition & 1 deletion ios/RNPassKit/RNPassKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ @implementation RNPassKit
resolve(@([PKAddPassesViewController canAddPasses]));
}

RCT_EXPORT_METHOD(presentAddPassesViewController:(NSString *)base64Encoded
RCT_EXPORT_METHOD(addPass:(NSString *)base64Encoded
resolver:(RCTPromiseResolveBlock)resolve
rejector:(RCTPromiseRejectBlock)reject) {
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Encoded options:NSUTF8StringEncoding];
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-native-passkit-wallet",
"version": "0.0.3",
"description": "React Native module to handle PassKit.",
"version": "0.1.0",
"description": "React Native module to handle PassKit pass.",
"main": "index",
"scripts": {
"lint": "eslint .",
Expand All @@ -14,7 +14,8 @@
},
"keywords": [
"react-native",
"ios"
"ios",
"android"
],
"author": "Masayuki Iwai <[email protected]> (http://mybdesign.com/)",
"license": "MIT",
Expand Down

0 comments on commit 79562c7

Please sign in to comment.