Эх сурвалжийг харах

Use android-job for scheduling

Mario Danic 8 жил өмнө
parent
commit
048b7f7bb3

+ 1 - 0
build.gradle

@@ -49,6 +49,7 @@ dependencies {
     compile 'com.getbase:floatingactionbutton:1.10.1'
     compile 'com.getbase:floatingactionbutton:1.10.1'
     compile 'com.google.code.findbugs:annotations:2.0.1'
     compile 'com.google.code.findbugs:annotations:2.0.1'
     compile group: 'commons-io', name: 'commons-io', version: '2.4'
     compile group: 'commons-io', name: 'commons-io', version: '2.4'
+    compile 'com.evernote:android-job:1.1.6'
 
 
     /// dependencies for local unit tests
     /// dependencies for local unit tests
     testCompile 'junit:junit:4.12'
     testCompile 'junit:junit:4.12'

+ 5 - 1
src/com/owncloud/android/MainApp.java

@@ -34,6 +34,7 @@ import android.os.IBinder;
 import android.preference.PreferenceManager;
 import android.preference.PreferenceManager;
 import android.support.v4.util.Pair;
 import android.support.v4.util.Pair;
 
 
+import com.evernote.android.job.JobManager;
 import com.owncloud.android.authentication.PassCodeManager;
 import com.owncloud.android.authentication.PassCodeManager;
 import com.owncloud.android.datamodel.SyncedFolder;
 import com.owncloud.android.datamodel.SyncedFolder;
 import com.owncloud.android.datamodel.SyncedFolderProvider;
 import com.owncloud.android.datamodel.SyncedFolderProvider;
@@ -41,6 +42,7 @@ import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.services.NCJobCreator;
 import com.owncloud.android.services.observer.SyncedFolderObserverService;
 import com.owncloud.android.services.observer.SyncedFolderObserverService;
 import com.owncloud.android.ui.activity.Preferences;
 import com.owncloud.android.ui.activity.Preferences;
 import com.owncloud.android.ui.activity.WhatsNewActivity;
 import com.owncloud.android.ui.activity.WhatsNewActivity;
@@ -115,7 +117,9 @@ public class MainApp extends Application {
         }
         }
 
 
         cleanOldEntries();
         cleanOldEntries();
-        
+
+        JobManager.create(this).addJobCreator(new NCJobCreator());
+
         Log_OC.d("SyncedFolderObserverService", "Start service SyncedFolderObserverService");
         Log_OC.d("SyncedFolderObserverService", "Start service SyncedFolderObserverService");
         Intent i = new Intent(this, SyncedFolderObserverService.class);
         Intent i = new Intent(this, SyncedFolderObserverService.class);
         startService(i);
         startService(i);

+ 21 - 23
src/com/owncloud/android/datamodel/UploadsStorageManager.java

@@ -21,17 +21,17 @@
 package com.owncloud.android.datamodel;
 package com.owncloud.android.datamodel;
 
 
 import android.accounts.Account;
 import android.accounts.Account;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
 import android.content.ContentResolver;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.Cursor;
 import android.net.Uri;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Build;
-import android.os.PersistableBundle;
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RequiresApi;
 
 
+import com.evernote.android.job.JobManager;
+import com.evernote.android.job.JobRequest;
+import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.db.OCUpload;
 import com.owncloud.android.db.OCUpload;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
@@ -46,6 +46,7 @@ import java.util.Calendar;
 import java.util.Collections;
 import java.util.Collections;
 import java.util.List;
 import java.util.List;
 import java.util.Observable;
 import java.util.Observable;
+import java.util.Set;
 
 
 /**
 /**
  * Database helper for storing list of files to be uploaded, including status
  * Database helper for storing list of files to be uploaded, including status
@@ -400,22 +401,20 @@ public class UploadsStorageManager extends Observable {
 
 
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     private List<OCUpload> getPendingJobs() {
     private List<OCUpload> getPendingJobs() {
-        JobScheduler js = (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+        Set<JobRequest> jobRequests = JobManager.create(mContext).getAllJobRequests();
 
 
         Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
         Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
 
 
         ArrayList<OCUpload> list = new ArrayList<>();
         ArrayList<OCUpload> list = new ArrayList<>();
 
 
-        if (js != null) {
-            for (JobInfo ji : js.getAllPendingJobs()) {
-                PersistableBundle extras = ji.getExtras();
-                if (extras.get("account").equals(currentAccount.name)) {
-                    OCUpload upload = new OCUpload(extras.getString("filePath"),
-                            extras.getString("remotePath"),
-                            extras.getString("account"));
+        for (JobRequest ji : jobRequests) {
+            PersistableBundleCompat extras = ji.getExtras();
+            if (extras.get("account").equals(currentAccount.name)) {
+                OCUpload upload = new OCUpload(extras.getString("filePath", ""),
+                        extras.getString("remotePath", ""),
+                        extras.getString("account", ""));
 
 
-                    list.add(upload);
-                }
+                list.add(upload);
             }
             }
         }
         }
 
 
@@ -424,16 +423,15 @@ public class UploadsStorageManager extends Observable {
 
 
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     public void cancelPendingJob(String accountName, String remotePath){
     public void cancelPendingJob(String accountName, String remotePath){
-        JobScheduler js = (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
-
-        if (js != null) {
-            for (JobInfo ji : js.getAllPendingJobs()) {
-                PersistableBundle extras = ji.getExtras();
-                if (remotePath.equalsIgnoreCase(extras.getString("remotePath")) &&
-                        accountName.equalsIgnoreCase(extras.getString("account"))) {
-                    js.cancel(ji.getId());
-                    break;
-                }
+        JobManager jobManager = JobManager.create(mContext);
+        Set<JobRequest> jobRequests = jobManager.getAllJobRequests();
+
+        for (JobRequest ji : jobRequests) {
+            PersistableBundleCompat extras = ji.getExtras();
+            if (remotePath.equalsIgnoreCase(extras.getString("remotePath", "")) &&
+                    accountName.equalsIgnoreCase(extras.getString("account", ""))) {
+                jobManager.cancel(ji.getJobId());
+                break;
             }
             }
         }
         }
     }
     }

+ 14 - 29
src/com/owncloud/android/services/SyncedFolderJobService.java → src/com/owncloud/android/services/AutoUploadJob.java

@@ -22,47 +22,37 @@
 package com.owncloud.android.services;
 package com.owncloud.android.services;
 
 
 import android.accounts.Account;
 import android.accounts.Account;
-import android.annotation.TargetApi;
-import android.app.job.JobParameters;
-import android.app.job.JobService;
 import android.content.Context;
 import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-import android.os.PersistableBundle;
+import android.support.annotation.NonNull;
 
 
+import com.evernote.android.job.Job;
+import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.utils.MimeTypeUtil;
 import com.owncloud.android.utils.MimeTypeUtil;
 
 
 import java.io.File;
 import java.io.File;
 
 
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public class SyncedFolderJobService extends JobService {
-    private static final String TAG = "SyncedFolderJobService";
+public class AutoUploadJob extends Job {
+    public static final String TAG = "AutoUploadJob";
 
 
-    public static final String LOCAL_PATH = "filePath";
+    private static final String LOCAL_PATH = "filePath";
     public static final String REMOTE_PATH = "remotePath";
     public static final String REMOTE_PATH = "remotePath";
     public static final String ACCOUNT = "account";
     public static final String ACCOUNT = "account";
     public static final String UPLOAD_BEHAVIOUR = "uploadBehaviour";
     public static final String UPLOAD_BEHAVIOUR = "uploadBehaviour";
 
 
+    @NonNull
     @Override
     @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        return START_REDELIVER_INTENT;
-    }
-
-    @Override
-    public boolean onStartJob(JobParameters params) {
+    protected Result onRunJob(Params params) {
         final Context context = MainApp.getAppContext();
         final Context context = MainApp.getAppContext();
-        PersistableBundle bundle = params.getExtras();
-        final String filePath = bundle.getString(LOCAL_PATH);
-        final String remotePath = bundle.getString(REMOTE_PATH);
-        final Account account = AccountUtils.getOwnCloudAccountByName(context, bundle.getString(ACCOUNT));
-        final Integer uploadBehaviour = bundle.getInt(UPLOAD_BEHAVIOUR);
+        PersistableBundleCompat bundle = params.getExtras();
+        final String filePath = bundle.getString(LOCAL_PATH, "");
+        final String remotePath = bundle.getString(REMOTE_PATH, "");
+        final Account account = AccountUtils.getOwnCloudAccountByName(context, bundle.getString(ACCOUNT, ""));
+        final Integer uploadBehaviour = bundle.getInt(UPLOAD_BEHAVIOUR, -1);
 
 
-        Log_OC.d(TAG, "startJob: " + params.getJobId() + ", filePath: " + filePath);
 
 
         File file = new File(filePath);
         File file = new File(filePath);
 
 
@@ -72,7 +62,6 @@ public class SyncedFolderJobService extends JobService {
             final String mimeType = MimeTypeUtil.getBestMimeTypeByFilename(file.getAbsolutePath());
             final String mimeType = MimeTypeUtil.getBestMimeTypeByFilename(file.getAbsolutePath());
 
 
             final FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
             final FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
-
             requester.uploadNewFile(
             requester.uploadNewFile(
                     context,
                     context,
                     account,
                     account,
@@ -84,11 +73,7 @@ public class SyncedFolderJobService extends JobService {
                     UploadFileOperation.CREATED_AS_INSTANT_PICTURE
                     UploadFileOperation.CREATED_AS_INSTANT_PICTURE
             );
             );
         }
         }
-        return false;
-    }
 
 
-    @Override
-    public boolean onStopJob(JobParameters params) {
-        return false;
+        return Result.SUCCESS;
     }
     }
 }
 }

+ 30 - 43
src/com/owncloud/android/services/FileAlterationMagicListener.java

@@ -3,31 +3,30 @@
  *
  *
  * @author Mario Danic
  * @author Mario Danic
  * Copyright (C) 2017 Mario Danic
  * Copyright (C) 2017 Mario Danic
- *
+ * <p>
  * This program is free software: you can redistribute it and/or modify
  * 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
  * 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
  * the Free Software Foundation, either version 3 of the License, or
  * at your option) any later version.
  * at your option) any later version.
- *
+ * <p>
  * This program is distributed in the hope that it will be useful,
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Affero General Public License for more details.
  * GNU Affero General Public License for more details.
- *
+ * <p>
  * You should have received a copy of the GNU Affero General Public License
  * 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/>.
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
  */
 package com.owncloud.android.services;
 package com.owncloud.android.services;
 
 
-import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.app.job.JobScheduler;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Context;
 import android.media.ExifInterface;
 import android.media.ExifInterface;
 import android.os.Handler;
 import android.os.Handler;
-import android.os.PersistableBundle;
 import android.text.TextUtils;
 import android.text.TextUtils;
 
 
+import com.evernote.android.job.JobRequest;
+import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.SyncedFolder;
 import com.owncloud.android.datamodel.SyncedFolder;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -119,45 +118,33 @@ public class FileAlterationMagicListener implements FileAlterationListener {
 
 
             final Long finalLastModificationTime = lastModificationTime;
             final Long finalLastModificationTime = lastModificationTime;
 
 
-                final Runnable runnable = new Runnable() {
-                @Override
-                public void run() {
-                    PersistableBundle bundle = new PersistableBundle();
-                    bundle.putString(SyncedFolderJobService.LOCAL_PATH, file.getAbsolutePath());
-                    bundle.putString(SyncedFolderJobService.REMOTE_PATH, FileStorageUtils.getInstantUploadFilePath(
-                            currentLocale,
-                            syncedFolder.getRemotePath(), file.getName(),
-                            finalLastModificationTime,
-                            syncedFolder.getSubfolderByDate()));
-                    bundle.putString(SyncedFolderJobService.ACCOUNT, syncedFolder.getAccount());
-                    bundle.putInt(SyncedFolderJobService.UPLOAD_BEHAVIOUR, syncedFolder.getUploadAction());
-
-                    JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
-
-                    Long date = new Date().getTime();
-                    JobInfo job = new JobInfo.Builder(
-                            date.intValue(),
-                            new ComponentName(context, SyncedFolderJobService.class))
-                            .setRequiresCharging(syncedFolder.getChargingOnly())
-                            .setMinimumLatency(10000)
-                            .setRequiredNetworkType(syncedFolder.getWifiOnly() ? JobInfo.NETWORK_TYPE_UNMETERED :
-                                    JobInfo.NETWORK_TYPE_ANY)
-                            .setExtras(bundle)
-                            .setPersisted(true)
-                            .build();
-
-                    Integer result = js.schedule(job);
-                    if (result <= 0) {
-                        Log_OC.d(TAG, "Job failed to start: " + result);
-                    }
-
-                    //fileRunnable.remove(file.getAbsolutePath());
-                    filesList.remove(file.getAbsolutePath());
-                }
-            };
+            PersistableBundleCompat bundle = new PersistableBundleCompat();
+            bundle.putString(AutoUploadJob.LOCAL_PATH, file.getAbsolutePath());
+            bundle.putString(AutoUploadJob.REMOTE_PATH, FileStorageUtils.getInstantUploadFilePath(
+                    currentLocale,
+                    syncedFolder.getRemotePath(), file.getName(),
+                    finalLastModificationTime,
+                    syncedFolder.getSubfolderByDate()));
+            bundle.putString(AutoUploadJob.ACCOUNT, syncedFolder.getAccount());
+            bundle.putInt(AutoUploadJob.UPLOAD_BEHAVIOUR, syncedFolder.getUploadAction());
+
+            JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+
+            int jobId = new JobRequest.Builder(AutoUploadJob.TAG)
+                    .setExecutionWindow(30_000L, 40_000L)
+                    .setRequiresCharging(syncedFolder.getChargingOnly())
+                    .setRequiredNetworkType(syncedFolder.getWifiOnly() ? JobRequest.NetworkType.UNMETERED :
+                            JobRequest.NetworkType.ANY)
+                    .setExtras(bundle)
+                    .setPersisted(true)
+                    .build()
+                    .schedule();
+
+            //fileRunnable.remove(file.getAbsolutePath());
+            filesList.remove(file.getAbsolutePath());
 
 
             //fileRunnable.put(file.getAbsolutePath(), runnable);
             //fileRunnable.put(file.getAbsolutePath(), runnable);
-            handler.postDelayed(runnable, 1500);
+            //handler.post(runnable);
         }
         }
 
 
     }
     }

