Browse Source

Improve push / remove push registration

Mario Danic 8 years ago
parent
commit
7f1739f5f7

+ 2 - 2
build.gradle

@@ -197,8 +197,8 @@ dependencies {
     compile 'org.greenrobot:eventbus:3.0.0'
     compile 'com.googlecode.ez-vcard:ez-vcard:0.10.2'
 
-// uncomment for gplay, modified
-//    compile 'com.google.android.gms:play-services:10.2.1'
+    // uncomment for gplay, modified
+    //compile 'com.google.android.gms:play-services:10.2.4'
 
     compile 'org.parceler:parceler-api:1.1.6'
     annotationProcessor 'org.parceler:parceler:1.1.6'

+ 0 - 2
src/gplay/java/com/owncloud/android/services/firebase/NCFirebaseInstanceIDService.java

@@ -36,8 +36,6 @@ public class NCFirebaseInstanceIDService extends FirebaseInstanceIdService {
         //You can implement this method to store the token on your server
         if (!TextUtils.isEmpty(getResources().getString(R.string.push_server_url))) {
             PreferenceManager.setPushToken(MainApp.getAppContext(), FirebaseInstanceId.getInstance().getToken());
-            PreferenceManager.setPushTokenUpdateTime(MainApp.getAppContext(), System.currentTimeMillis());
-
             PushUtils.pushRegistrationToServer();
         }
     }

+ 10 - 0
src/gplay/java/com/owncloud/android/ui/activity/ModifiedFileDisplayActivity.java

@@ -20,9 +20,12 @@
 
 package com.owncloud.android.ui.activity;
 
+import android.os.Bundle;
+
 import com.owncloud.android.ui.events.TokenPushEvent;
 import com.owncloud.android.utils.PushUtils;
 
+import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.Subscribe;
 import org.greenrobot.eventbus.ThreadMode;
 
@@ -33,4 +36,11 @@ public class ModifiedFileDisplayActivity extends FileDisplayActivity {
         PushUtils.pushRegistrationToServer();
     }
 
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // see if there's stuff to push every time we start the app
+        EventBus.getDefault().post(new TokenPushEvent());
+    }
+
 }

+ 111 - 36
src/gplay/java/com/owncloud/android/utils/PushUtils.java

@@ -27,9 +27,12 @@ import android.content.Context;
 import android.text.TextUtils;
 import android.util.Base64;
 
+import com.google.gson.Gson;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.datamodel.ArbitraryDataProvider;
+import com.owncloud.android.datamodel.PushArbitraryData;
 import com.owncloud.android.db.PreferenceManager;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -39,8 +42,12 @@ 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.UnregisterAccountDeviceForNotificationsOperation;
+import com.owncloud.android.lib.resources.notifications.UnregisterAccountDeviceForProxyOperation;
 import com.owncloud.android.lib.resources.notifications.models.PushResponse;
 
