Commit f10eb511 authored by vince-bourgmayer's avatar vince-bourgmayer
Browse files

make background service for initial folder creation to perform all folders...

make background service for initial folder creation to perform all folders creation and DB registering
parent 0ff8aecc
Pipeline #34296 failed with stage
in 2 minutes and 9 seconds
package foundation.e.drive.backgroundServices;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.IntentService;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
......@@ -13,12 +14,16 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import foundation.e.drive.database.DbHelper;
import foundation.e.drive.models.SyncedFolder;
import foundation.e.drive.utils.AppConstants;
import foundation.e.drive.utils.CommonUtils;
import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR;
import static foundation.e.drive.utils.AppConstants.ACCOUNT_KEY_CODE;
import static foundation.e.drive.utils.AppConstants.resultCodeKey;
import static foundation.e.drive.utils.AppConstants.resultIntentActionKey;
......@@ -28,62 +33,171 @@ import static foundation.e.drive.utils.AppConstants.resultIntentActionKey;
//https://developer.android.com/guide/components/services.html#ExtendingIntentService
public class CreateInitialRemoteFoldersIntentService extends IntentService {
private static final String TAG = CreateInitialRemoteFoldersIntentService.class.getSimpleName();
public static final String createFullPathKey = "create_full_path";
public static final String syncedFolderKey = "synced_folder";
/**
* Creates an IntentService.
*
* default constructor
*/
public CreateInitialRemoteFoldersIntentService() {
super(TAG);
}
public CreateInitialRemoteFoldersIntentService() { super(TAG); }
@Override
protected void onHandleIntent(Intent workIntent) {
if(workIntent == null || workIntent.getExtras() == null) return;
Bundle extras = workIntent.getExtras();
boolean mCreateFullPath = extras.getBoolean(createFullPathKey);
SyncedFolder mSyncedFolder = (SyncedFolder) extras.getParcelable(syncedFolderKey);
Account mAccount = extras.getParcelable(ACCOUNT_KEY_CODE);
//@TODO: if(mAccount == null)
OwnCloudClient client = CommonUtils.getOwnCloudClient(mAccount, this);
if(mSyncedFolder == null) return; //@TODO: Move this check in performTask
performTask(mSyncedFolder, mCreateFullPath, client);
LocalBroadcastManager.getInstance(this).sendBroadcast(doMission(client));
}
private void performTask(SyncedFolder mSyncedFolder, boolean mCreateFullPath, OwnCloudClient client){
/**
* @TODO: rename it
* @return Intent the result intent to send to launcher service
*/
private Intent doMission(OwnCloudClient client){
Intent resultIntent = new Intent(resultIntentActionKey);
List<String> syncCategories = Arrays.asList("Rom settings", "Images", "Movies", "Music", "Ringtones", "Documents", "Podcasts");
Log.d(TAG, "syncCategories. size : "+syncCategories.size());
//Get SyncedFolders
List<SyncedFolder> mSyncedFolders = getInitialSyncedFolders(syncCategories);
File folder = new File(mSyncedFolder.getLocalFolder() );
Log.d(TAG, "mSyncedFolders. size : "+mSyncedFolders.size());
resultIntent.putExtra(resultCodeKey, true);
for(SyncedFolder folder : mSyncedFolders){
Log.d(TAG, "Folder: "+folder.getLibelle());
if(!createFolder(folder, client)){
//@TODO: What to do if not succeed ?
resultIntent.putExtra(resultCodeKey, false);
break; //Leave the loop. Try again later.
}
}
Log.d(TAG, "Result: "+resultIntent.getExtras().getBoolean(resultCodeKey));
return resultIntent;
}
/**
* Return a list of SyncedFolder
* @param categories categories indicating which syncedFolder to create
*/
private List<SyncedFolder> getInitialSyncedFolders( List<String> categories){
Log.i(TAG, "getInitialSyncedFolders");
List<SyncedFolder> mSyncedFolders = new ArrayList<>();
for(int i=-1, size = categories.size(); ++i < size;){
final String DEVICE_SPECIFIC_PATH = PATH_SEPARATOR+"Devices"+PATH_SEPARATOR+ Build.BRAND+"_"+ Build.MODEL+"_"
+ Build.SERIAL;
switch ( categories.get(i) ){
case "Medias":
break;
case "Images":
mSyncedFolders.add( new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_DCIM),
"/Photos/", true) );
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_PICTURES),
"/Pictures/", true ) );
break;
case "Movies":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_MOVIES),
"/Movies/", true));
break;
case "Music":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_MUSIC),
"/Music/", true));
break;
case "Ringtones":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_RINGTONES),
"/Ringtones/", true));
break;
case "Documents":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_DOCUMENTS),
"/Documents/", true));
break;
case "Podcasts":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_PODCASTS),
"/Podcasts/", true));
break;
case "Rom settings":
String remoteFolderPath = DEVICE_SPECIFIC_PATH+"/rom_settings/";
mSyncedFolders.add( new SyncedFolder(categories.get(i), "/data/system/users/0/", remoteFolderPath, true, false, true, false) );
try{
mSyncedFolders.add( new SyncedFolder(
categories.get(i),
getFilesDir().getCanonicalPath()+PATH_SEPARATOR,
remoteFolderPath+"app_list/",
true,
false,
true,
false) );
}catch (Exception e){ Log.e(TAG, e.toString()); }
break;
}
}
return mSyncedFolders;
}
private String getExternalFolder(String directory){
return CommonUtils.getLocalPath(Environment.getExternalStoragePublicDirectory(directory))+ PATH_SEPARATOR;
}
/**
* Create a single folder
* @param syncedFolder folder to create
* @param client Client to use to perform the operation
* @return true if success, false either
*/
private boolean createFolder(SyncedFolder syncedFolder, OwnCloudClient client){
int trialCounter = 0;
//Check that local Folder exist
File folder = new File(syncedFolder.getLocalFolder() );
if( !folder.exists() ){
Log.e(TAG, "Local folder doesn't exist, so create it");
folder.mkdirs();
}
CreateFolderRemoteOperation createFolderOperation = new CreateFolderRemoteOperation(mSyncedFolder.getRemoteFolder(), mCreateFullPath);
RemoteOperationResult createOperationResult;
createOperationResult = createFolderOperation.execute(client, true);
if(createOperationResult.isSuccess() || createOperationResult.getCode() == RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS ){
if(DbHelper.insertSyncedFolder(mSyncedFolder, this) >= 0 ) {
resultIntent.putExtra(resultCodeKey, RemoteOperationResult.ResultCode.OK);
resultIntent.putExtra(AppConstants.resultIntentHttpCodeKey, createOperationResult.getHttpCode());
//Create the operation to create file
CreateFolderRemoteOperation createFolderOperation = new CreateFolderRemoteOperation(syncedFolder.getRemoteFolder(), true);
while(trialCounter < 3){
//Execute the operation
RemoteOperationResult createOperationResult = createFolderOperation.execute(client, true);
//Handle the result
int result = handleResult(createOperationResult);
if( result== 0) {
if(DbHelper.insertSyncedFolder(syncedFolder, this) >= 0 ) {
return true;
}else {
Log.d(TAG, "insertion of folder in DB failed");
//@TODO: check in DB if folder is already present
//if(DbHelper.syncedFolderExist()){ return true;}
return false;
}
}else {
Log.d(TAG, "insertion of folder in DB failed");
resultIntent.putExtra(resultCodeKey, RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS);
resultIntent.putExtra(AppConstants.resultIntentHttpCodeKey, createOperationResult.getHttpCode());
trialCounter += result;
}
}else{
resultIntent.putExtra(resultCodeKey, createOperationResult.getCode());
resultIntent.putExtra(AppConstants.resultIntentHttpCodeKey, createOperationResult.getHttpCode());
}
return false;
}
Log.d(TAG, createOperationResult.getLogMessage()+" \n"+createOperationResult.getCode()+
" \n"+createOperationResult.getHttpCode()+" \n"+createOperationResult.getAuthenticateHeaders().toString());
LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent);
/**
* Handle the result
* @param result the operation result to analyze
* @return int value 0 if success, 1 if operation should be retry, 3 if failure with no retry
*/
private int handleResult(RemoteOperationResult result){
if(result.isSuccess() || result.getCode() == RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS ){
return 0;
}else if(result.getHttpCode() == 423 || result.getHttpCode() == 409){
Log.w( TAG, " retry the operation" );
return 1; //It will make operation to be retried
}else{
Log.e(TAG, result.getCode()+" "+result.getHttpCode() );
return 3; //total failure
}
}
}
......@@ -16,55 +16,35 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import foundation.e.drive.backgroundServices.CreateInitialRemoteFoldersIntentService;
import foundation.e.drive.models.SyncedFolder;
import foundation.e.drive.operations.CreateInitialFolderRemoteOperation;
import foundation.e.drive.receivers.ScreenOffReceiver;
import foundation.e.drive.utils.AppConstants;
import foundation.e.drive.utils.CommonUtils;
import foundation.e.drive.utils.JobUtils;
import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR;
import static foundation.e.drive.backgroundServices.CreateInitialRemoteFoldersIntentService.createFullPathKey;
import static foundation.e.drive.backgroundServices.CreateInitialRemoteFoldersIntentService.syncedFolderKey;
import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER;
import static foundation.e.drive.utils.AppConstants.MEDIA_SYNCABLE_CATEGORIES;
import static foundation.e.drive.utils.AppConstants.SETTINGS_SYNCABLE_CATEGORIES;
/**
* @author Vincent Bourgmayer
*/
public class InitializerService extends Service {
final private String TAG = InitializerService.class.getSimpleName();
//Complex properties
private int existingRemoteFolderCounter; //@dev-only; Temporarily used to know if all remotePath exist
private List<SyncedFolder> mSyncedFolders; //syncedFolders
private OwnCloudClient mCloudClient;
private Handler mHandler;
private Account mAccount;
private int restartFolderCreationCounter =0;
@Override
public void onCreate() {
Log.i(TAG, "onCreate()");
super.onCreate();
this.existingRemoteFolderCounter = 0;
//JobUtils.scheduleInitializerJob(getApplicationContext());
IntentFilter intentFilter = new IntentFilter(AppConstants.resultIntentActionKey);
LocalBroadcastManager.getInstance(this).registerReceiver(
......@@ -101,203 +81,52 @@ public class InitializerService extends Service {
Log.w(TAG, "Account's name not found. Neither in shared prefs nor in intent's extras");
stopSelf();
}else{
this.mAccount = CommonUtils.getAccount( accountName, accountType, AccountManager.get(this) );
Account mAccount = CommonUtils.getAccount( accountName, accountType, AccountManager.get(this) );
//Get OwnCloudlient
if (this.mAccount != null) {
this.mCloudClient = CommonUtils.getOwnCloudClient( this.mAccount, getApplicationContext());
start();
}else {
if (mAccount == null) {
Log.w(TAG, "Got account is invalid.");
stopSelf();
}
}
}
return super.onStartCommand(intent, flags, startId);
}
/**
* start to do its job
*/
public void start() {
Log.i(TAG, "start");
if (mCloudClient == null){
stopSelf();
return;
}
//Get categories of element to sync
List<String> syncCategories = new ArrayList<>();
if (CommonUtils.isMediaSyncEnabled(mAccount)) {
syncCategories.addAll(Arrays.asList(MEDIA_SYNCABLE_CATEGORIES));
}
if (CommonUtils.isSettingsSyncEnabled(mAccount)) {
syncCategories.addAll(Arrays.asList(SETTINGS_SYNCABLE_CATEGORIES));
}
//Get SyncedFolders
getInitialSyncedFolders(syncCategories);
this.existingRemoteFolderCounter = 0;
CreateNextRemoteFolder();
}
/**
* Return a list of SyncedFolder
* @param categories categories indicating which syncedFolder to create
*/
private void getInitialSyncedFolders( List<String> categories){
Log.i(TAG, "getInitialSyncedFolders");
this.mSyncedFolders = new ArrayList<>();
for(int i=-1, size = categories.size(); ++i < size;){
final String DEVICE_SPECIFIC_PATH = PATH_SEPARATOR+"Devices"+PATH_SEPARATOR+ Build.BRAND+"_"+ Build.MODEL+"_"
+ Build.SERIAL;
switch ( categories.get(i) ){
case "Medias":
break;
case "Images":
mSyncedFolders.add( new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_DCIM),
"/Photos/", true) );
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_PICTURES),
"/Pictures/", true ) );
break;
case "Movies":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_MOVIES),
"/Movies/", true));
break;
case "Music":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_MUSIC),
"/Music/", true));
break;
case "Ringtones":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_RINGTONES),
"/Ringtones/", true));
break;
case "Documents":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_DOCUMENTS),
"/Documents/", true));
break;
case "Podcasts":
mSyncedFolders.add(new SyncedFolder(categories.get(i), getExternalFolder(Environment.DIRECTORY_PODCASTS),
"/Podcasts/", true));
break;
case "Rom settings":
String remoteFolderPath = DEVICE_SPECIFIC_PATH+"/rom_settings/";
mSyncedFolders.add( new SyncedFolder(categories.get(i), "/data/system/users/0/", remoteFolderPath, true, false, true, false) );
try{
mSyncedFolders.add( new SyncedFolder(
categories.get(i),
getFilesDir().getCanonicalPath()+PATH_SEPARATOR,
remoteFolderPath+"app_list/",
true,
false,
true,
false) );
}catch (Exception e){ Log.e(TAG, e.toString()); }
break;
}
}
}
private String getExternalFolder(String directory){
return CommonUtils.getLocalPath(Environment.getExternalStoragePublicDirectory(directory))+ PATH_SEPARATOR;
}
/**
* Start to createSyncedFolder in the cloud
*/
private void CreateNextRemoteFolder(){
this.restartFolderCreationCounter = 0;
if( this.mSyncedFolders == null || this.mSyncedFolders.isEmpty() ){
//JobUtils.stopScheduledJob(getApplicationContext(), JobUtils.InitializerJobId);
this.stopSelf();
}
//It means that there are still folders to create
if( this.existingRemoteFolderCounter < this.mSyncedFolders.size() ){
Intent createFolderIntent = new Intent(this, CreateInitialRemoteFoldersIntentService.class);
createFolderIntent.putExtra(AppConstants.ACCOUNT_KEY_CODE, mAccount);
startService(createFolderIntent);
if( this.mHandler == null ) this.mHandler = new Handler();
Intent createFolderIntent = new Intent(this, CreateInitialRemoteFoldersIntentService.class);
createFolderIntent.putExtra(syncedFolderKey, mSyncedFolders.get(this.existingRemoteFolderCounter));
createFolderIntent.putExtra(createFullPathKey, true);
createFolderIntent.putExtra(AppConstants.ACCOUNT_KEY_CODE, mAccount);
startService(createFolderIntent);
}else if(this.existingRemoteFolderCounter == this.mSyncedFolders.size() ){
doLastStep();
}else{
Log.e(TAG, "this.existingRemoteFolderCounter : "+this.existingRemoteFolderCounter+" > this.mSyncedFolders.size() : "+this.mSyncedFolders.size() );
this.stopSelf();
}
}
public void onFolderCreationResult(RemoteOperationResult.ResultCode resultCode, int httpResultCode){
if(resultCode != null && (resultCode.equals(RemoteOperationResult.ResultCode.OK) || resultCode.equals(RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS))){
this.existingRemoteFolderCounter+=1;
CreateNextRemoteFolder();
}else if(httpResultCode == 423 || httpResultCode == 409){
if( this.restartFolderCreationCounter < 3) {
Log.w( TAG, " restart operation" );
//operation.execute( this.mCloudClient, this, this.mHandler );
this.restartFolderCreationCounter+=1;
}else{
Log.e(TAG, "Remote folder's creation failed due to conflict with server");
stopSelf();
}
}else{
Log.e(TAG, resultCode+" "+httpResultCode );
stopSelf();
}
return super.onStartCommand(intent, flags, startId);
}
/**
* Function to check if all remote folder have been created
**/
private void doLastStep(){
Log.i(TAG, "doLastStep()");
private void doLastStep(boolean initDone, int initializedFoldersNumber){
Log.i(TAG, "doLastStep("+initDone+", "+initializedFoldersNumber+")");
getApplicationContext().getSharedPreferences( AppConstants.SHARED_PREFERENCE_NAME,
Context.MODE_PRIVATE )
.edit()
.putBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, true)
.putInt( INITIALFOLDERS_NUMBER, mSyncedFolders.size() )
.putBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, initDone)
.putInt( INITIALFOLDERS_NUMBER, initializedFoldersNumber )
.apply();
//all folder have been created
JobUtils.scheduleScannerJob(this);
if(initDone) {
//all folder have been created
JobUtils.scheduleScannerJob(this);
Log.d(TAG, "RegisterReceiver: screenOffReceiver");
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
getApplicationContext().registerReceiver(ScreenOffReceiver.getInstance(), filter);
Log.d(TAG, "RegisterReceiver: screenOffReceiver");
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
getApplicationContext().registerReceiver(ScreenOffReceiver.getInstance(), filter);
//Immediatly start ObserverService to not have to wait 30 minutes.
Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class);
startService(observersServiceIntent);
//Immediatly start ObserverService to not have to wait 30 minutes.
Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class);
startService(observersServiceIntent);
}
//JobUtils.stopScheduledJob(appContext, JobUtils.InitializerJobId);
stopSelf();
}
@Override
public void onDestroy() {
super.onDestroy();
this.mHandler = null;
this.mAccount = null;
this.mCloudClient = null;
if(this.mSyncedFolders != null) this.mSyncedFolders.clear();
this.mSyncedFolders = null;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
......@@ -311,12 +140,9 @@ public class InitializerService extends Service {
if(intent == null || (extras = intent.getExtras()) == null) {
return;
}
RemoteOperationResult.ResultCode resultCode = extras.getParcelable(AppConstants.resultCodeKey);
//Note: Problem with parsing parcelable to ResultCode. Probably because it's null...
int httpResultCode = extras.getInt(AppConstants.resultIntentHttpCodeKey);
onFolderCreationResult(resultCode, httpResultCode);
doLastStep( extras.getBoolean(AppConstants.resultCodeKey, false),
extras.getInt(AppConstants.createdFolderCounterKey));
}
};
}
\ No newline at end of file
......@@ -25,15 +25,10 @@ public abstract class AppConstants {
public static final String KEY_LAST_SYNC_TIME = "lastSyncTimestamp"; //key for read/write last sync time (in ms) in prefs.
public static final String KEY_OMS_IS_WORKING = "OMS_is_working";
public static final String[] MEDIA_SYNCABLE_CATEGORIES = new String[]{"Images", "Movies", "Music", "Ringtones", "Documents", "Podcasts"};
public static final String[] SETTINGS_SYNCABLE_CATEGORIES = new String[]{"Rom settings"};
//Initializer
public static final String resultCodeKey = "result_code";
public static final String resultIntentActionKey = "CreateInitialFolderResult";
public static final String resultIntentHttpCodeKey = "result_http_code";
public static final String ACCOUNT_KEY_CODE = "account";
public static String createdFolderCounterKey = "createdFolderCounterKey";
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment