Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FCM implementation #167

Open
wants to merge 37 commits into
base: v3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ed409a2
Implement reauthenticateWithCredentialForProvider for Android
ghuh Nov 8, 2016
972b16d
Catch exception thrown by setPersistenceEnabled which was causing the…
chaitanya-bhagavan Nov 8, 2016
a4a115f
Parity in response format between ios and android
chaitanya-bhagavan Nov 8, 2016
483e15f
Fixed a typo that was causing an error
chaitanya-bhagavan Nov 8, 2016
a85f5fa
Parity in response format between ios and android
chaitanya-bhagavan Nov 9, 2016
e34988b
Reverted changes since it was an error from my end
chaitanya-bhagavan Nov 9, 2016
68396e0
fixing filter value creation
pedro-ribeiro Nov 9, 2016
635f882
Merge pull request #122 from pedro-ribeiro/fixing_equalto
auser Nov 9, 2016
ea5e10c
Merge pull request #119 from chaitanya0bhagvan/master
auser Nov 9, 2016
b55ba69
Merge pull request #117 from ghuh/ghuh-android-reauthenticateWithCred…
auser Nov 9, 2016
c3129fb
Fix Android listenForAuth method to correctly check for user
ghuh Nov 10, 2016
28644a6
WIP: FirebaseAuth
auser Nov 10, 2016
1111617
Added initial handling of android error messages
auser Nov 10, 2016
c811a3a
Merge pull request #124 from ghuh/ghuh-android-listenForAuth
auser Nov 11, 2016
7d09ab4
Parity of response format between ios and android. Added authenticate…
chaitanya-bhagavan Nov 11, 2016
e525569
Remove RCTConvert to work with react-native-fcm
auser Nov 14, 2016
9f9525d
Merge branch 'master' of github.com:fullstackreact/react-native-fires…
auser Nov 14, 2016
ef52467
Merge pull request #126 from chaitanya0bhagvan/master
auser Nov 14, 2016
8306c45
Filter out undefined filters
samer Nov 16, 2016
487ed30
removing trailing comma
pedro-ribeiro Nov 16, 2016
a0a78e5
Merge pull request #137 from pedro-ribeiro/fixing_trailing_comma
auser Nov 16, 2016
da34c79
Merge pull request #136 from samer/filter-fix
auser Nov 16, 2016
6ca78a1
forEach and map method on the DataSnapshot does not retain key
chaitanya-bhagavan Nov 17, 2016
80133de
Fixed error calling length of undefined
chaitanya-bhagavan Nov 17, 2016
0349b61
Merge pull request #139 from chaitanya0bhagvan/master
auser Nov 17, 2016
d005ab2
Use storage url from .plist file if not setStorageUrl() hasn't been c…
janvogt Nov 17, 2016
dfc0bd1
Fix donwloadUrl to use storageUrl from .plist.
janvogt Nov 17, 2016
e214b6d
Merge pull request #143 from janvogt/fix-storage-config
auser Nov 17, 2016
f4bcfea
WIP
auser Nov 18, 2016
29140b6
Merge branch 'master' of github.com:fullstackreact/react-native-fires…
auser Nov 18, 2016
f715d41
Updated with @Salakar v3
auser Nov 18, 2016
7774ac1
Merge pull request #152 from Salakar/master
Salakar Nov 21, 2016
98d873f
Implement firestack.storage.download() for android
BlooJeans Nov 21, 2016
f3233ad
Factor out errorCodes for future constants
BlooJeans Nov 21, 2016
d50e976
Remove unused/old database.js
BlooJeans Nov 21, 2016
f034c1f
Merge pull request #154 from devshackio/android-downloadFile
Salakar Nov 22, 2016
4bb951c
FCM implementation
tretelny416 Nov 26, 2016
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
12 changes: 12 additions & 0 deletions android/.idea/gradle.xml

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

