Browse Source

Added support for Aria2 via its JSON RPC-API. Fixes #164.

pull/173/head
Eric Kok 10 years ago
parent
commit
09e5486ec3
  1. 2
      core/.classpath
  2. 4
      core/AndroidManifest.xml
  3. 5
      core/res/values/changelog.xml
  4. 5
      core/res/values/strings.xml
  5. 2
      core/src/org/transdroid/core/gui/settings/ServerSettingsActivity.java
  6. 4
      full/AndroidManifest.xml
  7. 502
      lib/src/org/transdroid/daemon/Aria2c/Aria2Adapter.java
  8. 37
      lib/src/org/transdroid/daemon/Daemon.java
  9. 2
      lib/src/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java
  10. 4
      lite/AndroidManifest.xml

2
core/.classpath

@ -10,6 +10,6 @@ @@ -10,6 +10,6 @@
</attributes>
</classpathentry>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry exported="true" kind="lib" path="libs/transdroid.jar"/>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/Transdroid Torrent Connect"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

4
core/AndroidManifest.xml

@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.transdroid.core"
android:versionCode="215"
android:versionName="2.2.0" >
android:versionCode="216"
android:versionName="2.3.0" >
<uses-sdk
android:minSdkVersion="15"

5
core/res/values/changelog.xml

@ -17,10 +17,15 @@ @@ -17,10 +17,15 @@
-->
<resources>
<string name="system_changelog">
Transdroid 2.3.0\n
- Aria2 support\n
\n
Transdroid 2.2.0\n
- Dropped legacy Android support; Android 4.0.3 is the new minimum\n
- Added Default Server option\n
- Fixed list selection quirks\n
- Another language-related qBittorrent fix\n
- Copy RSS item or torrent file name to clipboard\n
- Properly disable FTP download option when not supported\n
- Support KitKat file picker and more file managers\n
- Many updated translations\n

5
core/res/values/strings.xml

@ -244,7 +244,8 @@ @@ -244,7 +244,8 @@
<string name="pref_port">Port number</string>
<string name="pref_user">User name</string>
<string name="pref_pass">Password</string>
<string name="pref_extrapass">Deluge web password</string>
<string name="pref_extrapassword">Deluge web password</string>
<string name="pref_secret">Secret token</string>
<string name="pref_advanced">Advanced settings</string>
<string name="pref_localaddress">Local IP or host</string>
<string name="pref_localaddress_info">When connected to the specified local network</string>
@ -350,6 +351,7 @@ @@ -350,6 +351,7 @@
</string-array>
<string-array name="pref_daemon_types" translatable="false">
<item>Aria2</item>
<item>BitComet</item>
<item>Bitflu 1.2+</item>
<item>BitTorrent 6+</item>
@ -366,6 +368,7 @@ @@ -366,6 +368,7 @@
<item>Vuze</item>
</string-array>
<string-array name="pref_daemon_values" translatable="false">
<item>daemon_aria2</item>
<item>daemon_bitcomet</item>
<item>daemon_bitflu</item>
<item>daemon_bittorrent</item>

2
core/src/org/transdroid/core/gui/settings/ServerSettingsActivity.java