+ 20 - 0
src/com/owncloud/android/services/NCJobCreator.java

@@ -0,0 +1,20 @@
+package com.owncloud.android.services;
+
+import com.evernote.android.job.Job;
+import com.evernote.android.job.JobCreator;
+
+/**
+ * Created by mdjanic on 21/02/2017.
+ */
+
+public class NCJobCreator implements JobCreator {
+    @Override
+    public Job create(String tag) {
+        switch (tag) {
+            case AutoUploadJob.TAG:
+                return new AutoUploadJob();
+            default:
+                return null;
+        }
+    }
+}

+ 0 - 1
src/com/owncloud/android/services/observer/FileAlterationMagicObserver.java

@@ -181,7 +181,6 @@ public class FileAlterationMagicObserver extends FileAlterationObserver implemen
             while (fileAlterationListener.getActiveTasksCount() > 0) {
             while (fileAlterationListener.getActiveTasksCount() > 0) {
                 SystemClock.sleep(250);
                 SystemClock.sleep(250);
             }
             }
-
         }
         }
     }
     }
 
 

+ 1 - 0
src/com/owncloud/android/services/observer/SyncedFolderObserverService.java

@@ -91,6 +91,7 @@ public class SyncedFolderObserverService extends Service {
             FileAlterationMagicObserver fileAlterationMagicObserver = (FileAlterationMagicObserver)
             FileAlterationMagicObserver fileAlterationMagicObserver = (FileAlterationMagicObserver)
                     fileAlterationObserver;
                     fileAlterationObserver;
             try {
             try {
+                fileAlterationMagicObserver.checkAndNotify();
                 fileAlterationMagicObserver.destroy();
                 fileAlterationMagicObserver.destroy();
             } catch (Exception e) {
             } catch (Exception e) {
                 Log_OC.d(TAG, "Something went very wrong on trying to destroy observers");
                 Log_OC.d(TAG, "Something went very wrong on trying to destroy observers");