2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ allprojects {

dependencies {
compile 'com.facebook.react:react-native:0.20.+'
compile 'com.google.android.gms:play-services-base:9.8.0'
compile 'com.google.android.gms:play-services-base:+'
compile 'com.google.firebase:firebase-core:9.8.0'
compile 'com.google.firebase:firebase-config:9.8.0'
compile 'com.google.firebase:firebase-auth:9.8.0'
Expand Down
169 changes: 152 additions & 17 deletions android/src/main/java/io/fullstack/firestack/FirestackStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import android.content.Context;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.HashMap;

Expand All @@ -26,6 +29,8 @@
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;

import com.google.firebase.storage.StorageException;
import com.google.firebase.storage.StreamDownloadTask;
import com.google.firebase.storage.UploadTask;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageMetadata;
Expand All @@ -49,6 +54,18 @@ class FirestackStorageModule extends ReactContextBaseJavaModule {
private static final String FileTypeRegular = "FILETYPE_REGULAR";
private static final String FileTypeDirectory = "FILETYPE_DIRECTORY";

private static final String STORAGE_UPLOAD_PROGRESS = "upload_progress";
private static final String STORAGE_UPLOAD_PAUSED = "upload_paused";
private static final String STORAGE_UPLOAD_RESUMED = "upload_resumed";

private static final String STORAGE_DOWNLOAD_PROGRESS = "download_progress";
private static final String STORAGE_DOWNLOAD_PAUSED = "download_paused";
private static final String STORAGE_DOWNLOAD_RESUMED = "download_resumed";
private static final String STORAGE_DOWNLOAD_SUCCESS = "download_success";
private static final String STORAGE_DOWNLOAD_FAILURE = "download_failure";

private ReactContext mReactContext;

public FirestackStorageModule(ReactApplicationContext reactContext) {
super(reactContext);

Expand All @@ -60,6 +77,118 @@ public String getName() {
return TAG;
}


public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}

@ReactMethod
public void downloadFile(final String urlStr,
final String fbPath,
final String localFile,
final Callback callback) {
Log.d(TAG, "downloadFile: "+urlStr+", "+localFile);
if (!isExternalStorageWritable()) {
Log.w(TAG, "downloadFile failed: external storage not writable");
WritableMap error = Arguments.createMap();
final int errorCode = 1;
error.putDouble("code", errorCode);
error.putString("description", "downloadFile failed: external storage not writable");
callback.invoke(error);
return;
}
FirebaseStorage storage = FirebaseStorage.getInstance();
String storageBucket = storage.getApp().getOptions().getStorageBucket();
String storageUrl = "gs://" + storageBucket;
Log.d(TAG, "Storage url " + storageUrl + fbPath);

StorageReference storageRef = storage.getReferenceFromUrl(storageUrl);
StorageReference fileRef = storageRef.child(fbPath);

fileRef.getStream(new StreamDownloadTask.StreamProcessor() {
@Override
public void doInBackground(StreamDownloadTask.TaskSnapshot taskSnapshot, InputStream inputStream) throws IOException {
int indexOfLastSlash = localFile.lastIndexOf("/");
String pathMinusFileName = localFile.substring(0, indexOfLastSlash) + "/";
String filename = localFile.substring(indexOfLastSlash+1);
File fileWithJustPath = new File(pathMinusFileName);
if (!fileWithJustPath.mkdirs()) {
Log.e(TAG, "Directory not created");
WritableMap error = Arguments.createMap();
error.putString("message", "Directory not created");
callback.invoke(error);
return;
}
File fileWithFullPath = new File(pathMinusFileName, filename);
FileOutputStream output = new FileOutputStream(fileWithFullPath);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
output.close();
}
}).addOnProgressListener(new OnProgressListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onProgress(StreamDownloadTask.TaskSnapshot taskSnapshot) {
WritableMap data = Arguments.createMap();
data.putString("ref", taskSnapshot.getStorage().getBucket());
double percentComplete = taskSnapshot.getTotalByteCount() == 0 ? 0.0f : 100.0f * (taskSnapshot.getBytesTransferred()) / (taskSnapshot.getTotalByteCount());
data.putDouble("progress", percentComplete);
FirestackUtils.sendEvent(mReactContext, STORAGE_DOWNLOAD_PROGRESS, data);
}
}).addOnPausedListener(new OnPausedListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onPaused(StreamDownloadTask.TaskSnapshot taskSnapshot) {
WritableMap data = Arguments.createMap();
data.putString("ref", taskSnapshot.getStorage().getBucket());
FirestackUtils.sendEvent(mReactContext, STORAGE_DOWNLOAD_PAUSED, data);
}
}).addOnSuccessListener(new OnSuccessListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onSuccess(StreamDownloadTask.TaskSnapshot taskSnapshot) {
final WritableMap data = Arguments.createMap();
StorageReference ref = taskSnapshot.getStorage();
data.putString("fullPath", ref.getPath());
data.putString("bucket", ref.getBucket());
data.putString("name", ref.getName());
ref.getMetadata().addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
@Override
public void onSuccess(final StorageMetadata storageMetadata) {
data.putMap("metadata", getMetadataAsMap(storageMetadata));
callback.invoke(null, data);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
final int errorCode = 1;
WritableMap data = Arguments.createMap();
StorageException storageException = StorageException.fromException(exception);
data.putString("description", storageException.getMessage());
data.putInt("code", errorCode);
callback.invoke(makeErrorPayload(errorCode, exception));
}
});
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
final int errorCode = 1;
WritableMap data = Arguments.createMap();
StorageException storageException = StorageException.fromException(exception);
data.putString("description", storageException.getMessage());
data.putInt("code", errorCode);
callback.invoke(makeErrorPayload(errorCode, exception));
}
});
}