@ -117,6 +117,8 @@ public class ServerSettingsActivity extends KeyBoundPreferencesActivity { @@ -117,6 +117,8 @@ public class ServerSettingsActivity extends KeyBoundPreferencesActivity {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Daemon daemonType = Daemon.fromCode(prefs.getString("server_type_" + key, null));
extraPass.setEnabled(Daemon.supportsExtraPassword(daemonType));
extraPass.setTitle(getString(daemonType == Daemon.Deluge ? R.string.pref_extrapassword : R.string.pref_secret));
extraPass.setDialogTitle(extraPass.getTitle());
folder.setEnabled(daemonType == null ? false : Daemon.supportsCustomFolder(daemonType));
downloadDir.setEnabled(daemonType == null ? false : Daemon.needsManualPathSpecified(daemonType));
// sslTrustKey.setEnabled(sslValue && !sslTAValue);

4
full/AndroidManifest.xml

@ -18,8 +18,8 @@ @@ -18,8 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.transdroid.full"
android:versionCode="215"
android:versionName="2.2.0" >
android:versionCode="216"
android:versionName="2.3.0" >
<uses-sdk
android:minSdkVersion="15"

502
lib/src/org/transdroid/daemon/Aria2c/Aria2Adapter.java

@ -0,0 +1,502 @@ @@ -0,0 +1,502 @@
/*
* This file is part of Transdroid <http://www.transdroid.org>
*
* Transdroid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Transdroid 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 Transdroid. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.transdroid.daemon.Aria2c;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.base64.android.Base64;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.DaemonException;
import org.transdroid.daemon.DaemonException.ExceptionType;
import org.transdroid.daemon.DaemonSettings;
import org.transdroid.daemon.IDaemonAdapter;
import org.transdroid.daemon.Priority;
import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentDetails;
import org.transdroid.daemon.TorrentFile;
import org.transdroid.daemon.TorrentStatus;
import org.transdroid.daemon.task.AddByFileTask;
import org.transdroid.daemon.task.AddByMagnetUrlTask;
import org.transdroid.daemon.task.AddByUrlTask;
import org.transdroid.daemon.task.DaemonTask;
import org.transdroid.daemon.task.DaemonTaskFailureResult;
import org.transdroid.daemon.task.DaemonTaskResult;
import org.transdroid.daemon.task.DaemonTaskSuccessResult;
import org.transdroid.daemon.task.GetFileListTask;
import org.transdroid.daemon.task.GetFileListTaskSuccessResult;
import org.transdroid.daemon.task.GetTorrentDetailsTask;
import org.transdroid.daemon.task.GetTorrentDetailsTaskSuccessResult;
import org.transdroid.daemon.task.PauseTask;
import org.transdroid.daemon.task.RemoveTask;
import org.transdroid.daemon.task.ResumeTask;
import org.transdroid.daemon.task.RetrieveTask;
import org.transdroid.daemon.task.RetrieveTaskSuccessResult;
import org.transdroid.daemon.task.SetTransferRatesTask;
import org.transdroid.daemon.util.DLog;
import org.transdroid.daemon.util.HttpHelper;
import android.net.Uri;
import android.text.TextUtils;
/**
* The daemon adapter from the Aria2 torrent client. Documentation available at
* http://aria2.sourceforge.net/manual/en/html/aria2c.html
* @author erickok
*/
public class Aria2Adapter implements IDaemonAdapter {
private static final String LOG_NAME = "Aria2 daemon";
private DaemonSettings settings;
private DefaultHttpClient httpclient;
public Aria2Adapter(DaemonSettings settings) {
this.settings = settings;
}
@Override
public DaemonTaskResult executeTask(DaemonTask task) {
try {
JSONArray params = new JSONArray();
switch (task.getMethod()) {
case Retrieve:
// Request all torrents from server
// NOTE Since there is no aria2.tellAll (or something) we have to use batch requests
JSONArray fields = new JSONArray().put("gid").put("status").put("totalLength").put("completedLength")
.put("uploadLength").put("downloadSpeed").put("uploadSpeed").put("numSeeders").put("dir")
.put("connections").put("errorCode").put("bittorrent").put("files");
JSONObject active = buildRequest("aria2.tellActive", new JSONArray().put(fields));
JSONObject waiting = buildRequest("aria2.tellWaiting", new JSONArray().put(0).put(9999).put(fields));
JSONObject stopped = buildRequest("aria2.tellStopped", new JSONArray().put(0).put(9999).put(fields));
params.put(active).put(waiting).put(stopped);
List<Torrent> torrents = new ArrayList<Torrent>();
JSONArray lists = makeRequestForArray(params.toString());
for (int i = 0; i < lists.length(); i++) {
torrents.addAll(parseJsonRetrieveTorrents(lists.getJSONObject(i).getJSONArray("result")));
}
return new RetrieveTaskSuccessResult((RetrieveTask) task, torrents, null);
case GetTorrentDetails:
// Request file listing of a torrent
params.put(task.getTargetTorrent().getUniqueID()); // gid
params.put(new JSONArray().put("bittorrent").put("errorCode"));
JSONObject dinfo = makeRequest(buildRequest("aria2.tellStatus", params).toString());
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task,
parseJsonTorrentDetails(dinfo.getJSONObject("result")));
case GetFileList:
// Request file listing of a torrent
params.put(task.getTargetTorrent().getUniqueID()); // torrent_id
JSONObject finfo = makeRequest(buildRequest("aria2.getFiles", params).toString());
return new GetFileListTaskSuccessResult((GetFileListTask) task, parseJsonFileListing(
finfo.getJSONArray("result"), task.getTargetTorrent()));
case AddByFile:
// Encode the .torrent file's data
String file = ((AddByFileTask) task).getFile();
InputStream in = new Base64.InputStream(new FileInputStream(new File(URI.create(file))), Base64.ENCODE);
StringWriter writer = new StringWriter();
int c;
while ((c = in.read()) != -1) {
writer.write(c);
}
in.close();
// Request to add a torrent by local .torrent file
params.put(writer.toString());
makeRequest(buildRequest("aria2.addTorrent", params).toString());
return new DaemonTaskSuccessResult(task);
case AddByUrl:
// Request to add a torrent by URL
String url = ((AddByUrlTask) task).getUrl();
params.put(new JSONArray().put(url));
makeRequest(buildRequest("aria2.addUri", params).toString());
return new DaemonTaskSuccessResult(task);
case AddByMagnetUrl:
// Request to add a magnet link by URL
String magnet = ((AddByMagnetUrlTask) task).getUrl();
params.put(new JSONArray().put(magnet));
makeRequest(buildRequest("aria2.addUri", params).toString());
return new DaemonTaskSuccessResult(task);
case Remove:
// Remove a torrent
RemoveTask removeTask = (RemoveTask) task;
makeRequest(buildRequest(removeTask.includingData() ? "aria2.removeDownloadResult" : "aria2.remove",
params.put(removeTask.getTargetTorrent().getUniqueID())).toString());
return new DaemonTaskSuccessResult(task);
case Pause:
// Pause a torrent
PauseTask pauseTask = (PauseTask) task;
makeRequest(buildRequest("aria2.pause", params.put(pauseTask.getTargetTorrent().getUniqueID()))
.toString());
return new DaemonTaskSuccessResult(task);
case PauseAll:
// Resume all torrents
makeRequest(buildRequest("aria2.pauseAll", null).toString());
return new DaemonTaskSuccessResult(task);
case Resume:
// Resume a torrent
ResumeTask resumeTask = (ResumeTask) task;
makeRequest(buildRequest("aria2.unpause", params.put(resumeTask.getTargetTorrent().getUniqueID()))
.toString());
return new DaemonTaskSuccessResult(task);
case ResumeAll:
// Resume all torrents
makeRequest(buildRequest("aria2.unpauseAll", null).toString());
return new DaemonTaskSuccessResult(task);
case SetTransferRates:
// Request to set the maximum transfer rates
SetTransferRatesTask ratesTask = (SetTransferRatesTask) task;
JSONObject options = new JSONObject();
options.put("max-overall-download-limit", (ratesTask.getDownloadRate() == null ? -1 : ratesTask
.getDownloadRate().intValue()));
options.put("max-overall-upload-limit", (ratesTask.getUploadRate() == null ? -1 : ratesTask
.getUploadRate().intValue()));
makeRequest(buildRequest("aria2.changeGlobalOption", params.put(options)).toString());
return new DaemonTaskSuccessResult(task);
default:
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.MethodUnsupported,
task.getMethod() + " is not supported by " + getType()));
}
} catch (JSONException e) {
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.ParsingFailed, e.toString()));
} catch (DaemonException e) {
return new DaemonTaskFailureResult(task, e);
} catch (FileNotFoundException e) {
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.FileAccessError, e.toString()));
} catch (IOException e) {
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.FileAccessError, e.toString()));
}
}
private JSONObject buildRequest(String sendMethod, JSONArray params) throws JSONException {
// Build request for method
if (!TextUtils.isEmpty(settings.getExtraPassword())) {
JSONArray signed = new JSONArray();
// Start with the secret token as parameter and then add the normal parameters
signed.put("token:" + settings.getExtraPassword());
for (int i = 0; i < params.length(); i++) {
signed.put(params.get(i));
}
params = signed;
}
JSONObject request = new JSONObject();
request.put("id", "transdroid");
request.put("jsonrpc", "2.0");
request.put("method", sendMethod);
request.put("params", params);
return request;
}
private synchronized JSONObject makeRequest(String data) throws DaemonException {
String raw = makeRawRequest(data);
try {
return new JSONObject(raw);
} catch (JSONException e) {
DLog.d(LOG_NAME, "Error: " + e.toString());
throw new DaemonException(ExceptionType.UnexpectedResponse, e.toString());
}
}
private synchronized JSONArray makeRequestForArray(String data) throws DaemonException {
String raw = makeRawRequest(data);
try {
return new JSONArray(raw);
} catch (JSONException e) {
DLog.d(LOG_NAME, "Error: " + e.toString());
throw new DaemonException(ExceptionType.UnexpectedResponse, e.toString());
}
}
private synchronized String makeRawRequest(String data) throws DaemonException {
try {
// Initialise the HTTP client
if (httpclient == null) {
httpclient = HttpHelper.createStandardHttpClient(settings, !TextUtils.isEmpty(settings.getUsername()));
httpclient.addRequestInterceptor(HttpHelper.gzipRequestInterceptor);
httpclient.addResponseInterceptor(HttpHelper.gzipResponseInterceptor);
}
// Set POST URL and data
String url = (settings.getSsl() ? "https://" : "http://") + settings.getAddress() + ":"
+ settings.getPort() + (settings.getFolder() == null ? "" : settings.getFolder()) + "/jsonrpc";
HttpPost httppost = new HttpPost(url);
httppost.setEntity(new StringEntity(data));
httppost.setHeader("Content-Type", "application/json");
httppost.setHeader("Accept", "application/json");
// Execute
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity == null)
throw new DaemonException(ExceptionType.UnexpectedResponse, "No HTTP entity in response object.");
// Read JSON response
InputStream instream = entity.getContent();
String result = HttpHelper.convertStreamToString(instream);
instream.close();
DLog.d(LOG_NAME,
"Success: "
+ (result.length() > 300 ? result.substring(0, 300) + "... (" + result.length() + " chars)"
: result));
return result;
} catch (Exception e) {
DLog.d(LOG_NAME, "Error: " + e.toString());
throw new DaemonException(ExceptionType.ConnectionError, e.toString());
}
}
private ArrayList<Torrent> parseJsonRetrieveTorrents(JSONArray response) throws JSONException, DaemonException {
// Parse response
ArrayList<Torrent> torrents = new ArrayList<Torrent>();
for (int j = 0; j < response.length(); j++) {
// Add the parsed torrent to the list
JSONObject tor = response.getJSONObject(j);
int downloadSpeed = tor.getInt("downloadSpeed");
long totalLength = tor.getLong("totalLength");
long completedLength = tor.getLong("completedLength");
int numSeeders = tor.has("numSeeders") ? tor.getInt("numSeeders") : 0;
TorrentStatus status = convertAriaState(tor.getString("status"), completedLength == totalLength);
int errorCode = tor.optInt("errorCode", 0);
String error = errorCode > 0 ? convertAriaError(errorCode) : null;
String name = null;
JSONObject bittorrent = null;
if (tor.has("bittorrent")) {
// Get name form the bittorrent info object
bittorrent = tor.getJSONObject("bittorrent");
if (bittorrent.has("info"))
name = bittorrent.getJSONObject("info").getString("name");
} else if (tor.has("files")) {
// Get name from the first included file we can find
JSONArray files = tor.getJSONArray("files");
if (files.length() > 0) {
name = Uri.parse(files.getJSONObject(0).getString("path")).getLastPathSegment();
}
}
if (name == null)
name = tor.getString("gid"); // Fallback name
// @formatter:off
torrents.add(new Torrent(
j,
tor.getString("gid"),
name,
status,
tor.getString("dir"),
downloadSpeed,
tor.getInt("uploadSpeed"),
tor.getInt("connections"),
numSeeders ,
tor.getInt("connections"),
numSeeders,
(downloadSpeed > 0? (int) (totalLength / downloadSpeed): -1),
completedLength,
tor.getLong("uploadLength"),
totalLength,
completedLength / (float) totalLength, // Percentage to [0..1]
0f, // Not available
null, // Not available
null, // Not available
null, // Not available
error,
settings.getType()));
// @formatter:on
}
return torrents;
}
private ArrayList<TorrentFile> parseJsonFileListing(JSONArray response, Torrent torrent) throws JSONException {
// Parse response
ArrayList<TorrentFile> files = new ArrayList<TorrentFile>();
for (int j = 0; j < response.length(); j++) {
JSONObject file = response.getJSONObject(j);
// Add the parsed torrent to the list
// @formatter:off
String rel = file.getString("path");
if (rel.startsWith(torrent.getLocationDir())) {
rel = rel.substring(torrent.getLocationDir().length());
}
files.add(new TorrentFile(
Integer.toString(file.getInt("index")),
rel,
rel,
file.getString("path"),
file.getLong("length"),
file.getLong("completedLength"),
file.getBoolean("selected") ? Priority.Normal : Priority.Off));
// @formatter:on
}
return files;
}
private TorrentDetails parseJsonTorrentDetails(JSONObject response) throws JSONException {
// Parse response
List<String> trackers = new ArrayList<String>();
List<String> errors = new ArrayList<String>();
int error = response.optInt("errorCode", 0);
if (error > 0)
errors.add(convertAriaError(error));
if (response.has("bittorrent")) {
JSONObject bittorrent = response.getJSONObject("bittorrent");
JSONArray announceList = bittorrent.getJSONArray("announceList");
for (int i = 0; i < announceList.length(); i++) {
JSONArray announceUrlList = announceList.getJSONArray(i);
for (int j = 0; j < announceUrlList.length(); j++) {
trackers.add(announceUrlList.getString(j));
}
}
}
return new TorrentDetails(trackers, errors);
}
private TorrentStatus convertAriaState(String state, boolean isFinished) {
// Aria2 sends a string as status code
// (http://aria2.sourceforge.net/manual/en/html/aria2c.html#aria2.tellStatus)
if (state.equals("active")) {
return isFinished ? TorrentStatus.Seeding : TorrentStatus.Downloading;
} else if (state.equals("waiting")) {
return TorrentStatus.Queued;
} else if (state.equals("paused") || state.equals("complete")) {
return TorrentStatus.Paused;
} else if (state.equals("error")) {
return TorrentStatus.Error;
} else if (state.equals("removed")) {
return TorrentStatus.Checking;
}
return TorrentStatus.Unknown;
}
private String convertAriaError(int errorCode) {
// Aria2 sends an exit code as error (http://aria2.sourceforge.net/manual/en/html/aria2c.html#id1)
String error = "Aria error #" + Integer.toString(errorCode);
switch (errorCode) {
case 3:
case 4:
return error + ": Resource was not found";
case 5:
return error + ": Aborted because download speed was too slow";
case 6:
return error + ": Network problem occurred";
case 8:
return error + ": Remote server did not support resume when resume was required to complete download";
case 9:
return error + ": There was not enough disk space available";
case 11:
case 12:
return error + ": Duplicate file or info hash download";
case 15:
case 16:
return error + ": Aria2 could not create new or open or truncate existing file";
case 17:
case 18:
case 19:
return error + ": File I/O error occurred";
case 20:
case 27:
return error + ": Aria2 could not parse Magnet URI or Metalink document";
case 21:
return error + ": FTP command failed";
case 22:
return error + ": HTTP response header was bad or unexpected";
case 23:
return error + ": Too many redirects occurred";
case 24:
return error + ": HTTP authorization failed";
case 26:
return error + ": \".torrent\" file is corrupted or missing information that aria2 needs";
default:
return error;
}
}
@Override
public Daemon getType() {
return settings.getType();
}
@Override
public DaemonSettings getSettings() {
return this.settings;
}
}

37
lib/src/org/transdroid/daemon/Daemon.java

@ -17,8 +17,12 @@ @@ -17,8 +17,12 @@
*/
package org.transdroid.daemon;
import org.transdroid.daemon.Deluge.DelugeAdapter;
import org.transdroid.daemon.Aria2c.Aria2Adapter;
import org.transdroid.daemon.BitComet.BitCometAdapter;
import org.transdroid.daemon.Bitflu.BitfluAdapter;
import org.transdroid.daemon.BuffaloNas.BuffaloNasAdapter;
import org.transdroid.daemon.DLinkRouterBT.DLinkRouterBTAdapter;
import org.transdroid.daemon.Deluge.DelugeAdapter;
import org.transdroid.daemon.Ktorrent.KtorrentAdapter;
import org.transdroid.daemon.Qbittorrent.QbittorrentAdapter;
import org.transdroid.daemon.Rtorrent.RtorrentAdapter;
@ -27,9 +31,6 @@ import org.transdroid.daemon.Tfb4rt.Tfb4rtAdapter; @@ -27,9 +31,6 @@ import org.transdroid.daemon.Tfb4rt.Tfb4rtAdapter;
import org.transdroid.daemon.Transmission.TransmissionAdapter;
import org.transdroid.daemon.Utorrent.UtorrentAdapter;
import org.transdroid.daemon.Vuze.VuzeAdapter;
import org.transdroid.daemon.Bitflu.BitfluAdapter;
import org.transdroid.daemon.BuffaloNas.BuffaloNasAdapter;
import org.transdroid.daemon.BitComet.BitCometAdapter;
/**
* Factory for new instances of server daemons, based on user settings.
@ -39,6 +40,11 @@ import org.transdroid.daemon.BitComet.BitCometAdapter; @@ -39,6 +40,11 @@ import org.transdroid.daemon.BitComet.BitCometAdapter;
*/
public enum Daemon {
Aria2 {
public IDaemonAdapter createAdapter(DaemonSettings settings) {
return new Aria2Adapter(settings);
}
},
Bitflu {
public IDaemonAdapter createAdapter(DaemonSettings settings) {
return new BitfluAdapter(settings);
@ -125,6 +131,8 @@ public enum Daemon { @@ -125,6 +131,8 @@ public enum Daemon {
if (type == null)
return null;
switch (type) {
case Aria2:
return "daemon_aria2";
case BitComet:
return "daemon_bitcomet";
case Bitflu:
@ -169,6 +177,9 @@ public enum Daemon { @@ -169,6 +177,9 @@ public enum Daemon {
if (daemonCode == null) {
return null;
}
if (daemonCode.equals("daemon_aria2")) {
return Aria2;
}
if (daemonCode.equals("daemon_bitcomet")) {
return BitComet;
}
@ -252,6 +263,8 @@ public enum Daemon { @@ -252,6 +263,8 @@ public enum Daemon {
return 4081;
case Vuze:
return 6884;
case Aria2:
return 6800;
}
return 8080;
}
@ -265,11 +278,11 @@ public enum Daemon { @@ -265,11 +278,11 @@ public enum Daemon {
}
public static boolean supportsFileListing(Daemon type) {
return type == Synology || type == Transmission || type == uTorrent || type == BitTorrent || type == KTorrent || type == Deluge || type == rTorrent || type == Vuze || type == DLinkRouterBT || type == Bitflu || type == qBittorrent || type == BuffaloNas || type == BitComet || type == Dummy;
return type == Synology || type == Transmission || type == uTorrent || type == BitTorrent || type == KTorrent || type == Deluge || type == rTorrent || type == Vuze || type == DLinkRouterBT || type == Bitflu || type == qBittorrent || type == BuffaloNas || type == BitComet || type == Aria2 || type == Dummy;
}
public static boolean supportsFineDetails(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Daemon.Transmission || type == Deluge || type == rTorrent || type == qBittorrent || type == Dummy;
return type == uTorrent || type == BitTorrent || type == Daemon.Transmission || type == Deluge || type == rTorrent || type == qBittorrent || type == Aria2 || type == Dummy;
}
public static boolean needsManualPathSpecified(Daemon type) {
@ -277,7 +290,7 @@ public enum Daemon { @@ -277,7 +290,7 @@ public enum Daemon {
}
public static boolean supportsFilePaths(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Vuze || type == Deluge || type == Transmission || type == rTorrent || type == KTorrent || type == BuffaloNas || type == Dummy;
return type == uTorrent || type == BitTorrent || type == Vuze || type == Deluge || type == Transmission || type == rTorrent || type == KTorrent || type == BuffaloNas || type == Aria2 || type == Dummy;
}
public static boolean supportsStoppingStarting(Daemon type) {
@ -293,7 +306,7 @@ public enum Daemon { @@ -293,7 +306,7 @@ public enum Daemon {
}
public static boolean supportsSetTransferRates(Daemon type) {
return type == Deluge || type == Transmission || type == uTorrent || type == BitTorrent || type == Deluge || type == rTorrent || type == Vuze || type == BuffaloNas || type == BitComet || type == Dummy;
return type == Deluge || type == Transmission || type == uTorrent || type == BitTorrent || type == Deluge || type == rTorrent || type == Vuze || type == BuffaloNas || type == BitComet || type == Aria2 || type == Dummy;
}
public static boolean supportsAddByFile(Daemon type) {
@ -302,11 +315,11 @@ public enum Daemon { @@ -302,11 +315,11 @@ public enum Daemon {
}
public static boolean supportsAddByMagnetUrl(Daemon type) {
return type == uTorrent || type == BitTorrent || type == Transmission || type == Synology || type == Deluge || type == Bitflu || type == KTorrent || type == rTorrent || type == qBittorrent || type == BitComet || type == Dummy;
return type == uTorrent || type == BitTorrent || type == Transmission || type == Synology || type == Deluge || type == Bitflu || type == KTorrent || type == rTorrent || type == qBittorrent || type == BitComet || type == Aria2 || type == Dummy;
}
public static boolean supportsRemoveWithData(Daemon type) {
return type == uTorrent || type == Vuze || type == Transmission || type == Deluge || type == BitTorrent || type == Tfb4rt || type == DLinkRouterBT || type == Bitflu || type == qBittorrent || type == BuffaloNas || type == BitComet || type == rTorrent || type == Dummy;
return type == uTorrent || type == Vuze || type == Transmission || type == Deluge || type == BitTorrent || type == Tfb4rt || type == DLinkRouterBT || type == Bitflu || type == qBittorrent || type == BuffaloNas || type == BitComet || type == rTorrent || type == Aria2 || type == Dummy;
}
public static boolean supportsFilePrioritySetting(Daemon type) {
@ -342,11 +355,11 @@ public enum Daemon { @@ -342,11 +355,11 @@ public enum Daemon {
}
public static boolean supportsExtraPassword(Daemon type) {
return type == Deluge;
return type == Deluge || type == Aria2;
}
public static boolean supportsUsernameForHttp(Daemon type) {
return type == Deluge;
return type == Deluge || type == Aria2;
}
}

2
lib/src/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java

@ -469,7 +469,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -469,7 +469,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
if (in.length() >= 3) {
String part1 = in.substring(0, in.length() - 3);
String part2 = in.substring(in.length() - 3);
return part1.replace("Ê", "").replace(" ", "").replace(",", "").replace(".", "") + part2.replace(",", ".");
return part1.replace("Ê", "").replace(" ", "").replace(",", "").replace(".", "") + part2.replace(",", ".");
}
return in.replace(",", ".");
}

4
lite/AndroidManifest.xml

@ -18,8 +18,8 @@ @@ -18,8 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.transdroid.lite"
android:versionCode="215"
android:versionName="2.2.0" >
android:versionCode="216"
android:versionName="2.3.0" >
<uses-sdk
android:minSdkVersion="15"

Loading…
Cancel
Save