From 5f22080469f65177e58248cdfce1770cc24d8282 Mon Sep 17 00:00:00 2001 From: Eric Kok Date: Thu, 4 Apr 2013 23:48:41 +0200 Subject: [PATCH] Adding of torrent via UI or start intents. --- core/res/values/strings.xml | 3 +- .../transdroid/core/gui/TorrentsActivity.java | 138 +++++++++++++++++- .../{app => gui}/search/BarcodeHelper.java | 9 +- .../core/gui/search/FilePickerHelper.java | 47 ++++++ .../core/gui/search/UrlEntryDialog.java | 39 +++++ 5 files changed, 223 insertions(+), 13 deletions(-) rename core/src/org/transdroid/core/{app => gui}/search/BarcodeHelper.java (91%) create mode 100644 core/src/org/transdroid/core/gui/search/FilePickerHelper.java create mode 100644 core/src/org/transdroid/core/gui/search/UrlEntryDialog.java diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml index a3014d18..563fe83c 100644 --- a/core/res/values/strings.xml +++ b/core/res/values/strings.xml @@ -103,7 +103,8 @@ Torrent search Search for torrents - The Barcode Scanner could not be found. Would you like to install it from the Android Market? + The Barcode Scanner could not be found. Would you like to install it from the Play Store? + No compatible file manager could not be found. Would you like to install IO File Manager from the Play Store? Servers Add new server diff --git a/core/src/org/transdroid/core/gui/TorrentsActivity.java b/core/src/org/transdroid/core/gui/TorrentsActivity.java index 154ffd29..f9db7bad 100644 --- a/core/src/org/transdroid/core/gui/TorrentsActivity.java +++ b/core/src/org/transdroid/core/gui/TorrentsActivity.java @@ -1,5 +1,9 @@ package org.transdroid.core.gui; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -16,7 +20,6 @@ import org.androidannotations.annotations.SystemService; import org.androidannotations.annotations.UiThread; import org.androidannotations.annotations.ViewById; import org.transdroid.core.R; -import org.transdroid.core.app.search.BarcodeHelper; import org.transdroid.core.app.settings.ApplicationSettings; import org.transdroid.core.app.settings.ServerSetting; import org.transdroid.core.gui.lists.LocalTorrent; @@ -31,10 +34,15 @@ import org.transdroid.core.gui.navigation.Label; import org.transdroid.core.gui.navigation.NavigationFilter; import org.transdroid.core.gui.navigation.NavigationHelper; import org.transdroid.core.gui.navigation.StatusType; +import org.transdroid.core.gui.search.BarcodeHelper; +import org.transdroid.core.gui.search.FilePickerHelper; +import org.transdroid.core.gui.search.UrlEntryDialog; import org.transdroid.core.gui.settings.MainSettingsActivity_; import org.transdroid.daemon.Daemon; import org.transdroid.daemon.IDaemonAdapter; import org.transdroid.daemon.Torrent; +import org.transdroid.daemon.task.AddByFileTask; +import org.transdroid.daemon.task.AddByMagnetUrlTask; import org.transdroid.daemon.task.AddByUrlTask; import org.transdroid.daemon.task.DaemonTaskFailureResult; import org.transdroid.daemon.task.DaemonTaskResult; @@ -56,6 +64,7 @@ import org.transdroid.daemon.util.DLog; import android.annotation.TargetApi; import android.app.SearchManager; +import android.content.ContentResolver; import android.content.Intent; import android.net.Uri; import android.os.Build; @@ -147,7 +156,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi getSupportActionBar().setSelectedNavigationItem(lastUsed.getOrder()); // Handle any start up intents - if (firstStart) { + if (firstStart && getIntent() != null) { handleStartIntent(); } @@ -320,17 +329,69 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi * If required, add torrents, switch to a specific server, etc. */ protected void handleStartIntent() { - // TODO: Handle start intent + + Intent intent = getIntent(); + Uri dataUri = intent.getData(); + String data = intent.getDataString(); + String action = intent.getAction(); + + if (action.equals("org.transdroid.ADD_MULTIPLE")) { + // Intent should have some extras pointing to possibly multiple torrents + String[] urls = intent.getStringArrayExtra("TORRENT_URLS"); + String[] titles = intent.getStringArrayExtra("TORRENT_TITLES"); + if (urls != null) { + for (int i = 0; i < urls.length; i++) { + addTorrentByUrl(urls[i], (titles != null && titles.length >= i? titles[i]: "Torrent")); + } + } + return; + } + + if (dataUri.getScheme() != null && dataUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { + addTorrentFromDownloads(dataUri); + return; + } + + if (dataUri.getScheme().equals("http") || dataUri.getScheme().equals("https")) { + String title = data.substring(data.lastIndexOf("/")); + if (intent.hasExtra("TORRENT_TITLE")) { + title = intent.getStringExtra("TORRENT_TITLE"); + } + addTorrentByUrl(data, title); + return; + } + + if (dataUri.getScheme().equals("magnet")) { + addTorrentByMagnetUrl(data); + return; + } + + if (dataUri.getScheme().equals("file")) { + String title = data.substring(data.lastIndexOf("/")); + addTorrentByFile(data, title); + return; + } + } @OptionsItem(resName = "action_add_fromurl") protected void startUrlEntryDialog() { - // TODO: Open URL input dialog + UrlEntryDialog.startUrlEntry(this); } @OptionsItem(resName = "action_add_fromfile") protected void startFilePicker() { - // TODO: Start file picker + FilePickerHelper.startFilePicker(this); + } + + @Background + @OnActivityResult(FilePickerHelper.ACTIVITY_FILEPICKER) + public void onFilePicked(int resultCode, Intent data) { + // We should have received an Intent with a local torrent's Uri as data from the file picker + if (data != null && data.getData() != null && !data.getData().equals("")) { + String url = data.getData().getPath(); + addTorrentByFile(data.getData().toString(), url.substring(url.lastIndexOf("/"))); + } } @OptionsItem(resName = "action_add_frombarcode") @@ -338,15 +399,17 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi BarcodeHelper.startBarcodeScanner(this); } + @Background @OnActivityResult(BarcodeHelper.ACTIVITY_BARCODE) public void onBarcodeScanned(int resultCode, Intent data) { - String query = BarcodeHelper.handleScanResult(this, resultCode, data); + // We receive from the helper either a URL (as string) or a query we can start a search for + String query = BarcodeHelper.handleScanResult(resultCode, data); if (query.startsWith("http")) addTorrentByUrl(query, "QR code result"); // No torrent title known else startSearch(query, false, null, false); } - + @OptionsItem(resName = "action_refresh") protected void refreshScreen() { fragmentTorrents.updateIsLoading(true); @@ -412,7 +475,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi } @Background - public void addTorrentByUrl(String url, String title) { + protected void addTorrentByUrl(String url, String title) { DaemonTaskResult result = AddByUrlTask.create(currentConnection, url, title).execute(); if (result instanceof DaemonTaskResult) { onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_added, title); @@ -422,6 +485,65 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi } } + @Background + protected void addTorrentByMagnetUrl(String url) { + DaemonTaskResult result = AddByMagnetUrlTask.create(currentConnection, url).execute(); + if (result instanceof DaemonTaskResult) { + onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_added, "Torrent"); + refreshTorrents(); + } else { + onCommunicationError((DaemonTaskFailureResult) result); + } + } + + @Background + protected void addTorrentByFile(String localFile, String title) { + DaemonTaskResult result = AddByFileTask.create(currentConnection, localFile).execute(); + if (result instanceof DaemonTaskResult) { + onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_added, title); + refreshTorrents(); + } else { + onCommunicationError((DaemonTaskFailureResult) result); + } + } + + private void addTorrentFromDownloads(Uri contentUri) { + + InputStream input = null; + try { + // Open the content uri as input stream + input = getContentResolver().openInputStream(contentUri); + + // Write a temporary file with the torrent contents + File tempFile = File.createTempFile("transdroid_", ".torrent", getCacheDir()); + FileOutputStream output = new FileOutputStream(tempFile); + try { + final byte[] buffer = new byte[1024]; + int read; + while ((read = input.read(buffer)) != -1) + output.write(buffer, 0, read); + output.flush(); + String fileName = Uri.fromFile(tempFile).toString(); + addTorrentByFile(fileName, fileName.substring(fileName.lastIndexOf("/"))); + } finally { + output.close(); + } + } catch (SecurityException e) { + // No longer access to this file + Crouton.showText(this, R.string.error_torrentfile, navigationHelper.CROUTON_ERROR_STYLE); + } catch (IOException e1) { + // Can't write temporary file + Crouton.showText(this, R.string.error_torrentfile, navigationHelper.CROUTON_ERROR_STYLE); + } finally { + try { + if (input != null) + input.close(); + } catch (IOException e) { + Crouton.showText(this, R.string.error_torrentfile, navigationHelper.CROUTON_ERROR_STYLE); + } + } + } + @Background @Override public void resumeTorrent(Torrent torrent) { diff --git a/core/src/org/transdroid/core/app/search/BarcodeHelper.java b/core/src/org/transdroid/core/gui/search/BarcodeHelper.java similarity index 91% rename from core/src/org/transdroid/core/app/search/BarcodeHelper.java rename to core/src/org/transdroid/core/gui/search/BarcodeHelper.java index e504068d..ccf46913 100644 --- a/core/src/org/transdroid/core/app/search/BarcodeHelper.java +++ b/core/src/org/transdroid/core/gui/search/BarcodeHelper.java @@ -1,7 +1,7 @@ -package org.transdroid.core.app.search; +package org.transdroid.core.gui.search; import org.transdroid.core.R; -import org.transdroid.core.gui.TorrentsActivity; +import org.transdroid.core.app.search.GoogleWebSearchBarcodeResolver; import android.app.AlertDialog; import android.content.DialogInterface; @@ -38,7 +38,8 @@ public class BarcodeHelper { .setPositiveButton(android.R.string.yes, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - activity.startActivity(new Intent(Intent.ACTION_VIEW, SCANNER_MARKET_URI)); + if (activity != null) + activity.startActivity(new Intent(Intent.ACTION_VIEW, SCANNER_MARKET_URI)); } }).setNegativeButton(android.R.string.no, null).create(); }; @@ -54,7 +55,7 @@ public class BarcodeHelper { * @return A String that can be used as new search query, or null if the bar code could not be scanned or no query * can be constructed for it */ - public static String handleScanResult(TorrentsActivity activity, int resultCode, Intent data) { + public static String handleScanResult(int resultCode, Intent data) { String contents = data.getStringExtra("SCAN_RESULT"); String formatName = data.getStringExtra("SCAN_RESULT_FORMAT"); if (formatName != null && formatName.equals("QR_CODE")) { diff --git a/core/src/org/transdroid/core/gui/search/FilePickerHelper.java b/core/src/org/transdroid/core/gui/search/FilePickerHelper.java new file mode 100644 index 00000000..de463505 --- /dev/null +++ b/core/src/org/transdroid/core/gui/search/FilePickerHelper.java @@ -0,0 +1,47 @@ +package org.transdroid.core.gui.search; + +import org.transdroid.core.R; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.net.Uri; +import android.support.v4.app.DialogFragment; + +import com.actionbarsherlock.app.SherlockFragmentActivity; + +public class FilePickerHelper { + + public static final int ACTIVITY_FILEPICKER = 0x0000c0df; // A 'random' ID to identify file picker intents + public static final Uri FILEMANAGER_MARKET_URI = Uri.parse("market://search?q=pname:org.openintents.filemanager"); + + /** + * Call this to start a file picker intent. The calling activity will receive an Intent result with ID + * {@link #ACTIVITY_FILEPICKER} with an Intent that contains the selected local file as data Intent. + * @param activity The calling activity, to which the result is returned or a dialog is bound that asks to install + * the file picker + */ + public static void startFilePicker(final SherlockFragmentActivity activity) { + try { + // Start a file manager that can handle the PICK_FILE intent (specifically IO File Manager) + activity.startActivityForResult(new Intent("org.openintents.action.PICK_FILE"), ACTIVITY_FILEPICKER); + } catch (Exception e) { + // Can't start the file manager, for example with a SecurityException or when IO File Manager is not present + new DialogFragment() { + public android.app.Dialog onCreateDialog(android.os.Bundle savedInstanceState) { + return new AlertDialog.Builder(activity).setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(activity.getString(R.string.search_filemanagernotfound)) + .setPositiveButton(android.R.string.yes, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (activity != null) + activity.startActivity(new Intent(Intent.ACTION_VIEW, FILEMANAGER_MARKET_URI)); + } + }).setNegativeButton(android.R.string.no, null).create(); + }; + }.show(activity.getSupportFragmentManager(), "installfilemanager"); + } + } + +} diff --git a/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java b/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java new file mode 100644 index 00000000..db0f7eb4 --- /dev/null +++ b/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java @@ -0,0 +1,39 @@ +package org.transdroid.core.gui.search; + +import org.transdroid.core.gui.TorrentsActivity; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.support.v4.app.DialogFragment; +import android.text.InputType; +import android.text.TextUtils; +import android.widget.EditText; + +public class UrlEntryDialog { + + /** + * Opens a dialog that allows entry of a single URL string, which (on confirmation) will be supplied to the calling + * activity's {@link TorrentsActivity#addTorrentByUrl(String, String) method}. + * @param activity The activity that opens (and owns) this dialog + */ + public static void startUrlEntry(final TorrentsActivity activity) { + new DialogFragment() { + public android.app.Dialog onCreateDialog(android.os.Bundle savedInstanceState) { + final EditText urlInput = new EditText(activity); + urlInput.setInputType(InputType.TYPE_TEXT_VARIATION_URI); + return new AlertDialog.Builder(activity).setView(urlInput) + .setPositiveButton(android.R.string.ok, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Assume text entry box input as URL and treat the filename (after the last /) as title + String url = urlInput.getText().toString(); + if (activity != null && !TextUtils.isEmpty(url)) + activity.addTorrentByUrl(url, url.substring(url.lastIndexOf("/"))); + } + }).setNegativeButton(android.R.string.cancel, null).create(); + }; + }.show(activity.getSupportFragmentManager(), "urlentry"); + } + +}