Enable auto upload for all

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2017-05-04 23:43:49 +02:00 committed by AndyScherzinger
parent 2b313b92f8
commit 378c46f0ec
No known key found for this signature in database
GPG key ID: 6CADC7E3523C308B
7 changed files with 77 additions and 562 deletions

View file

@ -226,32 +226,7 @@
<activity android:name=".ui.activity.UploadListActivity" /> <activity android:name=".ui.activity.UploadListActivity" />
<activity android:name=".ui.activity.WhatsNewActivity" <activity android:name=".ui.activity.WhatsNewActivity"
android:theme="@style/Theme.ownCloud.noActionBar.Login" /> android:theme="@style/Theme.ownCloud.noActionBar.Login" />
<receiver android:name=".files.services.ConnectivityActionReceiver"
android:enabled="true" android:label="ConnectivityActionReceiver">
<intent-filter>
<!--action android:name="android.net.conn.CONNECTIVITY_CHANGE"/-->
<action android:name="android.net.wifi.STATE_CHANGE"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>
<receiver android:name=".files.InstantUploadBroadcastReceiver">
<intent-filter>
<!-- unofficially supported by many Android phones but not by HTC devices: -->
<action android:name="com.android.camera.NEW_PICTURE" />
<!-- officially supported since Android 4.0 (SDK 14, works even for HTC devices): -->
<action android:name="android.hardware.action.NEW_PICTURE" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.action.NEW_VIDEO" />
<data android:mimeType="video/*" />
</intent-filter>
</receiver>
<receiver android:name=".files.BootupBroadcastReceiver" > <receiver android:name=".files.BootupBroadcastReceiver" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />

View file

@ -1,22 +1,22 @@
/** /**
* ownCloud Android client application * ownCloud Android client application
* *
* @author LukeOwncloud * @author LukeOwncloud
* @author David A. Velasco * @author David A. Velasco
* @author masensio * @author masensio
* Copyright (C) 2016 ownCloud Inc. * Copyright (C) 2016 ownCloud Inc.
* *
* 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 General Public License version 2, * it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* 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 General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU 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.datamodel; package com.owncloud.android.datamodel;
@ -26,8 +26,6 @@ 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.support.annotation.RequiresApi;
import com.evernote.android.job.JobManager; import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest; import com.evernote.android.job.JobRequest;
@ -163,9 +161,9 @@ public class UploadsStorageManager extends Observable {
cv.put(ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP, ocUpload.getUploadEndTimestamp()); cv.put(ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP, ocUpload.getUploadEndTimestamp());
int result = getDB().update(ProviderTableMeta.CONTENT_URI_UPLOADS, int result = getDB().update(ProviderTableMeta.CONTENT_URI_UPLOADS,
cv, cv,
ProviderTableMeta._ID + "=?", ProviderTableMeta._ID + "=?",
new String[]{String.valueOf(ocUpload.getUploadId())} new String[]{String.valueOf(ocUpload.getUploadId())}
); );
Log_OC.d(TAG, "updateUpload returns with: " + result + " for file: " + ocUpload.getLocalPath()); Log_OC.d(TAG, "updateUpload returns with: " + result + " for file: " + ocUpload.getLocalPath());
@ -188,15 +186,15 @@ public class UploadsStorageManager extends Observable {
String path = c.getString(c.getColumnIndex(ProviderTableMeta.UPLOADS_LOCAL_PATH)); String path = c.getString(c.getColumnIndex(ProviderTableMeta.UPLOADS_LOCAL_PATH));
Log_OC.v( Log_OC.v(
TAG, TAG,
"Updating " + path + " with status:" + status + " and result:" "Updating " + path + " with status:" + status + " and result:"
+ (result == null ? "null" : result.toString()) + " (old:" + (result == null ? "null" : result.toString()) + " (old:"
+ upload.toFormattedString() + ")"); + upload.toFormattedString() + ")");
upload.setUploadStatus(status); upload.setUploadStatus(status);
upload.setLastResult(result); upload.setLastResult(result);
upload.setRemotePath(remotePath); upload.setRemotePath(remotePath);
if(localPath != null) { if (localPath != null) {
upload.setLocalPath(localPath); upload.setLocalPath(localPath);
} }
if (status == UploadStatus.UPLOAD_SUCCEEDED) { if (status == UploadStatus.UPLOAD_SUCCEEDED) {
@ -236,7 +234,7 @@ public class UploadsStorageManager extends Observable {
if (c.getCount() != 1) { if (c.getCount() != 1) {
Log_OC.e(TAG, c.getCount() + " items for id=" + id Log_OC.e(TAG, c.getCount() + " items for id=" + id
+ " available in UploadDb. Expected 1. Failed to update upload db."); + " available in UploadDb. Expected 1. Failed to update upload db.");
} else { } else {
returnValue = updateUploadInternal(c, status, result, remotePath, localPath); returnValue = updateUploadInternal(c, status, result, remotePath, localPath);
} }
@ -266,7 +264,7 @@ public class UploadsStorageManager extends Observable {
public int removeUpload(OCUpload upload) { public int removeUpload(OCUpload upload) {
int result = getDB().delete( int result = getDB().delete(
ProviderTableMeta.CONTENT_URI_UPLOADS, ProviderTableMeta.CONTENT_URI_UPLOADS,
ProviderTableMeta._ID + "=?" , ProviderTableMeta._ID + "=?",
new String[]{Long.toString(upload.getUploadId())} new String[]{Long.toString(upload.getUploadId())}
); );
Log_OC.d(TAG, "delete returns " + result + " for upload " + upload); Log_OC.d(TAG, "delete returns " + result + " for upload " + upload);
@ -287,7 +285,7 @@ public class UploadsStorageManager extends Observable {
public int removeUpload(String accountName, String remotePath) { public int removeUpload(String accountName, String remotePath) {
int result = getDB().delete( int result = getDB().delete(
ProviderTableMeta.CONTENT_URI_UPLOADS, ProviderTableMeta.CONTENT_URI_UPLOADS,
ProviderTableMeta.UPLOADS_ACCOUNT_NAME + "=? AND " + ProviderTableMeta.UPLOADS_REMOTE_PATH + "=?" , ProviderTableMeta.UPLOADS_ACCOUNT_NAME + "=? AND " + ProviderTableMeta.UPLOADS_REMOTE_PATH + "=?",
new String[]{accountName, remotePath} new String[]{accountName, remotePath}
); );
Log_OC.d(TAG, "delete returns " + result + " for file " + remotePath + " in " + accountName); Log_OC.d(TAG, "delete returns " + result + " for file " + remotePath + " in " + accountName);
@ -379,6 +377,7 @@ public class UploadsStorageManager extends Observable {
*/ */
public OCUpload[] getCurrentAndPendingUploads() { public OCUpload[] getCurrentAndPendingUploads() {
OCUpload[] uploads = getUploads( OCUpload[] uploads = getUploads(
ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value + " OR " + ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value + " OR " +
ProviderTableMeta.UPLOADS_LAST_RESULT + "==" + UploadResult.DELAYED_FOR_WIFI.getValue() + " OR " + ProviderTableMeta.UPLOADS_LAST_RESULT + "==" + UploadResult.DELAYED_FOR_WIFI.getValue() + " OR " +
@ -386,17 +385,13 @@ public class UploadsStorageManager extends Observable {
null null
); );
// add pending Jobs //return uploads;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return uploads; List<OCUpload> result = getPendingJobs();
} else { Collections.addAll(result, uploads);
List<OCUpload> result = getPendingJobs(); return result.toArray(uploads);
Collections.addAll(result, uploads);
return result.toArray(uploads);
}
} }
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private List<OCUpload> getPendingJobs() { private List<OCUpload> getPendingJobs() {
Set<JobRequest> jobRequests = JobManager.create(mContext).getAllJobRequestsForTag(AutoUploadJob.TAG); Set<JobRequest> jobRequests = JobManager.create(mContext).getAllJobRequestsForTag(AutoUploadJob.TAG);
@ -404,11 +399,11 @@ public class UploadsStorageManager extends Observable {
for (JobRequest ji : jobRequests) { for (JobRequest ji : jobRequests) {
PersistableBundleCompat extras = ji.getExtras(); PersistableBundleCompat extras = ji.getExtras();
OCUpload upload = new OCUpload(extras.getString("filePath", ""), OCUpload upload = new OCUpload(extras.getString("filePath", ""),
extras.getString("remotePath", ""), extras.getString("remotePath", ""),
extras.getString("account", "")); extras.getString("account", ""));
list.add(upload); list.add(upload);
} }
return list; return list;
@ -416,15 +411,14 @@ public class UploadsStorageManager extends Observable {
public void cancelPendingAutoUploadJobsForAccount(Account account) { public void cancelPendingAutoUploadJobsForAccount(Account account) {
JobManager jobManager = JobManager.create(mContext); JobManager jobManager = JobManager.create(mContext);
for (JobRequest ji: jobManager.getAllJobRequestsForTag(AutoUploadJob.TAG)) { for (JobRequest ji : jobManager.getAllJobRequestsForTag(AutoUploadJob.TAG)) {
if (ji.getExtras().getString(AutoUploadJob.ACCOUNT, "").equalsIgnoreCase(account.name)) { if (ji.getExtras().getString(AutoUploadJob.ACCOUNT, "").equalsIgnoreCase(account.name)) {
jobManager.cancel(ji.getJobId()); jobManager.cancel(ji.getJobId());
} }
} }
} }
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) public void cancelPendingJob(String accountName, String remotePath) {
public void cancelPendingJob(String accountName, String remotePath){
JobManager jobManager = JobManager.create(mContext); JobManager jobManager = JobManager.create(mContext);
Set<JobRequest> jobRequests = jobManager.getAllJobRequests(); Set<JobRequest> jobRequests = jobManager.getAllJobRequests();
@ -457,14 +451,14 @@ public class UploadsStorageManager extends Observable {
/** /**
* Get all failed uploads, except for those that were not performed due to lack of Wifi connection * Get all failed uploads, except for those that were not performed due to lack of Wifi connection
* @return Array of failed uploads, except for those that were not performed due to lack of Wifi connection. * @return Array of failed uploads, except for those that were not performed due to lack of Wifi connection.
*/ */
public OCUpload[] getFailedButNotDelayedUploads() { public OCUpload[] getFailedButNotDelayedUploads() {
return getUploads(ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value + AND + return getUploads(ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value + AND +
ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue() + AND + ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue() + AND +
ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_CHARGING.getValue(), ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_CHARGING.getValue(),
null null
); );
} }
@ -474,11 +468,11 @@ public class UploadsStorageManager extends Observable {
public long clearFailedButNotDelayedUploads() { public long clearFailedButNotDelayedUploads() {
long result = getDB().delete( long result = getDB().delete(
ProviderTableMeta.CONTENT_URI_UPLOADS, ProviderTableMeta.CONTENT_URI_UPLOADS,
ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value + AND + ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value + AND +
ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue() + AND + ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue() + AND +
ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_CHARGING.getValue(), ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_CHARGING.getValue(),
null null
); );
Log_OC.d(TAG, "delete all failed uploads but those delayed for Wifi"); Log_OC.d(TAG, "delete all failed uploads but those delayed for Wifi");
if (result > 0) { if (result > 0) {
@ -491,7 +485,7 @@ public class UploadsStorageManager extends Observable {
long result = getDB().delete( long result = getDB().delete(
ProviderTableMeta.CONTENT_URI_UPLOADS, ProviderTableMeta.CONTENT_URI_UPLOADS,
ProviderTableMeta.UPLOADS_STATUS + "=="+ UploadStatus.UPLOAD_SUCCEEDED.value, null ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_SUCCEEDED.value, null
); );
Log_OC.d(TAG, "delete all successful uploads"); Log_OC.d(TAG, "delete all successful uploads");
if (result > 0) { if (result > 0) {
@ -508,8 +502,8 @@ public class UploadsStorageManager extends Observable {
long result = getDB().delete( long result = getDB().delete(
ProviderTableMeta.CONTENT_URI_UPLOADS, ProviderTableMeta.CONTENT_URI_UPLOADS,
ProviderTableMeta.UPLOADS_STATUS + "=? OR " + ProviderTableMeta.UPLOADS_STATUS + "=? AND " + ProviderTableMeta.UPLOADS_STATUS + "=? OR " + ProviderTableMeta.UPLOADS_STATUS + "=? AND " +
ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue() + AND + ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue() + AND +
ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_CHARGING.getValue(), ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_CHARGING.getValue(),
whereArgs whereArgs
); );
Log_OC.d(TAG, "delete all finished uploads"); Log_OC.d(TAG, "delete all finished uploads");
@ -528,28 +522,28 @@ public class UploadsStorageManager extends Observable {
if (uploadResult.isCancelled()) { if (uploadResult.isCancelled()) {
removeUpload( removeUpload(
upload.getAccount().name, upload.getAccount().name,
upload.getRemotePath() upload.getRemotePath()
); );
} else { } else {
String localPath = (FileUploader.LOCAL_BEHAVIOUR_MOVE == upload.getLocalBehaviour()) String localPath = (FileUploader.LOCAL_BEHAVIOUR_MOVE == upload.getLocalBehaviour())
? upload.getStoragePath() : null; ? upload.getStoragePath() : null;
if (uploadResult.isSuccess()) { if (uploadResult.isSuccess()) {
updateUploadStatus( updateUploadStatus(
upload.getOCUploadId(), upload.getOCUploadId(),
UploadStatus.UPLOAD_SUCCEEDED, UploadStatus.UPLOAD_SUCCEEDED,
UploadResult.UPLOADED, UploadResult.UPLOADED,
upload.getRemotePath(), upload.getRemotePath(),
localPath localPath
); );
} else { } else {
updateUploadStatus( updateUploadStatus(
upload.getOCUploadId(), upload.getOCUploadId(),
UploadStatus.UPLOAD_FAILED, UploadStatus.UPLOAD_FAILED,
UploadResult.fromOperationResult(uploadResult), UploadResult.fromOperationResult(uploadResult),
upload.getRemotePath(), upload.getRemotePath(),
localPath localPath
); );
} }
} }
@ -560,14 +554,14 @@ public class UploadsStorageManager extends Observable {
*/ */
public void updateDatabaseUploadStart(UploadFileOperation upload) { public void updateDatabaseUploadStart(UploadFileOperation upload) {
String localPath = (FileUploader.LOCAL_BEHAVIOUR_MOVE == upload.getLocalBehaviour()) String localPath = (FileUploader.LOCAL_BEHAVIOUR_MOVE == upload.getLocalBehaviour())
? upload.getStoragePath() : null; ? upload.getStoragePath() : null;
updateUploadStatus( updateUploadStatus(
upload.getOCUploadId(), upload.getOCUploadId(),
UploadStatus.UPLOAD_IN_PROGRESS, UploadStatus.UPLOAD_IN_PROGRESS,
UploadResult.UNKNOWN, UploadResult.UNKNOWN,
upload.getRemotePath(), upload.getRemotePath(),
localPath localPath
); );
} }
@ -576,7 +570,7 @@ public class UploadsStorageManager extends Observable {
* Changes the status of any in progress upload from UploadStatus.UPLOAD_IN_PROGRESS * Changes the status of any in progress upload from UploadStatus.UPLOAD_IN_PROGRESS
* to UploadStatus.UPLOAD_FAILED * to UploadStatus.UPLOAD_FAILED
* *
* @return Number of uploads which status was changed. * @return Number of uploads which status was changed.
*/ */
public int failInProgressUploads(UploadResult fail) { public int failInProgressUploads(UploadResult fail) {
Log_OC.v(TAG, "Updating state of any killed upload"); Log_OC.v(TAG, "Updating state of any killed upload");
@ -584,16 +578,16 @@ public class UploadsStorageManager extends Observable {
ContentValues cv = new ContentValues(); ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.UPLOADS_STATUS, UploadStatus.UPLOAD_FAILED.getValue()); cv.put(ProviderTableMeta.UPLOADS_STATUS, UploadStatus.UPLOAD_FAILED.getValue());
cv.put( cv.put(
ProviderTableMeta.UPLOADS_LAST_RESULT, ProviderTableMeta.UPLOADS_LAST_RESULT,
fail != null ? fail.getValue() : UploadResult.UNKNOWN.getValue() fail != null ? fail.getValue() : UploadResult.UNKNOWN.getValue()
); );
cv.put(ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP, Calendar.getInstance().getTimeInMillis()); cv.put(ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP, Calendar.getInstance().getTimeInMillis());
int result = getDB().update( int result = getDB().update(
ProviderTableMeta.CONTENT_URI_UPLOADS, ProviderTableMeta.CONTENT_URI_UPLOADS,
cv, cv,
ProviderTableMeta.UPLOADS_STATUS + "=?", ProviderTableMeta.UPLOADS_STATUS + "=?",
new String[]{String.valueOf(UploadStatus.UPLOAD_IN_PROGRESS.getValue())} new String[]{String.valueOf(UploadStatus.UPLOAD_IN_PROGRESS.getValue())}
); );
if (result == 0) { if (result == 0) {

View file

@ -1,223 +0,0 @@
/**
* ownCloud Android client application
*
* @author Bartek Przybylski
* @author David A. Velasco
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2016 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.files;
import android.Manifest;
import android.accounts.Account;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Build;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Video;
import android.support.v4.content.ContextCompat;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.db.PreferenceManager;
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.utils.FileStorageUtils;
public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = InstantUploadBroadcastReceiver.class.getName();
// Image action
// Unofficial action, works for most devices but not HTC. See: https://github.com/owncloud/android/issues/6
private static final String NEW_PHOTO_ACTION_UNOFFICIAL = "com.android.camera.NEW_PICTURE";
// Officially supported action since SDK 14:
// http://developer.android.com/reference/android/hardware/Camera.html#ACTION_NEW_PICTURE
private static final String NEW_PHOTO_ACTION = "android.hardware.action.NEW_PICTURE";
// Video action
// Officially supported action since SDK 14:
// http://developer.android.com/reference/android/hardware/Camera.html#ACTION_NEW_VIDEO
private static final String NEW_VIDEO_ACTION = "android.hardware.action.NEW_VIDEO";
/**
* Because we support NEW_PHOTO_ACTION and NEW_PHOTO_ACTION_UNOFFICIAL it can happen that
* handleNewPictureAction is called twice for the same photo. Use this simple static variable to
* remember last uploaded photo to filter duplicates. Must not be null!
*/
static String lastUploadedPhotoPath = "";
@Override
public void onReceive(Context context, Intent intent) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log_OC.d(TAG, "Received: " + intent.getAction());
if (intent.getAction().equals(NEW_PHOTO_ACTION_UNOFFICIAL)) {
handleNewPictureAction(context, intent);
Log_OC.d(TAG, "UNOFFICIAL processed: com.android.camera.NEW_PICTURE");
} else if (intent.getAction().equals(NEW_PHOTO_ACTION)) {
handleNewPictureAction(context, intent);
Log_OC.d(TAG, "OFFICIAL processed: android.hardware.action.NEW_PICTURE");
} else if (intent.getAction().equals(NEW_VIDEO_ACTION)) {
handleNewVideoAction(context, intent);
Log_OC.d(TAG, "OFFICIAL processed: android.hardware.action.NEW_VIDEO");
} else {
Log_OC.e(TAG, "Incorrect intent received: " + intent.getAction());
}
}
}
private void handleNewPictureAction(Context context, Intent intent) {
Cursor c = null;
String file_path = null;
String file_name = null;
String mime_type = null;
long date_taken = 0;
Log_OC.i(TAG, "New photo received");
if (!PreferenceManager.instantPictureUploadEnabled(context)) {
Log_OC.d(TAG, "Instant picture upload disabled, ignoring new picture");
return;
}
Account account = AccountUtils.getCurrentOwnCloudAccount(context);
if (account == null) {
Log_OC.w(TAG, "No account found for instant upload, aborting");
return;
}
String[] CONTENT_PROJECTION = {
Images.Media.DATA, Images.Media.DISPLAY_NAME, Images.Media.MIME_TYPE, Images.Media.SIZE};
// if < Jelly Bean permission must be accepted during installation
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE);
if (android.content.pm.PackageManager.PERMISSION_GRANTED != permissionCheck) {
Log_OC.w(TAG, "Read external storage permission isn't granted, aborting");
return;
}
}
c = context.getContentResolver().query(intent.getData(), CONTENT_PROJECTION, null, null, null);
if (!c.moveToFirst()) {
Log_OC.e(TAG, "Couldn't resolve given uri: " + intent.getDataString());
return;
}
file_path = c.getString(c.getColumnIndex(Images.Media.DATA));
file_name = c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME));
mime_type = c.getString(c.getColumnIndex(Images.Media.MIME_TYPE));
date_taken = System.currentTimeMillis();
c.close();
if (file_path.equals(lastUploadedPhotoPath)) {
Log_OC.d(TAG, "Duplicate detected: " + file_path + ". Ignore.");
return;
}
lastUploadedPhotoPath = file_path;
Log_OC.d(TAG, "Path: " + file_path + "");
new FileUploader.UploadRequester();
int behaviour = getUploadBehaviour(context);
Boolean subfolderByDate = PreferenceManager.instantPictureUploadPathUseSubfolders(context);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
String uploadPathdef = context.getString(R.string.instant_upload_path);
String uploadPath = pref.getString("instant_upload_path", uploadPathdef);
FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
requester.uploadNewFile(
context,
account,
file_path,
FileStorageUtils.getInstantUploadFilePath(uploadPath, file_name, date_taken, subfolderByDate),
behaviour,
mime_type,
true, // create parent folder if not existent
UploadFileOperation.CREATED_AS_INSTANT_PICTURE
);
}
private Integer getUploadBehaviour(Context context) {
SharedPreferences appPreferences = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
String behaviour = appPreferences.getString("prefs_instant_behaviour", "NOTHING");
if (behaviour.equalsIgnoreCase("NOTHING")) {
Log_OC.d(TAG, "upload file and do nothing");
return FileUploader.LOCAL_BEHAVIOUR_FORGET;
} else if (behaviour.equalsIgnoreCase("MOVE")) {
Log_OC.d(TAG, "upload file and move file to oc folder");
return FileUploader.LOCAL_BEHAVIOUR_MOVE;
} else if (behaviour.equalsIgnoreCase("DELETE")) {
Log_OC.d(TAG, "upload file and delete original file");
return FileUploader.LOCAL_BEHAVIOUR_DELETE;
}
return FileUploader.LOCAL_BEHAVIOUR_FORGET;
}
private void handleNewVideoAction(Context context, Intent intent) {
Cursor c = null;
String file_path = null;
String file_name = null;
String mime_type = null;
long date_taken = 0;
Log_OC.i(TAG, "New video received");
if (!PreferenceManager.instantVideoUploadEnabled(context)) {
Log_OC.d(TAG, "Instant video upload disabled, ignoring new video");
return;
}
Account account = AccountUtils.getCurrentOwnCloudAccount(context);
if (account == null) {
Log_OC.w(TAG, "No account found for instant upload, aborting");
return;
}
String[] CONTENT_PROJECTION = {Video.Media.DATA, Video.Media.DISPLAY_NAME, Video.Media.MIME_TYPE,
Video.Media.SIZE};
c = context.getContentResolver().query(intent.getData(), CONTENT_PROJECTION, null, null, null);
if (!c.moveToFirst()) {
Log_OC.e(TAG, "Couldn't resolve given uri: " + intent.getDataString());
return;
}
file_path = c.getString(c.getColumnIndex(Video.Media.DATA));
file_name = c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME));
mime_type = c.getString(c.getColumnIndex(Video.Media.MIME_TYPE));
c.close();
date_taken = System.currentTimeMillis();
Log_OC.d(TAG, file_path + "");
int behaviour = getUploadBehaviour(context);
FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
requester.uploadNewFile(
context,
account,
file_path,
FileStorageUtils.getInstantVideoUploadFilePath(context, file_name, date_taken),
behaviour,
mime_type,
true, // create parent folder if not existent
UploadFileOperation.CREATED_AS_INSTANT_VIDEO
);
}
}

View file

@ -1,223 +0,0 @@
/**
* ownCloud Android client application
*
* @author LukeOwncloud
* Copyright (C) 2016 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.files.services;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.db.UploadResult;
import com.owncloud.android.lib.common.utils.Log_OC;
/**
* Receives all connectivity action from Android OS at all times and performs
* required OC actions. For now that are: - Signal connectivity to
* {@link FileUploader}.
*
* Later can be added: - Signal connectivity to download service, deletion
* service, ... - Handle offline mode (cf.
* https://github.com/owncloud/android/issues/162)
*
* Have fun with the comments :S
*/
public class ConnectivityActionReceiver extends BroadcastReceiver {
private static final String TAG = ConnectivityActionReceiver.class.getSimpleName();
/**
* Magic keyword, by Google.
*
* {@see http://developer.android.com/intl/es/reference/android/net/wifi/WifiInfo.html#getSSID()}
*/
private static final String UNKNOWN_SSID = "<unknown ssid>";
@Override
public void onReceive(final Context context, Intent intent) {
// LOG ALL EVENTS:
Log_OC.v(TAG, "action: " + intent.getAction());
Log_OC.v(TAG, "component: " + intent.getComponent());
Bundle extras = intent.getExtras();
if (extras != null) {
for (String key : extras.keySet()) {
Log_OC.v(TAG, "key [" + key + "]: " + extras.get(key));
}
} else {
Log_OC.v(TAG, "no extras");
}
if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED) &&
(PreferenceManager.instantPictureUploadEnabled(context) &&
PreferenceManager.instantPictureUploadWhenChargingOnly(context)) ||
(PreferenceManager.instantVideoUploadEnabled(context) &&
PreferenceManager.instantVideoUploadWhenChargingOnly(context))
) {
// for the moment, only recovery of instant uploads, similar to behaviour in release 1.9.1
Log_OC.d(TAG, "Requesting retry of instant uploads (& friends) due to charging");
FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
requester.retryFailedUploads(
context,
null,
UploadResult.DELAYED_FOR_CHARGING // for the rest of enqueued when Wifi fell
);
}
/**
* There is an interesting mess to process WifiManager.NETWORK_STATE_CHANGED_ACTION and
* ConnectivityManager.CONNECTIVITY_ACTION in a simple and reliable way.
*
* The former triggers much more events than what we really need to know about Wifi connection.
*
* But there are annoying uncertainties about ConnectivityManager.CONNECTIVITY_ACTION due
* to the deprecation of ConnectivityManager.EXTRA_NETWORK_INFO in API level 14, and the absence
* of ConnectivityManager.EXTRA_NETWORK_TYPE until API level 17. Dear Google, how should we
* handle API levels 14 to 16?
*
* In the end maybe we need to keep in memory the current knowledge about connectivity
* and update it taking into account several Intents received in a row
*
* But first let's try something "simple" to keep a basic retry of instant uploads in
* version 1.9.2, similar to the existent until 1.9.1. To be improved.
*/
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo networkInfo =
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
WifiInfo wifiInfo =
intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
String bssid =
intent.getStringExtra(WifiManager.EXTRA_BSSID);
if(networkInfo.isConnected() && // not enough; see (*) right below
wifiInfo != null &&
!UNKNOWN_SSID.equals(wifiInfo.getSSID().toLowerCase()) &&
bssid != null
) {
Log_OC.d(TAG, "WiFi connected");
wifiConnected(context);
} else {
// TODO tons of things to check to conclude disconnection;
// TODO maybe alternative commented below, based on CONNECTIVITY_ACTION is better
Log_OC.d(TAG, "WiFi disconnected ... but don't know if right now");
}
}
// (*) When WiFi is lost, an Intent with network state CONNECTED and SSID "<unknown ssid>" is
// received right before another Intent with network state DISCONNECTED; needs to
// be differentiated of a new Wifi connection.
//
// Besides, with a new connection two Intents are received, having only the second the extra
// WifiManager.EXTRA_BSSID, with the BSSID of the access point accessed.
//
// Not sure if this protocol is exact, since it's not documented. Only found mild references in
// - http://developer.android.com/intl/es/reference/android/net/wifi/WifiInfo.html#getSSID()
// - http://developer.android.com/intl/es/reference/android/net/wifi/WifiManager.html#EXTRA_BSSID
// and reproduced in Nexus 5 with Android 6.
/**
* Possible alternative attending ConnectivityManager.CONNECTIVITY_ACTION.
*
* Let's see what QA has to say
*
if(intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
NetworkInfo networkInfo = intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO // deprecated in API 14
);
int networkType = intent.getIntExtra(
ConnectivityManager.EXTRA_NETWORK_TYPE, // only from API level 17
-1
);
boolean couldBeWifiAction =
(networkInfo == null && networkType < 0) || // cases of lack of info
networkInfo.getType() == ConnectivityManager.TYPE_WIFI ||
networkType == ConnectivityManager.TYPE_WIFI;
if (couldBeWifiAction) {
if (ConnectivityUtils.isAppConnectedViaUnmeteredWiFi(context)) {
Log_OC.d(TAG, "WiFi connected");
wifiConnected(context);
} else {
Log_OC.d(TAG, "WiFi disconnected");
wifiDisconnected(context);
}
} /* else, CONNECTIVIY_ACTION is (probably) about other network interface (mobile, bluetooth, ...)
}
*/
}
private void wifiConnected(Context context) {
// for the moment, only recovery of instant uploads, similar to behaviour in release 1.9.1
if (
(PreferenceManager.instantPictureUploadEnabled(context) &&
PreferenceManager.instantPictureUploadViaWiFiOnly(context)) ||
(PreferenceManager.instantVideoUploadEnabled(context) &&
PreferenceManager.instantVideoUploadViaWiFiOnly(context))
) {
Log_OC.d(TAG, "Requesting retry of instant uploads (& friends)");
FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
requester.retryFailedUploads(
context,
null,
UploadResult.NETWORK_CONNECTION // for the interrupted when Wifi fell, if any
// (side effect: any upload failed due to network error will be retried too, instant or not)
);
requester.retryFailedUploads(
context,
null,
UploadResult.DELAYED_FOR_WIFI // for the rest of enqueued when Wifi fell
);
}
}
/**
*
private void wifiDisconnected() {
// TODO something smart
// NOTE: explicit cancellation of only-wifi instant uploads is not needed anymore, since currently:
// - any upload in progress will be interrupted due to the lack of connectivity while the device
// reconnects through other network interface;
// - FileUploader checks instant upload settings and connection state before executing each
// upload operation, so other pending instant uploads after the current one will not be run
// (currently are silently moved to FAILED state)
}
static public void enableActionReceiver(Context context) {
PackageManager pm = context.getPackageManager();
ComponentName compName = new ComponentName(context.getApplicationContext(), ConnectivityActionReceiver.class);
pm.setComponentEnabledSetting(compName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
static public void disableActionReceiver(Context context) {
PackageManager pm = context.getPackageManager();
ComponentName compName = new ComponentName(context.getApplicationContext(), ConnectivityActionReceiver.class);
pm.setComponentEnabledSetting(compName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
*/
}

View file

@ -34,7 +34,6 @@ import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Binder; import android.os.Binder;
import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
@ -691,7 +690,7 @@ public class FileUploader extends Service
// need to update now table in mUploadsStorageManager, // need to update now table in mUploadsStorageManager,
// since the operation will not get to be run by FileUploader#uploadFile // since the operation will not get to be run by FileUploader#uploadFile
mUploadsStorageManager.removeUpload(accountName, remotePath); mUploadsStorageManager.removeUpload(accountName, remotePath);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { } else {
// try to cancel job in jobScheduler // try to cancel job in jobScheduler
mUploadsStorageManager.cancelPendingJob(accountName, remotePath); mUploadsStorageManager.cancelPendingJob(accountName, remotePath);
} }

View file

@ -211,12 +211,6 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
setupDrawerMenu(mNavigationView); setupDrawerMenu(mNavigationView);
setupQuotaElement(); setupQuotaElement();
// show folder sync menu item only for Android 6+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M &&
mNavigationView.getMenu().findItem(R.id.nav_folder_sync) != null) {
mNavigationView.getMenu().removeItem(R.id.nav_folder_sync);
}
} }
setupDrawerToggle(); setupDrawerToggle();

View file

@ -282,9 +282,8 @@ public class FileDisplayActivity extends HookActivity
*/ */
private void upgradeNotificationForInstantUpload() { private void upgradeNotificationForInstantUpload() {
// check for Android 6+ if legacy instant upload is activated --> disable + show info // check for Android 6+ if legacy instant upload is activated --> disable + show info
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && if (PreferenceManager.instantPictureUploadEnabled(this) ||
(PreferenceManager.instantPictureUploadEnabled(this) || PreferenceManager.instantPictureUploadEnabled(this)) {
PreferenceManager.instantPictureUploadEnabled(this))) {
// remove legacy shared preferences // remove legacy shared preferences
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit(); SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();