@ReactMethod
public void downloadUrl(final String javascriptStorageBucket,
final String path,
Expand Down Expand Up @@ -90,16 +219,7 @@ public void onSuccess(Uri uri) {
public void onSuccess(final StorageMetadata storageMetadata) {
Log.d(TAG, "getMetadata success " + storageMetadata);

WritableMap metadata = Arguments.createMap();
metadata.putString("getBucket", storageMetadata.getBucket());
metadata.putString("getName", storageMetadata.getName());
metadata.putDouble("sizeBytes", storageMetadata.getSizeBytes());
metadata.putDouble("created_at", storageMetadata.getCreationTimeMillis());
metadata.putDouble("updated_at", storageMetadata.getUpdatedTimeMillis());
metadata.putString("md5hash", storageMetadata.getMd5Hash());
metadata.putString("encoding", storageMetadata.getContentEncoding());

res.putMap("metadata", metadata);
res.putMap("metadata", getMetadataAsMap(storageMetadata));
res.putString("name", storageMetadata.getName());
res.putString("url", storageMetadata.getDownloadUrl().toString());
callback.invoke(null, res);
Expand All @@ -109,7 +229,8 @@ public void onSuccess(final StorageMetadata storageMetadata) {
@Override
public void onFailure(@NonNull Exception exception) {
Log.e(TAG, "Failure in download " + exception);
callback.invoke(makeErrorPayload(1, exception));
final int errorCode = 1;
callback.invoke(makeErrorPayload(errorCode, exception));
}
});

Expand All @@ -129,6 +250,18 @@ public void onFailure(@NonNull Exception exception) {
});
}

private WritableMap getMetadataAsMap(StorageMetadata storageMetadata) {
WritableMap metadata = Arguments.createMap();
metadata.putString("getBucket", storageMetadata.getBucket());
metadata.putString("getName", storageMetadata.getName());
metadata.putDouble("sizeBytes", storageMetadata.getSizeBytes());
metadata.putDouble("created_at", storageMetadata.getCreationTimeMillis());
metadata.putDouble("updated_at", storageMetadata.getUpdatedTimeMillis());
metadata.putString("md5hash", storageMetadata.getMd5Hash());
metadata.putString("encoding", storageMetadata.getContentEncoding());
return metadata;
}

// STORAGE
@ReactMethod
public void uploadFile(final String urlStr, final String name, final String filepath, final ReadableMap metadata, final Callback callback) {
Expand Down Expand Up @@ -191,9 +324,9 @@ public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {

if (progress >= 0) {
WritableMap data = Arguments.createMap();
data.putString("eventName", "upload_progress");
data.putString("eventName", STORAGE_UPLOAD_PROGRESS);
data.putDouble("progress", progress);
FirestackUtils.sendEvent(getReactApplicationContext(), "upload_progress", data);
FirestackUtils.sendEvent(getReactApplicationContext(), STORAGE_UPLOAD_PROGRESS, data);
}
}
})
Expand All @@ -204,13 +337,14 @@ public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
StorageMetadata d = taskSnapshot.getMetadata();
String bucket = d.getBucket();
WritableMap data = Arguments.createMap();
data.putString("eventName", "upload_paused");
data.putString("eventName", STORAGE_UPLOAD_PAUSED);
data.putString("ref", bucket);
FirestackUtils.sendEvent(getReactApplicationContext(), "upload_paused", data);
FirestackUtils.sendEvent(getReactApplicationContext(), STORAGE_UPLOAD_PAUSED, data);
}
});
} catch (Exception ex) {
callback.invoke(makeErrorPayload(2, ex));
final int errorCode = 2;
callback.invoke(makeErrorPayload(errorCode, ex));
}
}