+import org.apache.commons.httpclient.HttpStatus;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -65,7 +72,11 @@ public class PushUtils {
     private static final String KEYPAIR_PRIV_EXTENSION = ".priv";
     private static final String KEYPAIR_PUB_EXTENSION = ".pub";
 
-    public static String generateSHA512Hash(String pushToken) {
+    public static final String KEY_PUSH = "push";
+
+    private static ArbitraryDataProvider arbitraryDataProvider;
+
+    private static String generateSHA512Hash(String pushToken) {
         MessageDigest messageDigest = null;
         try {
             messageDigest = MessageDigest.getInstance("SHA-512");
@@ -86,7 +97,7 @@ public class PushUtils {
         return result.toString();
     }
 
-    public static int generateRsa2048KeyPair() {
+    private static int generateRsa2048KeyPair() {
         String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
                 + KEYPAIR_FOLDER;
 
@@ -124,8 +135,58 @@ public class PushUtils {
         return -2;
     }
 
+    private static void deleteRegistrationForAccount(Account account) {
+        Context context = MainApp.getAppContext();
+        OwnCloudAccount ocAccount = null;
+        arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().getContentResolver());
+
+        try {
+            ocAccount = new OwnCloudAccount(account, context);
+            OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                    getClientFor(ocAccount, context);
+
+            RemoteOperation unregisterAccountDeviceForNotificationsOperation = new
+                    UnregisterAccountDeviceForNotificationsOperation();
+
+            RemoteOperationResult remoteOperationResult = unregisterAccountDeviceForNotificationsOperation.
+                    execute(mClient);
+
+            if (remoteOperationResult.getHttpCode() == HttpStatus.SC_ACCEPTED) {
+                String arbitraryValue;
+                if (!TextUtils.isEmpty(arbitraryValue = arbitraryDataProvider.getValue(account, KEY_PUSH))) {
+                    Gson gson = new Gson();
+                    PushArbitraryData pushArbitraryData = gson.fromJson(arbitraryValue, PushArbitraryData.class);
+                    RemoteOperation unregisterAccountDeviceForProxyOperation =
+                            new UnregisterAccountDeviceForProxyOperation(context.getResources().
+                                    getString(R.string.push_server_url),
+                                    pushArbitraryData.getDeviceIdentifier(),
+                                    pushArbitraryData.getDeviceIdentifierSignature(),
+                                    pushArbitraryData.getUserPublicKey());
+
+                    remoteOperationResult = unregisterAccountDeviceForProxyOperation.execute(mClient);
+
+                    if (remoteOperationResult.isSuccess()) {
+                        arbitraryDataProvider.deleteKeyForAccount(account, KEY_PUSH);
+                    }
+                }
+            }
+
+
+        } 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");
+        }
+    }
+
     public static void pushRegistrationToServer() {
         String token = PreferenceManager.getPushToken(MainApp.getAppContext());
+        arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext().getContentResolver());
+
         if (!TextUtils.isEmpty(MainApp.getAppContext().getResources().getString(R.string.push_server_url)) &&
                 !TextUtils.isEmpty(token)) {
             PushUtils.generateRsa2048KeyPair();
@@ -139,42 +200,56 @@ public class PushUtils {
                 publicKey = "-----BEGIN PUBLIC KEY-----\n" + publicKey + "\n-----END PUBLIC KEY-----\n";
 
                 Context context = MainApp.getAppContext();
+                String providerValue;
+                Gson gson = new Gson();
                 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);
-                            PreferenceManager.setPushTokenLastSentTime(MainApp.getAppContext(),
-                                    System.currentTimeMillis());
-
+                    if (!TextUtils.isEmpty(providerValue = arbitraryDataProvider.getValue(account, KEY_PUSH))) {
+                        PushArbitraryData accountPushData = gson.fromJson(providerValue, PushArbitraryData.class);
+                        if (!accountPushData.getPushToken().equals(token) && !accountPushData.isShouldBeDeleted()) {
+                            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);
+
+                                    if (remoteOperationResult.isSuccess()) {
+                                        PushArbitraryData pushArbitraryData = new PushArbitraryData(token,
+                                                pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
+                                                pushResponse.getPublicKey(), false);
+                                        arbitraryDataProvider.storeOrUpdateKeyValue(account, KEY_PUSH,
+                                                gson.toJson(pushArbitraryData));
+                                    }
+                                }
+                            } 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");
+                            }
+                        } else if (accountPushData.isShouldBeDeleted()) {
+                            deleteRegistrationForAccount(account);
                         }
-                    } 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");
                     }
                 }
             }

+ 11 - 1
src/main/java/com/owncloud/android/datamodel/ArbitraryDataProvider.java

@@ -47,9 +47,19 @@ public class ArbitraryDataProvider {
         this.contentResolver = contentResolver;
     }
 
