mirror of
https://github.com/nextcloud/android.git
synced 2024-11-22 21:25:35 +03:00
Work a bit more on notifications
This commit is contained in:
parent
50bed99eec
commit
047bd3cc8e
6 changed files with 253 additions and 13 deletions
|
@ -178,8 +178,8 @@ dependencies {
|
|||
compile name: 'touch-image-view'
|
||||
compile 'com.android.support:multidex:1.0.1'
|
||||
|
||||
compile 'com.github.nextcloud:android-library:notifications-SNAPSHOT'
|
||||
compile 'com.github.nextcloud:android-library:1.0.14'
|
||||
|
||||
compile 'com.github.nextcloud:android-library:notifications-push-SNAPSHOT'
|
||||
compile "com.android.support:support-v4:${supportLibraryVersion}"
|
||||
compile "com.android.support:design:${supportLibraryVersion}"
|
||||
compile 'com.jakewharton:disklrucache:2.0.2'
|
||||
|
|
|
@ -122,6 +122,8 @@
|
|||
<!-- Files becomes Home -->
|
||||
<bool name="use_home">false</bool>
|
||||
|
||||
<!-- Push server url -->
|
||||
<string name="push_server_url" translatable="true"></string>
|
||||
</resources>
|
||||
|
||||
|
||||
|
|
|
@ -19,28 +19,89 @@
|
|||
*/
|
||||
package com.owncloud.android.services.firebase;
|
||||
|
||||
import android.util.Log;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.firebase.iid.FirebaseInstanceId;
|
||||
import com.google.firebase.iid.FirebaseInstanceIdService;
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.authentication.AccountUtils;
|
||||
import com.owncloud.android.lib.common.OwnCloudAccount;
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.notifications.RegisterAccountDeviceForNotificationsOperation;
|
||||
import com.owncloud.android.lib.resources.notifications.RegisterAccountDeviceForProxyOperation;
|
||||
import com.owncloud.android.lib.resources.notifications.models.PushResponse;
|
||||
import com.owncloud.android.utils.PushUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class NCFirebaseInstanceIDService extends FirebaseInstanceIdService {
|
||||
private static final String TAG = "NCFirebaseInstanceID";
|
||||
|
||||
@Override
|
||||
public void onTokenRefresh() {
|
||||
//You can implement this method to store the token on your server
|
||||
if (!TextUtils.isEmpty(getResources().getString(R.string.push_server_url))) {
|
||||
PushUtils.generateRsa2048KeyPair();
|
||||
}
|
||||
|
||||
//Getting registration token
|
||||
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
|
||||
|
||||
//Displaying token on logcat
|
||||
Log.d(TAG, "Refreshed token: " + refreshedToken);
|
||||
|
||||
sendRegistrationToServer(FirebaseInstanceId.getInstance().getToken());
|
||||
}
|
||||
|
||||
private void sendRegistrationToServer(String token) {
|
||||
//You can implement this method to store the token on your server
|
||||
//Not required for current project
|
||||
String pushTokenHash = PushUtils.generateSHA512Hash(token);
|
||||
PublicKey devicePublicKey = (PublicKey) PushUtils.readKeyFromFile(true);
|
||||
if (devicePublicKey != null) {
|
||||
String publicKey = devicePublicKey.toString();
|
||||
|
||||
Context context = MainApp.getAppContext();
|
||||
for (Account account : AccountUtils.getAccounts(context)) {
|
||||
try {
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
|
||||
OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||
getClientFor(ocAccount, context);
|
||||
|
||||
RemoteOperation registerAccountDeviceForNotificationsOperation =
|
||||
new RegisterAccountDeviceForNotificationsOperation(pushTokenHash,
|
||||
publicKey, context.getResources().getString(R.string.push_server_url));
|
||||
|
||||
RemoteOperationResult remoteOperationResult = registerAccountDeviceForNotificationsOperation.
|
||||
execute(mClient);
|
||||
|
||||
if (remoteOperationResult.isSuccess()) {
|
||||
PushResponse pushResponse = remoteOperationResult.getPushResponseData();
|
||||
|
||||
RemoteOperation registerAccountDeviceForProxyOperation = new
|
||||
RegisterAccountDeviceForProxyOperation(
|
||||
context.getResources().getString(R.string.push_server_url),
|
||||
token, pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
|
||||
pushResponse.getPublicKey());
|
||||
|
||||
remoteOperationResult = registerAccountDeviceForProxyOperation.execute(mClient);
|
||||
}
|
||||
} catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
|
||||
Log_OC.d(TAG, "Failed to find an account");
|
||||
} catch (AuthenticatorException e) {
|
||||
Log_OC.d(TAG, "Failed via AuthenticatorException");
|
||||
} catch (IOException e) {
|
||||
Log_OC.d(TAG, "Failed via IOException");
|
||||
} catch (OperationCanceledException e) {
|
||||
Log_OC.d(TAG, "Failed via OperationCanceledException");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,17 +31,18 @@ import android.util.Log;
|
|||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.lib.resources.notifications.models.Notification;
|
||||
import com.owncloud.android.ui.activity.NotificationsActivity;
|
||||
|
||||
public class NCFirebaseMessagingService extends FirebaseMessagingService {
|
||||
private static final String TAG = "NCFirebaseMessaging";
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
super.onMessageReceived(remoteMessage);
|
||||
Log.d(TAG, "From: " + remoteMessage.getFrom());
|
||||
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
|
||||
|
||||
sendNotification(remoteMessage.getNotification().ge);
|
||||
sendNotification(remoteMessage.getNotification().getTitle());
|
||||
}
|
||||
|
||||
private void sendNotification(String contentTitle) {
|
||||
|
@ -55,6 +56,7 @@ public class NCFirebaseMessagingService extends FirebaseMessagingService {
|
|||
.setSmallIcon(R.mipmap.ic_launcher)
|
||||
.setContentTitle(contentTitle)
|
||||
.setSound(defaultSoundUri)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
|
|
170
src/modified/java/com/owncloud/android/utils/PushUtils.java
Normal file
170
src/modified/java/com/owncloud/android/utils/PushUtils.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
/**
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 Mario Danic
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.utils;
|
||||
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
public class PushUtils {
|
||||
|
||||
private static final String TAG = "PushUtils";
|
||||
private static final String KEYPAIR_FOLDER = "nc-keypair";
|
||||
private static final String KEYPAIR_FILE_NAME = "push_key";
|
||||
private static final String KEYPAIR_PUB_EXTENSION = ".pub";
|
||||
|
||||
public static String generateSHA512Hash(String pushToken) {
|
||||
MessageDigest messageDigest = null;
|
||||
try {
|
||||
messageDigest = MessageDigest.getInstance("SHA-512");
|
||||
byte[] byteData = messageDigest.digest(pushToken.getBytes("UTF-8"));
|
||||
String base64 = Base64.encodeToString(byteData, Base64.NO_WRAP);
|
||||
return base64;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log_OC.d(TAG, "SHA-512 algorithm not supported");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log_OC.d(TAG, "Unsupported encoding");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static int generateRsa2048KeyPair() {
|
||||
String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
|
||||
+ KEYPAIR_FOLDER;;
|
||||
|
||||
String privateKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME;
|
||||
String publicKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PUB_EXTENSION;
|
||||
File keyPathFile = new File(keyPath);
|
||||
if (!new File(privateKeyPath).exists() && !new File(publicKeyPath).exists()) {
|
||||
try {
|
||||
Log.d("MARIO", keyPathFile.getAbsolutePath());
|
||||
keyPathFile.createNewFile();
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyGen.initialize(2048);
|
||||
|
||||
KeyPair pair = keyGen.generateKeyPair();
|
||||
int statusPrivate = saveKeyToFile(pair.getPrivate(), privateKeyPath);
|
||||
int statusPublic = saveKeyToFile(pair.getPublic(), publicKeyPath);
|
||||
|
||||
if (statusPrivate == 0 && statusPublic == 0) {
|
||||
// all went well
|
||||
return 0;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log_OC.d(TAG, "Failed to generate a keypair folder path" + e.getLocalizedMessage());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log_OC.d(TAG, "RSA algorithm not supported");
|
||||
}
|
||||
} else {
|
||||
// we already have the key
|
||||
return -1;
|
||||
}
|
||||
|
||||
// we failed to generate the key
|
||||
return -2;
|
||||
}
|
||||
|
||||
public static Key readKeyFromFile(boolean readPublicKey) {
|
||||
String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
|
||||
+ KEYPAIR_FOLDER;;
|
||||
String privateKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME;
|
||||
String publicKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PUB_EXTENSION;
|
||||
|
||||
String path;
|
||||
|
||||
if (readPublicKey) {
|
||||
path = publicKeyPath;
|
||||
} else {
|
||||
path = privateKeyPath;
|
||||
}
|
||||
|
||||
FileInputStream fileInputStream = null;
|
||||
try {
|
||||
fileInputStream = new FileInputStream(path);
|
||||
byte[] bytes = new byte[fileInputStream.available()];
|
||||
fileInputStream.read(bytes);
|
||||
fileInputStream.close();
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
|
||||
if (readPublicKey) {
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
|
||||
PublicKey key = keyFactory.generatePublic(keySpec);
|
||||
return key;
|
||||
} else {
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
|
||||
PrivateKey key = keyFactory.generatePrivate(keySpec);
|
||||
return key;
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
Log_OC.d(TAG, "Failed to find path while reading the Key");
|
||||
} catch (IOException e) {
|
||||
Log_OC.d(TAG, "IOException while reading the key");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
Log_OC.d(TAG, "InvalidKeySpecException while reading the key");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log_OC.d(TAG, "RSA algorithm not supported");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int saveKeyToFile(Key key, String path) {
|
||||
byte[] encoded = key.getEncoded();
|
||||
FileOutputStream keyFileOutputStream = null;
|
||||
try {
|
||||
keyFileOutputStream = new FileOutputStream(path);
|
||||
keyFileOutputStream.write(encoded);
|
||||
keyFileOutputStream.close();
|
||||
return 0;
|
||||
} catch (FileNotFoundException e) {
|
||||
Log_OC.d(TAG, "Failed to save key to file");
|
||||
} catch (IOException e) {
|
||||
Log_OC.d(TAG, "Failed to save key to file via IOException");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -109,6 +109,9 @@
|
|||
|
||||
<!-- login data links -->
|
||||
<string name="login_data_own_scheme" translatable="false">cloud</string>
|
||||
<!-- url for webview login, with the protocol prefix
|
||||
If set, will replace all other login methods available -->
|
||||
<string name="webview_login_url" translatable="false"></string>
|
||||
|
||||
<!-- analytics enabled -->
|
||||
<bool name="analytics_enabled">false</bool>
|
||||
|
@ -116,6 +119,8 @@
|
|||
<!-- Files becomes Home -->
|
||||
<bool name="use_home">true</bool>
|
||||
|
||||
<!-- Push server url -->
|
||||
<string name="push_server_url" translatable="false"></string>
|
||||
</resources>
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue