package com.seafile.seadroid2.ui.activity; import android.support.v7.app.AlertDialog; import android.content.*; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.IBinder; import android.provider.MediaStore.Images; import android.util.Log; import com.google.common.collect.Lists; import com.seafile.seadroid2.data.SeafRepo; import com.seafile.seadroid2.util.ConcurrentAsyncTask; import com.seafile.seadroid2.R; import com.seafile.seadroid2.SeafException; import com.seafile.seadroid2.account.Account; import com.seafile.seadroid2.data.DataManager; import com.seafile.seadroid2.data.SeafDirent; import com.seafile.seadroid2.transfer.TransferService; import com.seafile.seadroid2.transfer.TransferService.TransferBinder; import com.seafile.seadroid2.util.Utils; import org.apache.commons.io.IOUtils; import java.io.*; import java.util.ArrayList; import java.util.List; public class ShareToSeafileActivity extends BaseActivity { private static final String DEBUG_TAG = "ShareToSeafileActivity"; public static final String PASSWORD_DIALOG_FRAGMENT_TAG = "password_dialog_fragment_tag"; private static final int CHOOSE_COPY_MOVE_DEST_REQUEST = 1; private TransferService mTxService; private ServiceConnection mConnection; private ArrayList<String> localPathList; private Intent dstData; private Boolean isFinishActivity = false; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { Object extraStream = extras.get(Intent.EXTRA_STREAM); if(localPathList == null) localPathList = Lists.newArrayList(); loadSharedFiles(extraStream); } } private void loadSharedFiles(Object extraStream) { if (extraStream instanceof ArrayList) { ConcurrentAsyncTask.execute(new LoadSharedFileTask(), ((ArrayList<Uri>) extraStream).toArray(new Uri[]{})); } else if (extraStream instanceof Uri) { ConcurrentAsyncTask.execute(new LoadSharedFileTask(), (Uri) extraStream); } } private String getSharedFilePath(Uri uri) { if (uri == null) { return null; } if (uri.getScheme().equals("file")) { return uri.getPath(); } else { ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(uri, null, null, null, null); if (cursor == null || !cursor.moveToFirst()) { return null; } String filePath = cursor.getString(cursor.getColumnIndex(Images.Media.DATA)); return filePath; } } class LoadSharedFileTask extends AsyncTask<Uri, Void, File[]> { @Override protected File[] doInBackground(Uri... uriList) { if (uriList == null) return null; List<File> fileList = new ArrayList<File>(); for (Uri uri: uriList) { InputStream in = null; OutputStream out = null; try { File tempDir = DataManager.createTempDir(); File tempFile = new File(tempDir, Utils.getFilenamefromUri(ShareToSeafileActivity.this, uri)); if (!tempFile.createNewFile()) { throw new RuntimeException("could not create temporary file"); } in = getContentResolver().openInputStream(uri); out = new FileOutputStream(tempFile); IOUtils.copy(in, out); fileList.add(tempFile); } catch (IOException e) { Log.e(DEBUG_TAG, "Could not open requested document", e); } catch (RuntimeException e) { Log.e(DEBUG_TAG, "Could not open requested document", e); } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); } } return fileList.toArray(new File[]{}); } @Override protected void onPostExecute(File... fileList) { for (File file: fileList) { if (file == null) { showShortToast(ShareToSeafileActivity.this, R.string.saf_upload_path_not_available); } else { localPathList.add(file.getAbsolutePath()); } } if (localPathList == null || localPathList.size() == 0) { showShortToast(ShareToSeafileActivity.this, R.string.not_supported_share); finish(); return; } // Log.d(DEBUG_TAG, "share " + localPathList); Intent chooserIntent = new Intent(ShareToSeafileActivity.this, SeafilePathChooserActivity.class); startActivityForResult(chooserIntent, CHOOSE_COPY_MOVE_DEST_REQUEST); } } @Override protected void onDestroy() { Log.d(DEBUG_TAG, "onDestroy is called"); if (mTxService != null) { unbindService(mConnection); mTxService = null; } super.onDestroy(); } /** * update the file to its latest version to avoid duplicate files * * @param account * @param repoName * @param repoID * @param targetDir * @param localFilePaths */ private void addUpdateTask(Account account, String repoName, String repoID, String targetDir, ArrayList<String> localFilePaths) { bindTransferService(account, repoName, repoID, targetDir, localFilePaths, true); } /** * upload the file, which may lead up to duplicate files * * @param account * @param repoName * @param repoID * @param targetDir * @param localFilePaths */ private void addUploadTask(Account account, String repoName, String repoID, String targetDir, ArrayList<String> localFilePaths) { bindTransferService(account, repoName, repoID, targetDir, localFilePaths, false); } /** * Trying to bind {@link TransferService} in order to upload files after the service was connected * * @param account * @param repoName * @param repoID * @param targetDir * @param localPaths * @param update * update the file to avoid duplicates if true, * upload directly, otherwise. * */ private void bindTransferService(final Account account, final String repoName, final String repoID, final String targetDir, final ArrayList<String> localPaths, final boolean update) { // start transfer service Intent txIntent = new Intent(this, TransferService.class); startService(txIntent); Log.d(DEBUG_TAG, "start TransferService"); // bind transfer service Intent bIntent = new Intent(this, TransferService.class); final DataManager dataManager = new DataManager(account); mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { TransferBinder binder = (TransferBinder) service; mTxService = binder.getService(); for (String path : localPaths) { final SeafRepo repo = dataManager.getCachedRepoByID(repoID); if (repo != null && repo.canLocalDecrypt()) { mTxService.addTaskToUploadQue(account, repoID, repoName, targetDir, path, update, false, repo.encVersion); } else { mTxService.addUploadTask(account, repoID, repoName, targetDir, path, update, false); } Log.d(DEBUG_TAG, path + (update ? " updated" : " uploaded")); } showShortToast(ShareToSeafileActivity.this, R.string.upload_started); finish(); } @Override public void onServiceDisconnected(ComponentName arg0) { mTxService = null; } }; bindService(bIntent, mConnection, Context.BIND_AUTO_CREATE); Log.d(DEBUG_TAG, "try bind TransferService"); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode != CHOOSE_COPY_MOVE_DEST_REQUEST) { return; } isFinishActivity = true; if (resultCode == RESULT_OK) { if (!Utils.isNetworkOn()) { showShortToast(this, R.string.network_down); return; } dstData = data; String dstRepoId, dstRepoName, dstDir; Account account; dstRepoName = dstData.getStringExtra(SeafilePathChooserActivity.DATA_REPO_NAME); dstRepoId = dstData.getStringExtra(SeafilePathChooserActivity.DATA_REPO_ID); dstDir = dstData.getStringExtra(SeafilePathChooserActivity.DATA_DIR); account = dstData.getParcelableExtra(SeafilePathChooserActivity.DATA_ACCOUNT); notifyFileOverwriting(account, dstRepoName, dstRepoId, dstDir); Log.i(DEBUG_TAG, "CHOOSE_COPY_MOVE_DEST_REQUEST returns"); } else { finish(); } } @Override protected void onPostResume() { super.onPostResume(); /*if (dstData != null) { String dstRepoId, dstRepoName, dstDir; Account account; dstRepoName = dstData.getStringExtra(SeafilePathChooserActivity.DATA_REPO_NAME); dstRepoId = dstData.getStringExtra(SeafilePathChooserActivity.DATA_REPO_ID); dstDir = dstData.getStringExtra(SeafilePathChooserActivity.DATA_DIR); account = (Account)dstData.getParcelableExtra(SeafilePathChooserActivity.DATA_ACCOUNT); addUploadTask(account, dstRepoName, dstRepoId, dstDir, localPath); Log.d(DEBUG_TAG, "dstRepoName: " + dstRepoName); Log.d(DEBUG_TAG, "dstDir: " + dstDir); } if(isFinishActivity) { Log.d(DEBUG_TAG, "finish!"); isFinishActivity = false; finish(); }*/ } /** * Popup a dialog to notify user if allow to overwrite the file. * There are two buttons in the dialog, "Allow duplicate" and "Overwrite". * "Allow duplicate" will upload the file again, while "Overwrite" will update (overwrite) the file. * * @param account * @param repoName * @param repoID * @param targetDir */ private void notifyFileOverwriting(final Account account, final String repoName, final String repoID, final String targetDir) { boolean fileExistent = false; DataManager dm = new DataManager(account); List<SeafDirent> dirents = dm.getCachedDirents(repoID, targetDir); if (dirents != null) { for (String path : localPathList) { for (SeafDirent dirent : dirents) { if (dirent.isDir()) continue; if (Utils.fileNameFromPath(path).equals(dirent.getTitle())) { fileExistent = true; break; } } } if (fileExistent) { AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle(getString(R.string.overwrite_existing_file_title)) .setMessage(getString(R.string.overwrite_existing_file_msg)) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { addUpdateTask(account, repoName, repoID, targetDir, localPathList); if(isFinishActivity) { Log.d(DEBUG_TAG, "finish!"); finish(); } } }) .setNeutralButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if(isFinishActivity) { Log.d(DEBUG_TAG, "finish!"); finish(); } } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { addUploadTask(account, repoName, repoID, targetDir, localPathList); if (isFinishActivity) { Log.d(DEBUG_TAG, "finish!"); finish(); } } }); builder.show(); } else { if (!Utils.isNetworkOn()) { showShortToast(this, R.string.network_down); return; } // asynchronously check existence of the file from server asyncCheckDrientFromServer(account, repoName, repoID, targetDir); } } } private void asyncCheckDrientFromServer(Account account, String repoName, String repoID, String targetDir) { CheckDirentExistentTask task = new CheckDirentExistentTask(account, repoName, repoID, targetDir); ConcurrentAsyncTask.execute(task); } class CheckDirentExistentTask extends AsyncTask<Void, Void, Void> { private Account account; private String repoName; private String repoID; private String targetDir; private DataManager dm; private boolean fileExistent = false; public CheckDirentExistentTask(Account account, String repoName, String repoID, String targetDir) { this.account = account; this.repoName = repoName; this.repoID = repoID; this.targetDir = targetDir; dm = new DataManager(account); } @Override protected Void doInBackground(Void... params) { List<SeafDirent> dirents = null; try { dirents = dm.getDirentsFromServer(repoID, targetDir); } catch (SeafException e) { Log.e(DEBUG_TAG, e.getMessage() + e.getCode()); } boolean existent = false; if (dirents != null) { for (String path : localPathList) { for (SeafDirent dirent : dirents) { if (dirent.isDir()) continue; if (Utils.fileNameFromPath(path).equals(dirent.getTitle())) { existent = true; break; } } } } if (!existent) // upload the file directly addUploadTask(account, repoName, repoID, targetDir, localPathList); return null; } @Override protected void onPostExecute(Void aVoid) { if (fileExistent) showShortToast(ShareToSeafileActivity.this, R.string.overwrite_existing_file_exist); finish(); } } }