-    public void storeOrUpdateKeyValue(Account account, String key, String newValue) {
+    public int deleteKeyForAccount(Account account, String key) {
+        int result = contentResolver.delete(
+                ProviderMeta.ProviderTableMeta.CONTENT_URI_ARBITRARY_DATA,
+                ProviderMeta.ProviderTableMeta.ARBITRARY_DATA_CLOUD_ID + " = ? AND " +
+                        ProviderMeta.ProviderTableMeta.ARBITRARY_DATA_KEY + "= ?",
+                new String[]{account.name, key}
+        );
+
+        return result;
+    }
 
 
+    public void storeOrUpdateKeyValue(Account account, String key, String newValue) {
         ArbitraryDataSet data = getArbitraryDataSet(account, key);
         if (data == null) {
             Log_OC.v(TAG, "Adding arbitrary data with cloud id: " + account.name + " key: " + key

+ 81 - 0
src/main/java/com/owncloud/android/datamodel/PushArbitraryData.java

@@ -0,0 +1,81 @@
+/**
+ * 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.datamodel;
+
+public class PushArbitraryData {
+    public String pushToken;
+    public String deviceIdentifier;
+    public String deviceIdentifierSignature;
+    public String userPublicKey;
+    public boolean shouldBeDeleted;
+
+    public PushArbitraryData() {
+    }
+
+    public PushArbitraryData(String pushToken, String deviceIdentifier, String deviceIdentifierSignature,
+                             String userPublicKey, boolean shouldBeDeleted) {
+        this.pushToken = pushToken;
+        this.deviceIdentifier = deviceIdentifier;
+        this.deviceIdentifierSignature = deviceIdentifierSignature;
+        this.userPublicKey = userPublicKey;
+        this.shouldBeDeleted = shouldBeDeleted;
+    }
+
+    public String getPushToken() {
+        return pushToken;
+    }
+
+    public void setPushToken(String pushToken) {
+        this.pushToken = pushToken;
+    }
+
+    public String getDeviceIdentifier() {
+        return deviceIdentifier;
+    }
+
+    public void setDeviceIdentifier(String deviceIdentifier) {
+        this.deviceIdentifier = deviceIdentifier;
+    }
+
+    public String getDeviceIdentifierSignature() {
+        return deviceIdentifierSignature;
+    }
+
+    public void setDeviceIdentifierSignature(String deviceIdentifierSignature) {
+        this.deviceIdentifierSignature = deviceIdentifierSignature;
+    }
+
+    public String getUserPublicKey() {
+        return userPublicKey;
+    }
+
+    public void setUserPublicKey(String userPublicKey) {
+        this.userPublicKey = userPublicKey;
+    }
+
+    public boolean isShouldBeDeleted() {
+        return shouldBeDeleted;
+    }
+
+    public void setShouldBeDeleted(boolean shouldBeDeleted) {
+        this.shouldBeDeleted = shouldBeDeleted;
+    }
+}

+ 7 - 19
src/main/java/com/owncloud/android/db/PreferenceManager.java

@@ -47,33 +47,15 @@ public abstract class PreferenceManager {
     private static final String PREF__LEGACY_CLEAN = "legacyClean";
     private static final String PREF__AUTO_UPLOAD_UPDATE_PATH = "autoUploadPathUpdate";
     private static final String PREF__PUSH_TOKEN = "pushToken";
-    private static final String PREF__PUSH_TOKEN_UPDATE_TIME = "pushTokenLastUpdated";
-    private static final String PREF__PUSH_TOKEN_LAST_REGISTRATION_TIME = "pushTokenLastSent";
-
-    public static void setPushTokenLastSentTime(Context context, long time) {
-        saveLongPreference(context, PREF__PUSH_TOKEN_LAST_REGISTRATION_TIME, time);
-    }
-
-    public static long getPushTokenLastSentTime(Context context) {
-        return getDefaultSharedPreferences(context).getLong(PREF__PUSH_TOKEN_LAST_REGISTRATION_TIME, -1);
-    }
 
     public static void setPushToken(Context context, String pushToken) {
-        saveStringPreference(context, PREF__PUSH_TOKEN, pushToken);
+        saveStringPreferenceNow(context, PREF__PUSH_TOKEN, pushToken);
     }
 
     public static String getPushToken(Context context) {
         return getDefaultSharedPreferences(context).getString(PREF__PUSH_TOKEN, "");
     }
 
-    public static void setPushTokenUpdateTime(Context context, long time) {
-        saveLongPreference(context, PREF__PUSH_TOKEN_UPDATE_TIME, time);
-    }
-
-    public static long getPushTokenUpdateTime(Context context) {
-        return getDefaultSharedPreferences(context).getLong(PREF__PUSH_TOKEN_UPDATE_TIME, -1);
-    }
-
     public static boolean instantPictureUploadEnabled(Context context) {
         return getDefaultSharedPreferences(context).getBoolean(PREF__INSTANT_UPLOADING, false);
     }
@@ -289,6 +271,12 @@ public abstract class PreferenceManager {
         appPreferences.apply();
     }
 
+    private static void saveStringPreferenceNow(Context context, String key, String value) {
+        SharedPreferences.Editor appPreferences = getDefaultSharedPreferences(context.getApplicationContext()).edit();
+        appPreferences.putString(key, value);
+        appPreferences.commit();
+    }
+
     private static void saveIntPreference(Context context, String key, int value) {
         SharedPreferences.Editor appPreferences = getDefaultSharedPreferences(context.getApplicationContext()).edit();
         appPreferences.putInt(key, value);

+ 0 - 12
src/main/java/com/owncloud/android/ui/activity/FileActivity.java

@@ -162,8 +162,6 @@ public abstract class FileActivity extends DrawerActivity
 
         setAccount(account, savedInstanceState != null);
 
-        checkContactsBackupJob();
-
         mOperationsServiceConnection = new OperationsServiceConnection();
         bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection,
                 Context.BIND_AUTO_CREATE);
@@ -243,16 +241,6 @@ public abstract class FileActivity extends DrawerActivity
         }
     }
 
-    private void checkContactsBackupJob() {
-        ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(getContentResolver());
-
-        if (getAccount() != null && arbitraryDataProvider.getBooleanValue(getAccount(),
-                ContactsPreferenceActivity.PREFERENCE_CONTACTS_AUTOMATIC_BACKUP)) {
-            ContactsPreferenceActivity.startContactBackupJob(getAccount());
-        }
-    }
-
-
     /**
      * Getter for the main {@link OCFile} handled by the activity.
      *

+ 20 - 0
src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java

@@ -47,17 +47,22 @@ import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.google.gson.Gson;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.ArbitraryDataProvider;
+import com.owncloud.android.datamodel.PushArbitraryData;
 import com.owncloud.android.lib.common.UserInfo;
 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.users.GetRemoteUserInfoOperation;
+import com.owncloud.android.ui.events.TokenPushEvent;
 import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.PushUtils;
 
+import org.greenrobot.eventbus.EventBus;
 import org.parceler.Parcels;
 
 import butterknife.BindString;
@@ -349,6 +354,21 @@ public class UserInfoActivity extends FileActivity {
                                             ContactsPreferenceActivity.PREFERENCE_CONTACTS_AUTOMATIC_BACKUP,
                                             "false");
 
+
+                                    String arbitraryDataPushString;
+
+                                    if (!TextUtils.isEmpty(arbitraryDataPushString = arbitraryDataProvider.getValue(
+                                            account, PushUtils.KEY_PUSH))) {
+                                        Gson gson = new Gson();
+                                        PushArbitraryData pushArbitraryData = gson.fromJson(arbitraryDataPushString,
+                                                PushArbitraryData.class);
+                                        pushArbitraryData.setShouldBeDeleted(true);
+                                        arbitraryDataProvider.storeOrUpdateKeyValue(account, PushUtils.KEY_PUSH,
+                                                gson.toJson(pushArbitraryData));
+                                        EventBus.getDefault().post(new TokenPushEvent());
+                                    }
+
+
                                     if (getActivity() != null && !removeDirectly) {
                                         Bundle bundle = new Bundle();
                                         bundle.putParcelable(KEY_ACCOUNT, Parcels.wrap(account));