using json string during aidl call for better compatibility

added option to fail directly for network issues
This commit is contained in:
Mariotaku Lee 2016-02-27 03:42:47 +08:00
parent dce1b65915
commit 43af801b6c
19 changed files with 160 additions and 52 deletions

View File

@ -18,16 +18,10 @@
*/ */
package org.mariotaku.twidere; package org.mariotaku.twidere;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.StatusShortenResult;
interface IStatusShortener { interface IStatusShortener {
StatusShortenResult shorten(in ParcelableStatusUpdate status,in ParcelableAccount currentAccount, String shorten(String statusJson, long currentAccountId, String overrideStatusText);
String overrideStatusText);
boolean callback(in StatusShortenResult result, in ParcelableStatus status); boolean callback(String resultJson, String statusJson);
} }

View File

@ -231,6 +231,8 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
String METADATA_KEY_EXTENSION_SETTINGS = "org.mariotaku.twidere.extension.settings"; String METADATA_KEY_EXTENSION_SETTINGS = "org.mariotaku.twidere.extension.settings";
String METADATA_KEY_EXTENSION_ICON = "org.mariotaku.twidere.extension.icon"; String METADATA_KEY_EXTENSION_ICON = "org.mariotaku.twidere.extension.icon";
String METADATA_KEY_EXTENSION_USE_JSON = "org.mariotaku.twidere.extension.use_json"; String METADATA_KEY_EXTENSION_USE_JSON = "org.mariotaku.twidere.extension.use_json";
String METADATA_KEY_EXTENSION_VERSION_STATUS_SHORTENER = "org.mariotaku.twidere.extension.version.status_shortener";
String METADATA_KEY_EXTENSION_VERSION_MEDIA_UPLOADER = "org.mariotaku.twidere.extension.version.media_uploader";
char SEPARATOR_PERMISSION = '|'; char SEPARATOR_PERMISSION = '|';
String SEPARATOR_PERMISSION_REGEX = "\\" + SEPARATOR_PERMISSION; String SEPARATOR_PERMISSION_REGEX = "\\" + SEPARATOR_PERMISSION;

View File

@ -302,6 +302,8 @@ public interface SharedPreferenceConstants {
String KEY_API_LAST_CHANGE = "api_last_change"; String KEY_API_LAST_CHANGE = "api_last_change";
@Preference(type = LONG, exportable = false) @Preference(type = LONG, exportable = false)
String KEY_DEFAULT_ACCOUNT_ID = "default_account_id"; String KEY_DEFAULT_ACCOUNT_ID = "default_account_id";
@Preference(type = BOOLEAN, exportable = true, defaultBoolean = true)
String KEY_RETRY_ON_NETWORK_ISSUE = "retry_on_network_issue";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false) @Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="status_shortener_service_interface_version">2</string>
<string name="media_uploader_service_interface_version">2</string>
</resources>

View File

@ -39,7 +39,7 @@ android {
dependencies { dependencies {
apt 'com.bluelinelabs:logansquare-compiler:1.3.4' apt 'com.bluelinelabs:logansquare-compiler:1.3.4'
compile 'com.github.mariotaku.RestFu:urlconnection:0.9.23' compile 'com.github.mariotaku.RestFu:urlconnection:0.9.24'
compile project(':twidere.library.extension') compile project(':twidere.library.extension')
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
} }

View File

@ -50,6 +50,11 @@
<service <service
android:name=".GistStatusShortenerService" android:name=".GistStatusShortenerService"
android:permission="org.mariotaku.twidere.permission.SHORTEN_STATUS"> android:permission="org.mariotaku.twidere.permission.SHORTEN_STATUS">
<meta-data
android:name="org.mariotaku.twidere.extension.version.status_shortener"
android:value="@string/status_shortener_service_interface_version"/>
<intent-filter> <intent-filter>
<action android:name="org.mariotaku.twidere.EXTENSION_SHORTEN_STATUS"/> <action android:name="org.mariotaku.twidere.EXTENSION_SHORTEN_STATUS"/>

View File

@ -34,7 +34,7 @@ import org.mariotaku.twidere.service.StatusShortenerService;
public class GistStatusShortenerService extends StatusShortenerService { public class GistStatusShortenerService extends StatusShortenerService {
@Override @Override
protected StatusShortenResult shorten(ParcelableStatusUpdate status, ParcelableAccount currentAccount, String overrideStatusText) { protected StatusShortenResult shorten(ParcelableStatusUpdate status, long currentAccountId, String overrideStatusText) {
final Github github = GithubFactory.getInstance(getApiKey()); final Github github = GithubFactory.getInstance(getApiKey());
final NewGist newGist = new NewGist(); final NewGist newGist = new NewGist();
newGist.setDescription("long tweet"); newGist.setDescription("long tweet");

View File

@ -38,7 +38,7 @@ android {
dependencies { dependencies {
apt 'com.bluelinelabs:logansquare-compiler:1.3.4' apt 'com.bluelinelabs:logansquare-compiler:1.3.4'
compile 'com.github.mariotaku.RestFu:urlconnection:0.9.23' compile 'com.github.mariotaku.RestFu:urlconnection:0.9.24'
compile project(':twidere.library.extension') compile project(':twidere.library.extension')
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
} }

View File

@ -73,6 +73,11 @@
<service <service
android:name=".TwitLongerStatusShortenerService" android:name=".TwitLongerStatusShortenerService"
android:permission="org.mariotaku.twidere.permission.SHORTEN_STATUS"> android:permission="org.mariotaku.twidere.permission.SHORTEN_STATUS">
<meta-data
android:name="org.mariotaku.twidere.extension.version.status_shortener"
android:value="@string/status_shortener_service_interface_version"/>
<intent-filter> <intent-filter>
<action android:name="org.mariotaku.twidere.EXTENSION_SHORTEN_STATUS"/> <action android:name="org.mariotaku.twidere.EXTENSION_SHORTEN_STATUS"/>

View File

@ -9,7 +9,6 @@ import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import org.mariotaku.twidere.Twidere; import org.mariotaku.twidere.Twidere;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials; import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate; import org.mariotaku.twidere.model.ParcelableStatusUpdate;
@ -31,7 +30,7 @@ public class TwitLongerStatusShortenerService extends StatusShortenerService imp
*/ */
@Override @Override
protected StatusShortenResult shorten(final ParcelableStatusUpdate status, protected StatusShortenResult shorten(final ParcelableStatusUpdate status,
final ParcelableAccount currentAccount, final long currentAccountId,
final String overrideStatusText) { final String overrideStatusText) {
final int granted = Twidere.isPermissionGranted(this); final int granted = Twidere.isPermissionGranted(this);
if (granted == Twidere.Permission.DENIED) { if (granted == Twidere.Permission.DENIED) {
@ -57,7 +56,7 @@ public class TwitLongerStatusShortenerService extends StatusShortenerService imp
} }
final ParcelableCredentials credentials; final ParcelableCredentials credentials;
try { try {
credentials = getOAuthCredentials(currentAccount.account_id); credentials = getOAuthCredentials(currentAccountId);
} catch (SecurityException e) { } catch (SecurityException e) {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e); Log.w(LOGTAG, e);

View File

@ -2,15 +2,17 @@ package org.mariotaku.twidere.service;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import org.mariotaku.twidere.IStatusShortener; import org.mariotaku.twidere.IStatusShortener;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate; import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.StatusShortenResult; import org.mariotaku.twidere.model.StatusShortenResult;
import org.mariotaku.twidere.util.LoganSquareMapperFinder;
import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
/** /**
@ -24,7 +26,7 @@ public abstract class StatusShortenerService extends Service {
} }
protected abstract StatusShortenResult shorten(ParcelableStatusUpdate status, protected abstract StatusShortenResult shorten(ParcelableStatusUpdate status,
ParcelableAccount currentAccount, long currentAccountId,
String overrideStatusText); String overrideStatusText);
protected abstract boolean callback(StatusShortenResult result, ParcelableStatus status); protected abstract boolean callback(StatusShortenResult result, ParcelableStatus status);
@ -43,16 +45,38 @@ public abstract class StatusShortenerService extends Service {
} }
@Override @Override
public StatusShortenResult shorten(final ParcelableStatusUpdate status, public String shorten(final String statusJson, final long currentAccountId,
final ParcelableAccount currentAccount, final String overrideStatusText)
final String overrideStatusText)
throws RemoteException { throws RemoteException {
return mService.get().shorten(status, currentAccount, overrideStatusText); try {
final ParcelableStatusUpdate statusUpdate = LoganSquareMapperFinder.mapperFor(ParcelableStatusUpdate.class)
.parse(statusJson);
final StatusShortenResult shorten = mService.get().shorten(statusUpdate, currentAccountId, overrideStatusText);
return LoganSquareMapperFinder.mapperFor(StatusShortenResult.class).serialize(shorten);
} catch (IOException e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
throw new RemoteException(e.getMessage());
} else {
throw new RemoteException();
}
}
} }
@Override @Override
public boolean callback(StatusShortenResult result, ParcelableStatus status) throws RemoteException { public boolean callback(String resultJson, String statusJson) throws RemoteException {
return mService.get().callback(result, status); try {
final StatusShortenResult result = LoganSquareMapperFinder.mapperFor(StatusShortenResult.class)
.parse(resultJson);
final ParcelableStatus status = LoganSquareMapperFinder.mapperFor(ParcelableStatus.class)
.parse(statusJson);
return mService.get().callback(result, status);
} catch (IOException e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
throw new RemoteException(e.getMessage());
} else {
throw new RemoteException();
}
}
} }
} }

View File

@ -212,17 +212,19 @@ public class TwidereApplication extends MultiDexApplication implements Constants
break; break;
} }
case KEY_ENABLE_PROXY: case KEY_ENABLE_PROXY:
case KEY_CONNECTION_TIMEOUT:
case KEY_PROXY_HOST: case KEY_PROXY_HOST:
case KEY_PROXY_PORT: case KEY_PROXY_PORT:
case KEY_PROXY_TYPE: case KEY_PROXY_TYPE:
case KEY_PROXY_USERNAME: case KEY_PROXY_USERNAME:
case KEY_PROXY_PASSWORD: { case KEY_PROXY_PASSWORD:
case KEY_CONNECTION_TIMEOUT:
case KEY_RETRY_ON_NETWORK_ISSUE: {
HttpClientFactory.reloadConnectivitySettings(this); HttpClientFactory.reloadConnectivitySettings(this);
break; break;
} }
case KEY_DNS_SERVER: case KEY_DNS_SERVER:
case KEY_TCP_DNS_QUERY: { case KEY_TCP_DNS_QUERY:
case KEY_BUILTIN_DNS_RESOLVER: {
reloadDnsSettings(); reloadDnsSettings();
break; break;
} }

View File

@ -30,9 +30,11 @@ import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Parcelable; import android.os.Parcelable;
import android.provider.BaseColumns; import android.provider.BaseColumns;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.app.NotificationCompat.Builder;
import android.text.TextUtils; import android.text.TextUtils;
@ -84,6 +86,7 @@ import org.mariotaku.twidere.preference.ServicePickerPreference;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags; import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages; import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts; import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.util.AbsServiceInterface;
import org.mariotaku.twidere.util.AsyncTwitterWrapper; import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.BitmapUtils; import org.mariotaku.twidere.util.BitmapUtils;
import org.mariotaku.twidere.util.ContentValuesCreator; import org.mariotaku.twidere.util.ContentValuesCreator;
@ -519,6 +522,23 @@ public class BackgroundOperationService extends IntentService implements Constan
if (!ServicePickerPreference.isNoneValue(shortenerComponent)) { if (!ServicePickerPreference.isNoneValue(shortenerComponent)) {
shortener = StatusShortenerInterface.getInstance(app, shortenerComponent); shortener = StatusShortenerInterface.getInstance(app, shortenerComponent);
if (shortener == null) throw new ShortenerNotFoundException(this); if (shortener == null) throw new ShortenerNotFoundException(this);
try {
shortener.checkService(new AbsServiceInterface.CheckServiceAction() {
@Override
public void check(@Nullable Bundle metaData) throws AbsServiceInterface.CheckServiceException {
if (metaData == null) throw new ExtensionVersionMismatchException();
final String extensionVersion = metaData.getString(METADATA_KEY_EXTENSION_VERSION_STATUS_SHORTENER);
if (!TextUtils.equals(extensionVersion, getString(R.string.status_shortener_service_interface_version))) {
throw new ExtensionVersionMismatchException();
}
}
});
} catch (AbsServiceInterface.CheckServiceException e) {
if (e instanceof ExtensionVersionMismatchException) {
throw new ShortenException(getString(R.string.shortener_version_incompatible));
}
throw new ShortenException(e);
}
} }
final boolean hasMedia = statusUpdate.media != null && statusUpdate.media.length > 0; final boolean hasMedia = statusUpdate.media != null && statusUpdate.media.length > 0;
@ -581,7 +601,8 @@ public class BackgroundOperationService extends IntentService implements Constan
StatusShortenResult shortenedResult = null; StatusShortenResult shortenedResult = null;
if (shouldShorten && shortener != null) { if (shouldShorten && shortener != null) {
try { try {
shortenedResult = shortener.shorten(statusUpdate, account, statusText); shortenedResult = shortener.shorten(statusUpdate, account.account_id,
statusText);
} catch (final Exception e) { } catch (final Exception e) {
throw new ShortenException(getString(R.string.error_message_tweet_shorten_failed), e); throw new ShortenException(getString(R.string.error_message_tweet_shorten_failed), e);
} }
@ -910,4 +931,8 @@ public class BackgroundOperationService extends IntentService implements Constan
super(message); super(message);
} }
} }
static class ExtensionVersionMismatchException extends AbsServiceInterface.CheckServiceException {
}
} }

View File

@ -23,8 +23,10 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.IInterface; import android.os.IInterface;
import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.Constants;
@ -37,6 +39,8 @@ public abstract class AbsServiceInterface<I extends IInterface> implements Const
private final Context mContext; private final Context mContext;
private final String mShortenerName; private final String mShortenerName;
@Nullable
private final Bundle mMetaData;
private I mIInterface; private I mIInterface;
private ServiceToken mToken; private ServiceToken mToken;
@ -56,9 +60,10 @@ public abstract class AbsServiceInterface<I extends IInterface> implements Const
protected abstract I onServiceConnected(ComponentName service, IBinder obj); protected abstract I onServiceConnected(ComponentName service, IBinder obj);
protected AbsServiceInterface(final Context context, final String shortenerName) { protected AbsServiceInterface(final Context context, final String componentName, @Nullable final Bundle metaData) {
mContext = context; mContext = context;
mShortenerName = shortenerName; mShortenerName = componentName;
mMetaData = metaData;
} }
public final I getInterface() { public final I getInterface() {
@ -89,4 +94,15 @@ public abstract class AbsServiceInterface<I extends IInterface> implements Const
} }
} }
public final void checkService(CheckServiceAction action) throws CheckServiceException {
action.check(mMetaData);
}
public interface CheckServiceAction {
void check(@Nullable Bundle metaData) throws CheckServiceException;
}
public static class CheckServiceException extends Exception {
}
} }

View File

@ -2,7 +2,6 @@ package org.mariotaku.twidere.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils; import android.text.TextUtils;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
@ -10,9 +9,11 @@ import org.mariotaku.restfu.http.RestHttpClient;
import org.mariotaku.restfu.okhttp3.OkHttpRestClient; import org.mariotaku.restfu.okhttp3.OkHttpRestClient;
import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.util.dagger.DependencyHolder; import org.mariotaku.twidere.util.dagger.DependencyHolder;
import org.mariotaku.twidere.util.net.TwidereDns;
import org.mariotaku.twidere.util.net.TwidereProxySelector; import org.mariotaku.twidere.util.net.TwidereProxySelector;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy; import java.net.Proxy;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -33,14 +34,14 @@ import static android.text.TextUtils.isEmpty;
public class HttpClientFactory implements Constants { public class HttpClientFactory implements Constants {
public static RestHttpClient createRestHttpClient(final Context context, public static RestHttpClient createRestHttpClient(final Context context,
final SharedPreferences prefs, final Dns dns, final SharedPreferencesWrapper prefs, final Dns dns,
final ConnectionPool connectionPool) { final ConnectionPool connectionPool) {
final OkHttpClient.Builder builder = new OkHttpClient.Builder(); final OkHttpClient.Builder builder = new OkHttpClient.Builder();
initOkHttpClient(context, prefs, builder, dns, connectionPool); initOkHttpClient(context, prefs, builder, dns, connectionPool);
return new OkHttpRestClient(builder.build()); return new OkHttpRestClient(builder.build());
} }
public static void initOkHttpClient(final Context context, final SharedPreferences prefs, public static void initOkHttpClient(final Context context, final SharedPreferencesWrapper prefs,
final OkHttpClient.Builder builder, final Dns dns, final OkHttpClient.Builder builder, final Dns dns,
final ConnectionPool connectionPool) { final ConnectionPool connectionPool) {
updateHttpClientConfiguration(context, builder, prefs, dns, connectionPool); updateHttpClientConfiguration(context, builder, prefs, dns, connectionPool);
@ -50,11 +51,11 @@ public class HttpClientFactory implements Constants {
@SuppressLint("SSLCertificateSocketFactoryGetInsecure") @SuppressLint("SSLCertificateSocketFactoryGetInsecure")
public static void updateHttpClientConfiguration(final Context context, public static void updateHttpClientConfiguration(final Context context,
final OkHttpClient.Builder builder, final OkHttpClient.Builder builder,
final SharedPreferences prefs, final Dns dns, final SharedPreferencesWrapper prefs, final Dns dns,
final ConnectionPool connectionPool) { final ConnectionPool connectionPool) {
final boolean enableProxy = prefs.getBoolean(KEY_ENABLE_PROXY, false); final boolean enableProxy = prefs.getBoolean(KEY_ENABLE_PROXY, false);
builder.connectTimeout(prefs.getInt(KEY_CONNECTION_TIMEOUT, 10), TimeUnit.SECONDS); builder.connectTimeout(prefs.getInt(KEY_CONNECTION_TIMEOUT, 10), TimeUnit.SECONDS);
builder.retryOnConnectionFailure(true); builder.retryOnConnectionFailure(prefs.getBoolean(KEY_RETRY_ON_NETWORK_ISSUE));
builder.connectionPool(connectionPool); builder.connectionPool(connectionPool);
if (enableProxy) { if (enableProxy) {
final String proxyType = prefs.getString(KEY_PROXY_TYPE, null); final String proxyType = prefs.getString(KEY_PROXY_TYPE, null);
@ -64,7 +65,11 @@ public class HttpClientFactory implements Constants {
TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE)) { TwidereMathUtils.RANGE_INCLUSIVE_INCLUSIVE)) {
final Proxy.Type type = getProxyType(proxyType); final Proxy.Type type = getProxyType(proxyType);
if (type != Proxy.Type.DIRECT) { if (type != Proxy.Type.DIRECT) {
builder.proxySelector(new TwidereProxySelector(context, type, proxyHost, proxyPort)); if (TwidereDns.isValidIpAddress(proxyHost)) {
builder.proxy(new Proxy(type, InetSocketAddress.createUnresolved(proxyHost, proxyPort)));
} else {
builder.proxySelector(new TwidereProxySelector(context, type, proxyHost, proxyPort));
}
} }
} }
final String username = prefs.getString(KEY_PROXY_USERNAME, null); final String username = prefs.getString(KEY_PROXY_USERNAME, null);

View File

@ -23,6 +23,9 @@ import android.app.Application;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
@ -32,9 +35,11 @@ import org.mariotaku.twidere.model.MediaUploadResult;
import org.mariotaku.twidere.model.ParcelableStatusUpdate; import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.UploaderMediaItem; import org.mariotaku.twidere.model.UploaderMediaItem;
import java.util.List;
public final class MediaUploaderInterface extends AbsServiceInterface<IMediaUploader> implements IMediaUploader { public final class MediaUploaderInterface extends AbsServiceInterface<IMediaUploader> implements IMediaUploader {
protected MediaUploaderInterface(Context context, String shortenerName) { protected MediaUploaderInterface(Context context, String uploaderName, Bundle metaData) {
super(context, shortenerName); super(context, uploaderName, metaData);
} }
public static MediaUploaderInterface getInstance(final Application application, final String uploaderName) { public static MediaUploaderInterface getInstance(final Application application, final String uploaderName) {
@ -42,8 +47,10 @@ public final class MediaUploaderInterface extends AbsServiceInterface<IMediaUplo
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_UPLOAD_MEDIA); final Intent intent = new Intent(INTENT_ACTION_EXTENSION_UPLOAD_MEDIA);
final ComponentName component = ComponentName.unflattenFromString(uploaderName); final ComponentName component = ComponentName.unflattenFromString(uploaderName);
intent.setComponent(component); intent.setComponent(component);
if (application.getPackageManager().queryIntentServices(intent, 0).size() != 1) return null; final PackageManager pm = application.getPackageManager();
return new MediaUploaderInterface(application, uploaderName); final List<ResolveInfo> services = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
if (services.size() != 1) return null;
return new MediaUploaderInterface(application, uploaderName, services.get(0).serviceInfo.metaData);
} }
@Override @Override

View File

@ -23,19 +23,23 @@ import android.app.Application;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import org.mariotaku.twidere.IStatusShortener; import org.mariotaku.twidere.IStatusShortener;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate; import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.StatusShortenResult; import org.mariotaku.twidere.model.StatusShortenResult;
public final class StatusShortenerInterface extends AbsServiceInterface<IStatusShortener> implements IStatusShortener { import java.util.List;
protected StatusShortenerInterface(Context context, String shortenerName) { public final class StatusShortenerInterface extends AbsServiceInterface<IStatusShortener> {
super(context, shortenerName);
protected StatusShortenerInterface(Context context, String shortenerName, Bundle metaData) {
super(context, shortenerName, metaData);
} }
@Override @Override
@ -43,37 +47,41 @@ public final class StatusShortenerInterface extends AbsServiceInterface<IStatusS
return IStatusShortener.Stub.asInterface(obj); return IStatusShortener.Stub.asInterface(obj);
} }
@Override
public StatusShortenResult shorten(final ParcelableStatusUpdate status, public StatusShortenResult shorten(final ParcelableStatusUpdate status,
final ParcelableAccount currentAccount, final long currentAccountId,
final String overrideStatusText) { final String overrideStatusText) {
final IStatusShortener iface = getInterface(); final IStatusShortener iface = getInterface();
if (iface == null) return null; if (iface == null) return null;
try { try {
return iface.shorten(status, currentAccount, overrideStatusText); final String statusJson = JsonSerializer.serialize(status, ParcelableStatusUpdate.class);
final String resultJson = iface.shorten(statusJson, currentAccountId, overrideStatusText);
return JsonSerializer.parse(resultJson, StatusShortenResult.class);
} catch (final RemoteException e) { } catch (final RemoteException e) {
return null; return null;
} }
} }
@Override
public boolean callback(StatusShortenResult result, ParcelableStatus status) { public boolean callback(StatusShortenResult result, ParcelableStatus status) {
final IStatusShortener iface = getInterface(); final IStatusShortener iface = getInterface();
if (iface == null) return false; if (iface == null) return false;
try { try {
return iface.callback(result, status); final String resultJson = JsonSerializer.serialize(result, StatusShortenResult.class);
final String statusJson = JsonSerializer.serialize(status, ParcelableStatus.class);
return iface.callback(resultJson, statusJson);
} catch (final RemoteException e) { } catch (final RemoteException e) {
return false; return false;
} }
} }
public static StatusShortenerInterface getInstance(final Application application, final String shortener_name) { public static StatusShortenerInterface getInstance(final Application application, final String shortenerName) {
if (shortener_name == null) return null; if (shortenerName == null) return null;
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_SHORTEN_STATUS); final Intent intent = new Intent(INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
final ComponentName component = ComponentName.unflattenFromString(shortener_name); final ComponentName component = ComponentName.unflattenFromString(shortenerName);
intent.setComponent(component); intent.setComponent(component);
if (application.getPackageManager().queryIntentServices(intent, 0).size() != 1) return null; final PackageManager pm = application.getPackageManager();
return new StatusShortenerInterface(application, shortener_name); final List<ResolveInfo> services = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
if (services.size() != 1) return null;
return new StatusShortenerInterface(application, shortenerName, services.get(0).serviceInfo.metaData);
} }
} }

View File

@ -742,6 +742,8 @@
<string name="action_start">Start</string> <string name="action_start">Start</string>
<string name="builtin_dns_resolver">Builtin DNS resolver</string> <string name="builtin_dns_resolver">Builtin DNS resolver</string>
<string name="bandwidth_saving_mode">Bandwidth saving mode</string> <string name="bandwidth_saving_mode">Bandwidth saving mode</string>
<string name="retry_on_network_issue">Retry on network issue</string>
<string name="retry_on_network_issue_summary">Try recover from network issue automatically</string>
<string name="bandwidth_saving_mode_summary">Disable media preview on metered network</string> <string name="bandwidth_saving_mode_summary">Disable media preview on metered network</string>
<string name="recent_media">Recent media</string> <string name="recent_media">Recent media</string>
<string name="reply_to_name_text">Reply to <xliff:g id="name">%1$s</xliff:g>: <xliff:g id="text">%2$s</xliff:g></string> <string name="reply_to_name_text">Reply to <xliff:g id="name">%1$s</xliff:g>: <xliff:g id="text">%2$s</xliff:g></string>
@ -750,4 +752,5 @@
<string name="status_menu_title_format"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="text">%2$s</xliff:g></string> <string name="status_menu_title_format"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="text">%2$s</xliff:g></string>
<string name="translate_from_language">Translate from <xliff:g id="language">%s</xliff:g></string> <string name="translate_from_language">Translate from <xliff:g id="language">%s</xliff:g></string>
<string name="translation">Translation</string> <string name="translation">Translation</string>
<string name="shortener_version_incompatible">Incompatible shortener</string>
</resources> </resources>

View File

@ -33,6 +33,12 @@
android:key="custom_host_mapping" android:key="custom_host_mapping"
android:summary="@string/custom_host_mapping_summary" android:summary="@string/custom_host_mapping_summary"
android:title="@string/custom_host_mapping"/> android:title="@string/custom_host_mapping"/>
<org.mariotaku.twidere.preference.AutoFixSwitchPreference
android:defaultValue="true"
android:key="retry_on_network_issue"
android:summary="@string/retry_on_network_issue_summary"
android:title="@string/retry_on_network_issue"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:key="category_proxy" android:key="category_proxy"