Expand All @@ -221,7 +355,8 @@ public void getRealPathFromURI(final String uri, final Callback callback) {
callback.invoke(null, path);
} catch (Exception ex) {
ex.printStackTrace();
callback.invoke(makeErrorPayload(1, ex));
final int errorCode = 1;
callback.invoke(makeErrorPayload(errorCode, ex));
}
}

Expand Down
56 changes: 56 additions & 0 deletions docs/api/cloud-messaging.md
Original file line number Diff line number Diff line change
@@ -1 +1,57 @@
#cloud messaging

Make this prettier at some point but can't forget these things
setup certificates, enable push settings in app
Add things to app delegate
appdelegate.h ->
@import UserNotifications;
@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>

appdelegate.m
Appdidfinishwithlaunching blah blah
UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

if (localNotification) {
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_MESSAGE_RECEIVED_LOCAL object:localNotification];
NSLog(@"fresh launch from local notificaiton");
}

if(userInfo){
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_MESSAGE_RECEIVED_REMOTE object:self userInfo:userInfo];
NSLog(@"fresh launch from remote");
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification

// Print full message.
NSLog(@"%@", userInfo);

[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_MESSAGE_RECEIVED_REMOTE object:self userInfo:userInfo];

}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
NSLog(@"%@", userInfo);
if ( application.applicationState == UIApplicationStateActive ){
//user had the app in the foreground
}
else {
//app went from background to foreground
}
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_MESSAGE_RECEIVED_REMOTE object:self userInfo:userInfo];
completionHandler(UIBackgroundFetchResultNoData);
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSLog(@"%@", notification);
[[NSNotificationCenter defaultCenter] postNotificationName:MESSAGING_MESSAGE_RECEIVED_LOCAL object:notification];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"Notification Registration Error %@", [error description]);
}
4 changes: 3 additions & 1 deletion ios/Firestack/Firestack.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#import "FirestackErrors.h"
#import "FirestackEvents.h"
// #import "FirestackAnalytics.h"
// #import "FirestackCloudMessaging.h"
#import "FirestackCloudMessaging.h"

static Firestack *_sharedInstance = nil;
static dispatch_once_t onceToken;
Expand Down Expand Up @@ -239,6 +239,8 @@ - (FIRApp *) firebaseApp

// if (!self.configured) {

//If you want this method could replace all of the above for the option setting for firebase
//FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:plistPath];
if ([FIRApp defaultApp] == NULL) {
[FIRApp configureWithOptions:finalOptions];
}
Expand Down
9 changes: 5 additions & 4 deletions ios/Firestack/FirestackAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ @implementation FirestackAuth
} @catch(NSException *ex) {
NSDictionary *eventError = @{
@"eventName": AUTH_ANONYMOUS_ERROR_EVENT,
@"msg": ex.reason
@"errorMessage": ex.reason
};

[self sendJSEvent:AUTH_ERROR_EVENT
Expand Down Expand Up @@ -137,14 +137,15 @@ @implementation FirestackAuth
sendJSEvent:AUTH_CHANGED_EVENT
props: @{
@"eventName": @"userTokenError",
@"msg": [error localizedFailureReason]
@"authenticated": @((BOOL)true),
@"errorMessage": [error localizedFailureReason]
}];
} else {
[self
sendJSEvent:AUTH_CHANGED_EVENT
props: @{
@"eventName": @"user",
@"authenticated": @(true),
@"authenticated": @((BOOL)true),
@"user": userProps
}];
}
Expand All @@ -157,7 +158,7 @@ @implementation FirestackAuth
[self sendJSEvent:AUTH_CHANGED_EVENT
props:@{
@"eventName": @"no_user",
@"authenticated": @(false),
@"authenticated": @((BOOL)false),
@"error": err
}];
}
Expand Down
3 changes: 2 additions & 1 deletion ios/Firestack/FirestackCloudMessaging.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "RCTBridgeModule.h"
#import "RCTUtils.h"


@interface FirestackCloudMessaging : RCTEventEmitter <RCTBridgeModule> {

}
Expand All @@ -22,4 +23,4 @@

@end

#endif
#endif
Loading