diff --git a/global.gradle b/global.gradle index 9ce8a3d44..feeba163e 100644 --- a/global.gradle +++ b/global.gradle @@ -23,4 +23,15 @@ android { lintOptions { abortOnError false } + + packagingOptions { + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/LICENSE' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/license.txt' + exclude 'META-INF/NOTICE' + exclude 'META-INF/NOTICE.txt' + exclude 'META-INF/notice.txt' + exclude 'META-INF/ASL2.0' + } } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 405d6e9b2..8850e4395 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,6 +7,5 @@ include ':twidere.donate.nyanwp' include ':twidere.donate.nyanwp.wear' include ':twidere.component.nyan' include ':twidere.extension.twitlonger' -include ':twidere.extension.streaming' include ':twidere.extension.push.xiaomi' include ':twidere.extension.launcher.compose' \ No newline at end of file diff --git a/twidere.component.common/build.gradle b/twidere.component.common/build.gradle index fd3059a10..41c053e6e 100644 --- a/twidere.component.common/build.gradle +++ b/twidere.component.common/build.gradle @@ -45,7 +45,6 @@ dependencies { compile 'org.apache.commons:commons-lang3:3.4' compile 'com.github.mariotaku:RestFu:6ef0913' compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1' - compile 'com.fasterxml.jackson.core:jackson-databind:2.4.4' compile project(':twidere.component.querybuilder') compile fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java index 4ee094f56..36f609c3a 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java @@ -189,6 +189,8 @@ public interface SharedPreferenceConstants { String KEY_MENTIONS_NOTIFICATION = "mentions_notification"; @Preference(type = BOOLEAN) String KEY_DIRECT_MESSAGES_NOTIFICATION = "direct_messages_notification"; + @Preference(type = BOOLEAN) + String KEY_ENABLE_STREAMING = "enable_streaming"; @Preference(type = INT) String KEY_LOCAL_TRENDS_WOEID = "local_trends_woeid"; String KEY_NOTIFICATION_RINGTONE = "notification_ringtone"; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserMention.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserMention.java index d782dd852..0c154b4cd 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserMention.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserMention.java @@ -26,14 +26,17 @@ import android.text.TextUtils; import com.bluelinelabs.logansquare.LoganSquare; import com.bluelinelabs.logansquare.annotation.JsonField; import com.bluelinelabs.logansquare.annotation.JsonObject; - -import java.io.IOException; -import java.util.List; +import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease; +import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease; import org.mariotaku.twidere.api.twitter.model.Status; import org.mariotaku.twidere.api.twitter.model.UserMentionEntity; +import java.io.IOException; +import java.util.List; + @JsonObject +@ParcelablePlease(allFields = false) public class ParcelableUserMention implements Parcelable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -48,10 +51,13 @@ public class ParcelableUserMention implements Parcelable { } }; + @ParcelableThisPlease @JsonField(name = "id") public long id; + @ParcelableThisPlease @JsonField(name = "name") public String name; + @ParcelableThisPlease @JsonField(name = "screen_name") public String screen_name; @@ -87,8 +93,15 @@ public class ParcelableUserMention implements Parcelable { } public static ParcelableUserMention[] fromSerializedJson(String string) { - - return new ParcelableUserMention[0]; + if (string == null) return null; + final List list; + try { + list = LoganSquare.parseList(string, ParcelableUserMention.class); + } catch (IOException e) { + return null; + } + if (list == null) return null; + return list.toArray(new ParcelableUserMention[list.size()]); } @Override diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/TwitterAPIUtils.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/util/TwitterAPIUtils.java deleted file mode 100644 index aab082f89..000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/TwitterAPIUtils.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2015 Mariotaku Lee - * - * This program 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. - * - * This program 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 this program. If not, see . - */ - -package org.mariotaku.twidere.util; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.util.Pair; - -import org.mariotaku.restfu.ExceptionFactory; -import org.mariotaku.restfu.HttpRequestFactory; -import org.mariotaku.restfu.RequestInfoFactory; -import org.mariotaku.restfu.RestMethodInfo; -import org.mariotaku.restfu.RestRequestInfo; -import org.mariotaku.restfu.annotation.RestMethod; -import org.mariotaku.restfu.http.Authorization; -import org.mariotaku.restfu.http.Endpoint; -import org.mariotaku.restfu.http.FileValue; -import org.mariotaku.restfu.http.RestHttpRequest; -import org.mariotaku.restfu.http.RestHttpResponse; -import org.mariotaku.restfu.http.mime.StringTypedData; -import org.mariotaku.restfu.http.mime.TypedData; -import org.mariotaku.twidere.TwidereConstants; -import org.mariotaku.twidere.api.twitter.Twitter; -import org.mariotaku.twidere.api.twitter.TwitterException; -import org.mariotaku.twidere.api.twitter.TwitterOAuth; -import org.mariotaku.twidere.api.twitter.TwitterUpload; -import org.mariotaku.twidere.api.twitter.TwitterUserStream; -import org.mariotaku.twidere.api.twitter.auth.BasicAuthorization; -import org.mariotaku.twidere.api.twitter.auth.EmptyAuthorization; -import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization; -import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint; -import org.mariotaku.twidere.api.twitter.auth.OAuthToken; -import org.mariotaku.twidere.api.twitter.util.TwitterConverter; -import org.mariotaku.twidere.model.ConsumerKeyType; -import org.mariotaku.twidere.model.ParcelableCredentials; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static android.text.TextUtils.isEmpty; - -/** - * Created by mariotaku on 15/5/26. - */ -public class TwitterAPIUtils implements TwidereConstants { - - public static Endpoint getEndpoint(ParcelableCredentials credentials, Class cls) { - final String apiUrlFormat; - final boolean sameOAuthSigningUrl = credentials.same_oauth_signing_url; - final boolean noVersionSuffix = credentials.no_version_suffix; - if (!isEmpty(credentials.api_url_format)) { - apiUrlFormat = credentials.api_url_format; - } else { - apiUrlFormat = DEFAULT_TWITTER_API_URL_FORMAT; - } - final String domain, versionSuffix; - if (Twitter.class.isAssignableFrom(cls)) { - domain = "api"; - versionSuffix = noVersionSuffix ? null : "/1.1/"; - } else if (TwitterUpload.class.isAssignableFrom(cls)) { - domain = "upload"; - versionSuffix = noVersionSuffix ? null : "/1.1/"; - } else if (TwitterOAuth.class.isAssignableFrom(cls)) { - domain = "api"; - versionSuffix = "oauth"; - } else if (TwitterUserStream.class.isAssignableFrom(cls)) { - domain = "userstream"; - versionSuffix = noVersionSuffix ? null : "/1.1/"; - } else { - throw new TwitterConverter.UnsupportedTypeException(cls); - } - final String endpointUrl; - endpointUrl = getApiUrl(apiUrlFormat, domain, versionSuffix); - if (credentials.auth_type == ParcelableCredentials.AUTH_TYPE_XAUTH || credentials.auth_type == ParcelableCredentials.AUTH_TYPE_OAUTH) { - final String signEndpointUrl; - if (!sameOAuthSigningUrl) { - signEndpointUrl = getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix); - } else { - signEndpointUrl = endpointUrl; - } - return new OAuthEndpoint(endpointUrl, signEndpointUrl); - } - return new Endpoint(endpointUrl); - } - - public static Authorization getAuthorization(ParcelableCredentials credentials) { - switch (credentials.auth_type) { - case ParcelableCredentials.AUTH_TYPE_OAUTH: - case ParcelableCredentials.AUTH_TYPE_XAUTH: { - final String consumerKey = TextUtils.isEmpty(credentials.consumer_key) ? - TWITTER_CONSUMER_KEY_LEGACY : credentials.consumer_key; - final String consumerSecret = TextUtils.isEmpty(credentials.consumer_secret) ? - TWITTER_CONSUMER_SECRET_LEGACY : credentials.consumer_secret; - final OAuthToken accessToken = new OAuthToken(credentials.oauth_token, credentials.oauth_token_secret); - return new OAuthAuthorization(consumerKey, consumerSecret, accessToken); - } - case ParcelableCredentials.AUTH_TYPE_BASIC: { - final String screenName = credentials.screen_name; - final String username = credentials.basic_auth_username; - final String loginName = username != null ? username : screenName; - final String password = credentials.basic_auth_password; - if (isEmpty(loginName) || isEmpty(password)) return null; - return new BasicAuthorization(loginName, password); - } - } - return new EmptyAuthorization(); - } - - private static void addParameter(List> params, String name, Object value) { - params.add(Pair.create(name, String.valueOf(value))); - } - - private static void addPart(List> params, String name, Object value) { - final TypedData typedData = new StringTypedData(String.valueOf(value), Charset.defaultCharset()); - params.add(Pair.create(name, typedData)); - } - - public static String getApiBaseUrl(String format, final String domain) { - if (format == null) return null; - final Matcher matcher = Pattern.compile("\\[(\\.?)DOMAIN(\\.?)\\]").matcher(format); - if (!matcher.find()) { - // For backward compatibility - format = substituteLegacyApiBaseUrl(format, domain); - if (!format.endsWith("/1.1") && !format.endsWith("/1.1/")) { - return format; - } - final String versionSuffix = "/1.1"; - final int suffixLength = versionSuffix.length(); - final int lastIndex = format.lastIndexOf(versionSuffix); - return format.substring(0, lastIndex) + format.substring(lastIndex + suffixLength); - } - if (TextUtils.isEmpty(domain)) return matcher.replaceAll(""); - return matcher.replaceAll(String.format("$1%s$2", domain)); - } - - private static String substituteLegacyApiBaseUrl(@NonNull String format, String domain) { - final int startOfHost = format.indexOf("://") + 3, endOfHost = format.indexOf('/', startOfHost); - final String host = endOfHost != -1 ? format.substring(startOfHost, endOfHost) : format.substring(startOfHost); - if (!host.equalsIgnoreCase("api.twitter.com")) return format; - return format.substring(0, startOfHost) + domain + ".twitter.com" + format.substring(endOfHost); - } - - public static String getApiUrl(final String pattern, final String domain, final String appendPath) { - final String urlBase = getApiBaseUrl(pattern, domain); - if (urlBase == null) return null; - if (appendPath == null) return urlBase.endsWith("/") ? urlBase : urlBase + "/"; - final StringBuilder sb = new StringBuilder(urlBase); - if (urlBase.endsWith("/")) { - sb.append(appendPath.startsWith("/") ? appendPath.substring(1) : appendPath); - } else { - if (appendPath.startsWith("/")) { - sb.append(appendPath); - } else { - sb.append('/'); - sb.append(appendPath); - } - } - return sb.toString(); - } - - public static String getUserAgentName(ConsumerKeyType type) { - switch (type) { - case TWITTER_FOR_ANDROID: { - return "TwitterAndroid"; - } - case TWITTER_FOR_IPHONE: { - return "Twitter-iPhone"; - } - case TWITTER_FOR_IPAD: { - return "Twitter-iPad"; - } - case TWITTER_FOR_MAC: { - return "Twitter-Mac"; - } - } - return "Twitter"; - } - - public static String getTwidereUserAgent(final Context context) { - final PackageManager pm = context.getPackageManager(); - try { - final PackageInfo pi = pm.getPackageInfo(TWIDERE_PACKAGE_NAME, 0); - return TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL + " / " + pi.versionName; - } catch (final PackageManager.NameNotFoundException e) { - return TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL; - } - } - - public static class TwidereRequestInfoFactory implements RequestInfoFactory { - @Override - public RestRequestInfo create(RestMethodInfo methodInfo) { - final RestMethod method = methodInfo.getMethod(); - final String path = methodInfo.getPath(); - final List> queries = new ArrayList<>(methodInfo.getQueries()); - final List> forms = new ArrayList<>(methodInfo.getForms()); - final List> headers = methodInfo.getHeaders(); - final List> parts = methodInfo.getParts(); - final FileValue file = methodInfo.getFile(); - final Map extras = methodInfo.getExtras(); - if (parts.isEmpty()) { - final List> params = method.hasBody() ? forms : queries; - addParameter(params, "include_cards", true); - addParameter(params, "cards_platform", "Android-12"); - addParameter(params, "include_entities", true); - addParameter(params, "include_my_retweet", 1); - addParameter(params, "include_rts", 1); - addParameter(params, "include_reply_count", true); - addParameter(params, "include_descendent_reply_count", true); - } else { - addPart(parts, "include_cards", true); - addPart(parts, "cards_platform", "Android-12"); - addPart(parts, "include_entities", true); - addPart(parts, "include_my_retweet", 1); - addPart(parts, "include_rts", 1); - addPart(parts, "include_reply_count", true); - addPart(parts, "include_descendent_reply_count", true); - } - return new RestRequestInfo(method.value(), path, queries, forms, headers, parts, file, - methodInfo.getBody(), extras); - } - } - - public static class TwidereHttpRequestFactory implements HttpRequestFactory { - - private final String userAgent; - - public TwidereHttpRequestFactory(final String userAgent) { - this.userAgent = userAgent; - } - - @Override - public RestHttpRequest create(@NonNull Endpoint endpoint, @NonNull RestRequestInfo info, - @Nullable Authorization authorization) { - final String restMethod = info.getMethod(); - final String url = Endpoint.constructUrl(endpoint.getUrl(), info); - final ArrayList> headers = new ArrayList<>(info.getHeaders()); - - if (authorization != null && authorization.hasAuthorization()) { - headers.add(Pair.create("Authorization", authorization.getHeader(endpoint, info))); - } - headers.add(Pair.create("User-Agent", userAgent)); - return new RestHttpRequest(restMethod, url, headers, info.getBody(), null); - } - } - - public static class TwidereExceptionFactory implements ExceptionFactory { - @Override - public Exception newException(Throwable cause, RestHttpRequest request, RestHttpResponse response) { - final TwitterException te = new TwitterException(cause); - te.setResponse(response); - return te; - } - } -} diff --git a/twidere.extension.streaming/.gitignore b/twidere.extension.streaming/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/twidere.extension.streaming/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/twidere.extension.streaming/build.gradle b/twidere.extension.streaming/build.gradle deleted file mode 100644 index 003774997..000000000 --- a/twidere.extension.streaming/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2015 Mariotaku Lee - * - * This program 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. - * - * This program 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 this program. If not, see . - */ - -apply plugin: 'com.android.application' -apply from: rootProject.file('global.gradle') -apply from: rootProject.file('signing.gradle') - -android { - defaultConfig { - applicationId "org.mariotaku.twidere.extension.streaming" - minSdkVersion 14 - targetSdkVersion 22 - versionCode 14 - versionName "1.12 (0.3.0-dev)" - } - packagingOptions { - exclude 'META-INF/DEPENDENCIES' - exclude 'META-INF/LICENSE' - exclude 'META-INF/LICENSE.txt' - exclude 'META-INF/license.txt' - exclude 'META-INF/NOTICE' - exclude 'META-INF/NOTICE.txt' - exclude 'META-INF/notice.txt' - exclude 'META-INF/ASL2.0' - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } -} - -dependencies { - compile 'com.squareup.okhttp:okhttp:2.4.0' - compile project(':twidere.library.extension') - compile fileTree(dir: 'libs', include: ['*.jar']) -} diff --git a/twidere.extension.streaming/proguard-rules.pro b/twidere.extension.streaming/proguard-rules.pro deleted file mode 100644 index ee5b46f04..000000000 --- a/twidere.extension.streaming/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/mariotaku/Tools/android-sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/twidere.extension.streaming/src/main/AndroidManifest.xml b/twidere.extension.streaming/src/main/AndroidManifest.xml deleted file mode 100644 index 41c9021c6..000000000 --- a/twidere.extension.streaming/src/main/AndroidManifest.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/Constants.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/Constants.java deleted file mode 100644 index 49d5a4135..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/Constants.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.mariotaku.twidere.extension.streaming; - -import org.mariotaku.twidere.TwidereConstants; - -public interface Constants extends TwidereConstants { - - public static final String LOGTAG = "Twidere.Streaming"; - - public static final String PREFERENCE_KEY_ACCOUNT_IDS = "account_ids"; - public static final String PREFERENCE_KEY_ENABLE_STREAMING = "enable_streaming"; - -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/PrivateConstants.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/PrivateConstants.java deleted file mode 100644 index 02e0a8c29..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/PrivateConstants.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mariotaku.twidere.extension.streaming; - -public interface PrivateConstants { - - public static final String TWITTER_CONSUMER_KEY = "uAFVpMhBntJutfVj6abfA"; - public static final String TWITTER_CONSUMER_SECRET = "JARXkJTfxo0F8MyctYy9bUmrLISjo8vXAHsZHYuk2E"; - - public static final String MAPS_API_KEY_RELEASE = "0kjPwJOe_zwYjzGc9uYak7vhm_Sf3eob-2L3Xzw"; - public static final String MAPS_API_KEY_DEBUG = "0kjPwJOe_zwY9p6kT-kygu4mxwysyOOpfkaXqTA"; -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/SettingsActivity.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/SettingsActivity.java deleted file mode 100644 index d68626520..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/SettingsActivity.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.mariotaku.twidere.extension.streaming; - -import org.mariotaku.twidere.Twidere; - -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; - -public class SettingsActivity extends PreferenceActivity implements Constants, OnSharedPreferenceChangeListener { - - private static final int REQUEST_REQUEST_PERMISSIONS = 101; - private SharedPreferences mPreferences; - - @Override - public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) { - if (PREFERENCE_KEY_ENABLE_STREAMING.equals(key)) { - final Intent intent = new Intent(this, StreamingService.class); - if (preferences.getBoolean(key, true)) { - startService(intent); - } else { - stopService(intent); - } - } - } - - @Override - protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { - switch (requestCode) { - case REQUEST_REQUEST_PERMISSIONS: { - if (resultCode != RESULT_OK) { - finish(); - return; - } - } - } - super.onActivityResult(requestCode, resultCode, data); - } - - @SuppressWarnings("deprecation") - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - final boolean granted; - try { - granted = Twidere.isPermissionGranted(this); - } catch (final SecurityException e) { - // TODO show error - finish(); - return; - } - if (!granted) { - final Intent intent = new Intent(Twidere.INTENT_ACTION_REQUEST_PERMISSIONS); - intent.setPackage("org.mariotaku.twidere"); - try { - startActivityForResult(intent, REQUEST_REQUEST_PERMISSIONS); - } catch (final ActivityNotFoundException e) { - - } - } - mPreferences = PreferenceManager.getDefaultSharedPreferences(this); - addPreferencesFromResource(R.xml.settings); - mPreferences.registerOnSharedPreferenceChangeListener(this); - } - -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/TwidereLaunchReceiver.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/TwidereLaunchReceiver.java deleted file mode 100644 index b7bdcc8ac..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/TwidereLaunchReceiver.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.mariotaku.twidere.extension.streaming; - -import org.mariotaku.twidere.Twidere; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -public class TwidereLaunchReceiver extends BroadcastReceiver { - - @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - final Intent service_intent = new Intent(context, StreamingService.class); - if (Twidere.BROADCAST_HOME_ACTIVITY_ONCREATE.equals(action)) { - context.startService(service_intent); - } else if (Twidere.BROADCAST_HOME_ACTIVITY_ONDESTROY.equals(action)) { - context.stopService(service_intent); - } - } - -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/ActivityAccessor.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/ActivityAccessor.java deleted file mode 100644 index 6bfd747cb..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/ActivityAccessor.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012 Mariotaku Lee - * - * This program 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. - * - * This program 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 this program. If not, see . - */ - -package org.mariotaku.twidere.extension.streaming.util; - -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.Activity; -import android.os.Build; - -public final class ActivityAccessor { - - public static void onBackPressed(final Activity activity) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR) return; - OnBackPressedAccessor.onBackPressed(activity); - } - - public static void overridePendingTransition(final Activity activity, final int enter_anim, final int exit_anim) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR) return; - OverridePendingTransitionAccessor.overridePendingTransition(activity, enter_anim, exit_anim); - } - - public static void setHomeButtonEnabled(final Activity activity, final boolean enabled) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) return; - SetHomeButtonEnabledAccessor.setHomeButtonEnabled(activity, enabled); - } - - @TargetApi(Build.VERSION_CODES.ECLAIR) - private static class OnBackPressedAccessor { - - private static void onBackPressed(final Activity activity) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR) return; - activity.onBackPressed(); - } - } - - @TargetApi(Build.VERSION_CODES.ECLAIR) - private static class OverridePendingTransitionAccessor { - private static void overridePendingTransition(final Activity activity, final int enter_anim, final int exit_anim) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR) return; - activity.overridePendingTransition(enter_anim, exit_anim); - } - } - - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - private static class SetHomeButtonEnabledAccessor { - - private static void setHomeButtonEnabled(final Activity activity, final boolean enabled) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) return; - final ActionBar action_bar = activity.getActionBar(); - action_bar.setHomeButtonEnabled(enabled); - } - } -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/OkHttpRestClient.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/OkHttpRestClient.java deleted file mode 100644 index 69dc99409..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/OkHttpRestClient.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2015 Mariotaku Lee - * - * This program 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. - * - * This program 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 this program. If not, see . - */ - -package org.mariotaku.twidere.extension.streaming.util; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Pair; - -import com.squareup.okhttp.Call; -import com.squareup.okhttp.Headers; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; - -import org.mariotaku.restfu.Utils; -import org.mariotaku.restfu.http.ContentType; -import org.mariotaku.restfu.http.RestHttpClient; -import org.mariotaku.restfu.http.RestHttpRequest; -import org.mariotaku.restfu.http.RestHttpResponse; -import org.mariotaku.restfu.http.mime.TypedData; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import okio.BufferedSink; - -/** - * Created by mariotaku on 15/5/5. - */ -public class OkHttpRestClient implements RestHttpClient { - - private final OkHttpClient client; - - public OkHttpRestClient() { - this(new OkHttpClient()); - } - - public OkHttpRestClient(OkHttpClient client) { - this.client = client; - } - - @NonNull - @Override - public RestHttpResponse execute(RestHttpRequest restHttpRequest) throws IOException { - final Request.Builder builder = new Request.Builder(); - builder.method(restHttpRequest.getMethod(), RestToOkBody.wrap(restHttpRequest.getBody())); - builder.url(restHttpRequest.getUrl()); - final List> headers = restHttpRequest.getHeaders(); - if (headers != null) { - for (Pair header : headers) { - builder.addHeader(header.first, header.second); - } - } - final Call call = client.newCall(builder.build()); - return new OkRestHttpResponse(call.execute()); - } - - private static class RestToOkBody extends RequestBody { - private final TypedData body; - - public RestToOkBody(TypedData body) { - this.body = body; - } - - @Override - public MediaType contentType() { - final ContentType contentType = body.contentType(); - if (contentType == null) return null; - return MediaType.parse(contentType.toHeader()); - } - - @Override - public void writeTo(BufferedSink sink) throws IOException { - body.writeTo(sink.outputStream()); - } - - @Nullable - public static RequestBody wrap(@Nullable TypedData body) { - if (body == null) return null; - return new RestToOkBody(body); - } - } - - private static class OkRestHttpResponse extends RestHttpResponse { - private final Response response; - private TypedData body; - - public OkRestHttpResponse(Response response) { - this.response = response; - } - - @Override - public int getStatus() { - return response.code(); - } - - @Override - public List> getHeaders() { - final Headers headers = response.headers(); - final ArrayList> headersList = new ArrayList<>(); - for (int i = 0, j = headers.size(); i < j; i++) { - headersList.add(Pair.create(headers.name(i), headers.value(i))); - } - return headersList; - } - - @Override - public String getHeader(String name) { - return response.header(name); - } - - @Override - public String[] getHeaders(String name) { - final List values = response.headers(name); - return values.toArray(new String[values.size()]); - } - - @Override - public TypedData getBody() { - if (body != null) return body; - return body = new OkToRestBody(response.body()); - } - - @Override - public void close() throws IOException { - if (body != null) { - body.close(); - body = null; - } - } - } - - private static class OkToRestBody implements TypedData { - - private final ResponseBody body; - - public OkToRestBody(ResponseBody body) { - this.body = body; - } - - @Override - public ContentType contentType() { - final MediaType mediaType = body.contentType(); - if (mediaType == null) return null; - return ContentType.parse(mediaType.toString()); - } - - @Override - public String contentEncoding() { - return null; - } - - @Override - public long length() throws IOException { - return body.contentLength(); - } - - @Override - public void writeTo(@NonNull OutputStream os) throws IOException { - Utils.copyStream(stream(), os); - } - - @NonNull - @Override - public InputStream stream() throws IOException { - return body.byteStream(); - } - - @Override - public void close() throws IOException { - body.close(); - } - } -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/TwidereHostAddressResolver.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/TwidereHostAddressResolver.java deleted file mode 100644 index 6260fbe81..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/TwidereHostAddressResolver.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012 Mariotaku Lee - * - * This program 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. - * - * This program 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 this program. If not, see . - */ - -package org.mariotaku.twidere.extension.streaming.util; - -import android.content.Context; -import android.util.Log; - -import com.squareup.okhttp.internal.Network; - -import org.mariotaku.twidere.Twidere; -import org.mariotaku.twidere.extension.streaming.BuildConfig; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.LinkedHashMap; - -public class TwidereHostAddressResolver implements Network { - - private static final String RESOLVER_LOGTAG = "Twidere.Streaming.Host"; - private static TwidereHostAddressResolver sInstance; - - private final HostCache mHostCache = new HostCache(512); - private final Context mContext; - - public TwidereHostAddressResolver(final Context context) { - mContext = context; - } - - @Override - public InetAddress[] resolveInetAddresses(final String host) throws UnknownHostException { - if (host == null) return null; - // First, I'll try to load address cached. - final InetAddress[] cached = mHostCache.get(host); - if (cached != null) { - if (BuildConfig.DEBUG) { - Log.d(RESOLVER_LOGTAG, "Got cached " + Arrays.toString(cached)); - } - return cached; - } - final InetAddress[] resolved = Twidere.resolveHost(mContext, host); - mHostCache.put(host, resolved); - return resolved; - } - - public static Network getInstance(final Context context) { - if (sInstance != null) return sInstance; - return sInstance = new TwidereHostAddressResolver(context); - } - - private static class HostCache extends LinkedHashMap { - - private static final long serialVersionUID = -9216545511009449147L; - - HostCache(final int initialCapacity) { - super(initialCapacity); - } - - @Override - public InetAddress[] put(final String key, final InetAddress[] value) { - if (value == null) return null; - return super.put(key, value); - } - } -} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/Utils.java b/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/Utils.java deleted file mode 100644 index 1e526fb68..000000000 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/util/Utils.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.mariotaku.twidere.extension.streaming.util; - -import android.content.Context; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.net.SSLCertificateSocketFactory; - -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.internal.Internal; - -import org.mariotaku.restfu.RestAPIFactory; -import org.mariotaku.restfu.http.Authorization; -import org.mariotaku.restfu.http.Endpoint; -import org.mariotaku.restfu.http.RestHttpClient; -import org.mariotaku.twidere.Twidere; -import org.mariotaku.twidere.TwidereConstants; -import org.mariotaku.twidere.TwidereSharedPreferences; -import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization; -import org.mariotaku.twidere.api.twitter.util.TwitterConverter; -import org.mariotaku.twidere.model.ConsumerKeyType; -import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; -import org.mariotaku.twidere.util.ParseUtils; -import org.mariotaku.twidere.util.TwitterAPIUtils; -import org.mariotaku.twidere.util.TwitterContentUtils; - -import java.io.Closeable; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.SocketAddress; -import java.util.concurrent.TimeUnit; - -import static android.text.TextUtils.isEmpty; - -public class Utils implements TwidereConstants { - - - public static void closeSilently(Closeable closeable) { - if (closeable == null) return; - try { - closeable.close(); - } catch (IOException ignore) { - - } - } - - - - public static RestHttpClient getDefaultHttpClient(final Context context) { - if (context == null) return null; - final SharedPreferences prefs = Twidere.getSharedPreferences(context); - return createHttpClient(context, prefs); - } - - public static T getInstance(final Context context, final Endpoint endpoint, final Authorization auth, Class cls) { - final RestAPIFactory factory = new RestAPIFactory(); - final String userAgent; - if (auth instanceof OAuthAuthorization) { - final String consumerKey = ((OAuthAuthorization) auth).getConsumerKey(); - final String consumerSecret = ((OAuthAuthorization) auth).getConsumerSecret(); - final ConsumerKeyType officialKeyType = TwitterContentUtils.getOfficialKeyType(context, consumerKey, consumerSecret); - if (officialKeyType != ConsumerKeyType.UNKNOWN) { - userAgent = TwitterAPIUtils.getUserAgentName(officialKeyType); - } else { - userAgent = TwitterAPIUtils.getTwidereUserAgent(context); - } - } else { - userAgent = TwitterAPIUtils.getTwidereUserAgent(context); - } - factory.setClient(getDefaultHttpClient(context)); - factory.setConverter(new TwitterConverter()); - factory.setEndpoint(endpoint); - factory.setAuthorization(auth); - factory.setRequestInfoFactory(new TwitterAPIUtils.TwidereRequestInfoFactory()); - factory.setHttpRequestFactory(new TwitterAPIUtils.TwidereHttpRequestFactory(userAgent)); - factory.setExceptionFactory(new TwitterAPIUtils.TwidereExceptionFactory()); - return factory.build(cls); - } - - public static RestHttpClient createHttpClient(final Context context, final SharedPreferences prefs) { - final int connectionTimeout = prefs.getInt(KEY_CONNECTION_TIMEOUT, 10); - final boolean ignoreSslError = prefs.getBoolean(KEY_IGNORE_SSL_ERROR, false); - final boolean enableProxy = prefs.getBoolean(KEY_ENABLE_PROXY, false); - - final OkHttpClient client = new OkHttpClient(); - client.setConnectTimeout(connectionTimeout, TimeUnit.SECONDS); - if (ignoreSslError) { - client.setSslSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null)); - } else { - client.setSslSocketFactory(SSLCertificateSocketFactory.getDefault(0, null)); - } - if (enableProxy) { - client.setProxy(getProxy(prefs)); - } - Internal.instance.setNetwork(client, TwidereHostAddressResolver.getInstance(context)); - return new OkHttpRestClient(client); - } - - - public static Proxy getProxy(final SharedPreferences prefs) { - final String proxyHost = prefs.getString(KEY_PROXY_HOST, null); - final int proxyPort = ParseUtils.parseInt(prefs.getString(KEY_PROXY_PORT, "-1")); - if (!isEmpty(proxyHost) && proxyPort >= 0 && proxyPort < 65535) { - final SocketAddress addr = InetSocketAddress.createUnresolved(proxyHost, proxyPort); - return new Proxy(Proxy.Type.HTTP, addr); - } - return Proxy.NO_PROXY; - } - - - - public static long[] getActivatedAccountIds(final Context context) { - long[] accounts = new long[0]; - if (context == null) return accounts; - final String[] cols = new String[]{Accounts.ACCOUNT_ID}; - final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, cols, Accounts.IS_ACTIVATED + "=1", - null, Accounts.ACCOUNT_ID); - if (cur != null) { - final int idx = cur.getColumnIndexOrThrow(Accounts.ACCOUNT_ID); - cur.moveToFirst(); - accounts = new long[cur.getCount()]; - int i = 0; - while (!cur.isAfterLast()) { - accounts[i] = cur.getLong(idx); - i++; - cur.moveToNext(); - } - cur.close(); - } - return accounts; - } - - public static String getNonEmptyString(final TwidereSharedPreferences pref, final String key, final String def) { - if (pref == null) return def; - final String val = pref.getString(key, def); - return isEmpty(val) ? def : val; - } - - public static String replaceLast(final String text, final String regex, final String replacement) { - if (text == null || regex == null || replacement == null) return text; - return text.replaceFirst("(?s)" + regex + "(?!.*?" + regex + ")", replacement); - } - -} diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi-v11/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-hdpi-v11/ic_stat_login.png deleted file mode 100644 index cc6a7ed2b..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi-v11/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi-v11/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-hdpi-v11/ic_stat_twidere.png deleted file mode 100644 index 5662508de..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi-v11/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi-v9/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-hdpi-v9/ic_stat_login.png deleted file mode 100644 index e14806f1e..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi-v9/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi-v9/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-hdpi-v9/ic_stat_twidere.png deleted file mode 100644 index ec6f52438..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi-v9/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_launcher.png b/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 4ce12c012..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_stat_login.png deleted file mode 100644 index 7ad61d275..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_stat_twidere.png deleted file mode 100644 index 62008a233..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-hdpi/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-ldpi-v11/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-ldpi-v11/ic_stat_login.png deleted file mode 100644 index 55f4c57c0..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-ldpi-v11/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-ldpi-v11/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-ldpi-v11/ic_stat_twidere.png deleted file mode 100644 index 2c6c59919..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-ldpi-v11/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-ldpi-v9/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-ldpi-v9/ic_stat_login.png deleted file mode 100644 index 3545323dd..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-ldpi-v9/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-ldpi-v9/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-ldpi-v9/ic_stat_twidere.png deleted file mode 100644 index fa7c3c3e5..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-ldpi-v9/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi-v11/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-mdpi-v11/ic_stat_login.png deleted file mode 100644 index 197d929a3..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi-v11/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi-v11/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-mdpi-v11/ic_stat_twidere.png deleted file mode 100644 index 9afc68308..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi-v11/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi-v9/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-mdpi-v9/ic_stat_login.png deleted file mode 100644 index bf03f9a81..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi-v9/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi-v9/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-mdpi-v9/ic_stat_twidere.png deleted file mode 100644 index bfd556d32..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi-v9/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_launcher.png b/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_launcher.png deleted file mode 100644 index 380d5229f..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_stat_login.png deleted file mode 100644 index b734debe0..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_stat_twidere.png deleted file mode 100644 index 05e41a6cf..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-mdpi/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v11/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi-v11/ic_stat_login.png deleted file mode 100644 index d32701859..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v11/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v11/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi-v11/ic_stat_twidere.png deleted file mode 100644 index 3439e6269..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v11/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v9/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi-v9/ic_stat_login.png deleted file mode 100644 index 24bf7379e..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v9/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v9/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi-v9/ic_stat_twidere.png deleted file mode 100644 index 2b49bf774..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi-v9/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_launcher.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index 2d12e0e0d..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_stat_login.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_stat_login.png deleted file mode 100644 index d4994d081..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_stat_login.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_stat_twidere.png b/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_stat_twidere.png deleted file mode 100644 index 5866a0b02..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xhdpi/ic_stat_twidere.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/drawable-xxhdpi/ic_launcher.png b/twidere.extension.streaming/src/main/res/drawable-xxhdpi/ic_launcher.png deleted file mode 100644 index 40dc3ffca..000000000 Binary files a/twidere.extension.streaming/src/main/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/twidere.extension.streaming/src/main/res/values-hdpi/bools.xml b/twidere.extension.streaming/src/main/res/values-hdpi/bools.xml deleted file mode 100644 index 1fe4e3e54..000000000 --- a/twidere.extension.streaming/src/main/res/values-hdpi/bools.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - true - - diff --git a/twidere.extension.streaming/src/main/res/values/bools.xml b/twidere.extension.streaming/src/main/res/values/bools.xml deleted file mode 100644 index 9c358e248..000000000 --- a/twidere.extension.streaming/src/main/res/values/bools.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - false - - diff --git a/twidere.extension.streaming/src/main/res/values/strings.xml b/twidere.extension.streaming/src/main/res/values/strings.xml deleted file mode 100644 index 074348612..000000000 --- a/twidere.extension.streaming/src/main/res/values/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - Twidere Streaming Extension - Select accounts - Enable streaming - Streaming service is running - Permission request to access Twidere - - diff --git a/twidere.extension.streaming/src/main/res/xml/settings.xml b/twidere.extension.streaming/src/main/res/xml/settings.xml deleted file mode 100644 index 347f02bf8..000000000 --- a/twidere.extension.streaming/src/main/res/xml/settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/twidere/build.gradle b/twidere/build.gradle index bd5154248..3ca0b2d3f 100644 --- a/twidere/build.gradle +++ b/twidere/build.gradle @@ -22,16 +22,6 @@ android { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } - packagingOptions { - exclude 'META-INF/DEPENDENCIES' - exclude 'META-INF/LICENSE' - exclude 'META-INF/LICENSE.txt' - exclude 'META-INF/license.txt' - exclude 'META-INF/NOTICE' - exclude 'META-INF/NOTICE.txt' - exclude 'META-INF/notice.txt' - exclude 'META-INF/ASL2.0' - } productFlavors { google { } @@ -95,11 +85,14 @@ dependencies { compile 'com.bluelinelabs:logansquare:1.1.0' compile 'ch.acra:acra:4.6.2' compile 'org.jraf:android-switch-backport:2.0.1' + compile 'com.fasterxml.jackson.core:jackson-databind:2.4.4' googleCompile 'com.google.android.gms:play-services-maps:7.3.0' googleCompile 'com.google.maps.android:android-maps-utils:0.3.4' fdroidCompile 'org.osmdroid:osmdroid-android:4.3' fdroidCompile 'org.slf4j:slf4j-simple:1.7.12' debugCompile 'im.dino:dbinspector:3.1.0@aar' + debugCompile 'com.facebook.stetho:stetho:1.1.1' + debugCompile 'com.facebook.stetho:stetho-okhttp:1.1.1' compile project(':twidere.component.common') compile project(':twidere.component.nyan') compile fileTree(dir: 'libs/main', include: ['*.jar']) diff --git a/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java b/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java new file mode 100644 index 000000000..6be3a40f8 --- /dev/null +++ b/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java @@ -0,0 +1,43 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2015 Mariotaku Lee + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +package org.mariotaku.twidere.util; + +import android.app.Application; + +import com.facebook.stetho.Stetho; +import com.facebook.stetho.okhttp.StethoInterceptor; +import com.squareup.okhttp.OkHttpClient; + +/** + * Created by mariotaku on 15/5/27. + */ +public class DebugModeUtils { + + public static void initForHttpClient(final OkHttpClient client) { + client.networkInterceptors().add(new StethoInterceptor()); + } + + public static void initForApplication(final Application application) { + Stetho.initialize(Stetho.newInitializerBuilder(application) + .enableDumpapp(Stetho.defaultDumperPluginsProvider(application)) + .enableWebKitInspector(Stetho.defaultInspectorModulesProvider(application)) + .build()); + } +} diff --git a/twidere/src/main/AndroidManifest.xml b/twidere/src/main/AndroidManifest.xml index 1194b46f0..a1428b065 100644 --- a/twidere/src/main/AndroidManifest.xml +++ b/twidere/src/main/AndroidManifest.xml @@ -1,65 +1,65 @@ - + + android:required="false"/> + android:required="false"/> + android:required="false"/> + android:required="false"/> + android:required="false"/> + android:required="false"/> + android:required="true"/> - - - - - - - - - - - + + + + + + + + + + + + android:label="@string/app_name"/> + android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP"/> + android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP"/> + android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP"/> + android:required="false"/> + android:value="AEdPqrEAAAAIKbKATV1AGbLB4kem3w8QaPVJSPVVumbMHxkfwA"/> + android:value="true"/> + android:value="480dp"/> + android:value="640dp"/> + android:value="240dp"/> + android:value="320dp"/> + android:value="true"/> - + - - - + + + - + - - - + + + - + - + - + - + + android:resource="@xml/searchable"/> + android:value=".activity.support.HomeActivity"/> - - - - - - - + + + + + + + - + - - + + - + - - + + + android:value=".activity.support.HomeActivity"/> - + - + - + - + - + - + - - + + - + + android:value=".activity.support.HomeActivity"/> + android:windowSoftInputMode="adjustResize"/> - + - + - + - + - - - + + + + android:theme="@style/Theme.Twidere.Light.NoDisplay"/> + android:value=".activity.support.HomeActivity"/> - + - - + + - + - + - - + + - - - + + + - - + + - + - - - + + + - + - - + + - + - + - + - + - + - + - + - - + + - + + android:theme="@style/Theme.Twidere.Wizard"/> + android:theme="@android:style/Theme.NoDisplay"/> + android:theme="@android:style/Theme.NoDisplay"/> - + - + + android:scheme="http"/> + android:scheme="https"/> + android:scheme="http"/> + android:scheme="https"/> + android:scheme="http"/> + android:scheme="https"/> - - + + - - + + - + - + + android:resource="@drawable/ic_assist_twidere"/> + android:theme="@style/Theme.Twidere.Dark.Dialog"/> - + - + + android:windowSoftInputMode="stateAlwaysHidden"/> + android:theme="@android:style/Theme.NoDisplay"/> + android:label="@string/label_refresh_service"/> + + android:label="@string/label_background_operation_service"/> - + + android:resource="@xml/nyan_wallpaper"/> - + @@ -522,53 +525,53 @@ android:exported="true" android:grantUriPermissions="true" android:label="@string/label_data_provider" - tools:ignore="ExportedContentProvider" /> + tools:ignore="ExportedContentProvider"/> + tools:ignore="ExportedContentProvider"/> + tools:ignore="ExportedContentProvider"/> - + - + - + + android:scheme="android_secret_code"/> - + - - - - + + + + diff --git a/twidere/src/main/java/edu/ucdavis/earlybird/CSVFileFilter.java b/twidere/src/main/java/edu/ucdavis/earlybird/CSVFileFilter.java deleted file mode 100644 index a7800c1f4..000000000 --- a/twidere/src/main/java/edu/ucdavis/earlybird/CSVFileFilter.java +++ /dev/null @@ -1,19 +0,0 @@ -package edu.ucdavis.earlybird; - -import java.io.File; -import java.io.FileFilter; - -public final class CSVFileFilter implements FileFilter { - - @Override - public boolean accept(final File file) { - return file.isFile() && "csv".equalsIgnoreCase(getExtension(file)); - } - - static String getExtension(final File file) { - final String name = file.getName(); - final int pos = name.lastIndexOf('.'); - if (pos == -1) return null; - return name.substring(pos + 1); - } -} diff --git a/twidere/src/main/java/edu/ucdavis/earlybird/ProfilingUtil.java b/twidere/src/main/java/edu/ucdavis/earlybird/ProfilingUtil.java deleted file mode 100644 index 525cd6e98..000000000 --- a/twidere/src/main/java/edu/ucdavis/earlybird/ProfilingUtil.java +++ /dev/null @@ -1,70 +0,0 @@ -package edu.ucdavis.earlybird; - -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.os.BatteryManager; -import android.util.Log; - -import org.mariotaku.twidere.BuildConfig; -import org.mariotaku.twidere.Constants; - -import java.io.BufferedWriter; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; - -public class ProfilingUtil { - - public static final String FILE_NAME_PROFILE = "Profile"; - public static final String FILE_NAME_LOCATION = "Location"; - public static final String FILE_NAME_APP = "App"; - public static final String FILE_NAME_WIFI = "Wifi"; - - public static boolean isCharging(final Context context) { - if (context == null) return false; - final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); - if (intent == null) return false; - final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); - return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB; - } - - public static boolean log(final Context context, final String msg) { - if (BuildConfig.DEBUG) { - final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1]; - final String fullname = ste.getClassName(); - final String name = fullname.substring(fullname.lastIndexOf('.')); - final String tag = name + "." + ste.getMethodName(); - Log.d(tag, msg); - return true; - } else - return false; - } - - public static void profile(final Context context, final long accountID, final String text) { - profile(context, accountID + "_" + FILE_NAME_PROFILE, text); - } - - public static void profile(final Context context, final String name, final String text) { - if (context == null) return; - final SharedPreferences prefs = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, - Context.MODE_PRIVATE); - if (!prefs.getBoolean(Constants.KEY_USAGE_STATISTICS, false)) return; - final String filename = name + ".csv"; - new Thread() { - @Override - public void run() { - try { - final FileOutputStream fos = context.openFileOutput(filename, Context.MODE_APPEND); - if (fos == null) return; - final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos)); - bw.write("[" + System.currentTimeMillis() + "], " + text + "\n"); - bw.flush(); - fos.close(); - } catch (final Exception e) { - e.printStackTrace(); - } - } - }.start(); - } -} diff --git a/twidere/src/main/java/edu/ucdavis/earlybird/UCDService.java b/twidere/src/main/java/edu/ucdavis/earlybird/UCDService.java deleted file mode 100644 index c9a0b6df8..000000000 --- a/twidere/src/main/java/edu/ucdavis/earlybird/UCDService.java +++ /dev/null @@ -1,42 +0,0 @@ -package edu.ucdavis.earlybird; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -/** - * Request location ONCE per WAKE_PERIOD_IN_MILLI. - */ -public class UCDService extends Service { - - public static final String ACTION_GET_LOCATION = "edu.ucdavis.earlybird.GET_LOCATION"; - private AlarmManager mAlarmManager; - private PendingIntent uploadIntent; - - @Override - public IBinder onBind(final Intent intent) { - throw new IllegalStateException("Not implemented."); - } - - @Override - public void onCreate() { - super.onCreate(); - - ProfilingUtil.log(this, "onCreate"); - mAlarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE); - - // Upload Service - final Intent i = new Intent(UploadReceiver.ACTION_UPLOAD_PROFILE); - uploadIntent = PendingIntent.getBroadcast(this, 0, i, 0); - mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 12 * 60 * 60 * 1000, uploadIntent); - } - - @Override - public void onDestroy() { - mAlarmManager.cancel(uploadIntent); - super.onDestroy(); - } - -} diff --git a/twidere/src/main/java/edu/ucdavis/earlybird/UploadReceiver.java b/twidere/src/main/java/edu/ucdavis/earlybird/UploadReceiver.java deleted file mode 100644 index be3077cd6..000000000 --- a/twidere/src/main/java/edu/ucdavis/earlybird/UploadReceiver.java +++ /dev/null @@ -1,27 +0,0 @@ -package edu.ucdavis.earlybird; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.net.wifi.WifiManager; - -import org.mariotaku.twidere.util.Utils; - -public class UploadReceiver extends BroadcastReceiver { - - public static final String ACTION_UPLOAD_PROFILE = "edu.ucdavis.earlybird.UPLOAD_PROFILE"; - - @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - final boolean isWifi = Utils.isOnWifi(context.getApplicationContext()); - final boolean isCharging = ProfilingUtil.isCharging(context.getApplicationContext()); - if (WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION.equals(action)) { - final boolean wifi = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false); - ProfilingUtil.profile(context, ProfilingUtil.FILE_NAME_WIFI, wifi ? "connected" : "disconnected"); - } - if (isWifi && isCharging) { - new UploadTask(context).execute(); - } - } -} diff --git a/twidere/src/main/java/edu/ucdavis/earlybird/UploadTask.java b/twidere/src/main/java/edu/ucdavis/earlybird/UploadTask.java deleted file mode 100644 index 3c770d4e9..000000000 --- a/twidere/src/main/java/edu/ucdavis/earlybird/UploadTask.java +++ /dev/null @@ -1,146 +0,0 @@ -package edu.ucdavis.earlybird; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.AsyncTask; -import android.provider.Settings.Secure; - -import org.mariotaku.restfu.annotation.method.POST; -import org.mariotaku.restfu.http.RestHttpClient; -import org.mariotaku.restfu.http.RestHttpRequest; -import org.mariotaku.restfu.http.RestHttpResponse; -import org.mariotaku.restfu.http.mime.FileTypedData; -import org.mariotaku.restfu.http.mime.MultipartTypedBody; -import org.mariotaku.twidere.util.TwitterAPIFactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import static org.mariotaku.twidere.util.Utils.copyStream; - -public class UploadTask extends AsyncTask { - - private static final String LAST_UPLOAD_DATE = "last_upload_time"; - private static final double MILLSECS_HALF_DAY = 1000 * 60 * 60 * 12; - - private final String device_id; - private final Context context; - - private final RestHttpClient client; - - private static final String PROFILE_SERVER_URL = "http://weik.metaisle.com/profiles"; - - // private static final String PROFILE_SERVER_URL = - // "http://192.168.0.105:3000/profiles"; - - public UploadTask(final Context context) { - this.context = context; - this.client = TwitterAPIFactory.getDefaultHttpClient(context); - device_id = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); - } - - public void uploadMultipart(final String url, final File file) { - final String app_root = file.getParent(); - final File tmp_dir = new File(app_root + "/tmp"); - if (!tmp_dir.exists()) { - if (!tmp_dir.mkdirs()) { - ProfilingUtil.log(context, "cannot create tmp, do nothing."); - return; - } - } - final File tmp = new File(tmp_dir, file.getName()); - file.renameTo(tmp); - - try { - - final RestHttpRequest.Builder builder = new RestHttpRequest.Builder(); - builder.url(PROFILE_SERVER_URL); - builder.method(POST.METHOD); - final MultipartTypedBody body = new MultipartTypedBody(); - body.add("upload", new FileTypedData(tmp)); - builder.body(body); - final RestHttpResponse response = client.execute(builder.build()); - - // Responses from the server (code and message) - final int serverResponseCode = response.getStatus(); - - ProfilingUtil.log(context, "server response code " + serverResponseCode); - - if (serverResponseCode / 100 == 2) { - tmp.delete(); - } else { - putBackProfile(context, tmp, file); - } - - } catch (final IOException e) { - e.printStackTrace(); - putBackProfile(context, tmp, file); - } - } - - @Override - protected Object doInBackground(final Object... params) { - - final SharedPreferences prefs = context.getSharedPreferences("ucd_data_profiling", Context.MODE_PRIVATE); - - if (prefs.contains(LAST_UPLOAD_DATE)) { - final long lastUpload = prefs.getLong(LAST_UPLOAD_DATE, System.currentTimeMillis()); - final double deltaDays = (System.currentTimeMillis() - lastUpload) / (MILLSECS_HALF_DAY * 2); - if (deltaDays < 1) { - ProfilingUtil.log(context, "Uploaded less than 1 day ago."); - return null; - } - } - - final File root = context.getFilesDir(); - final File[] files = root.listFiles(new CSVFileFilter()); - - uploadToNode(files); - prefs.edit().putLong(LAST_UPLOAD_DATE, System.currentTimeMillis()).apply(); - return null; - } - - private boolean uploadToNode(final File... files) { - for (final File file : files) { - if (file.isDirectory()) { - continue; - } - final String url = PROFILE_SERVER_URL + "/" + device_id + "/" - + file.getName().replaceFirst("[.][^.]+$", ""); - ProfilingUtil.log(context, url); - uploadMultipart(url, file); - } - return false; - } - - public static void putBackProfile(final Context context, final File tmp, final File profile) { - boolean success; - if (profile.exists()) { - try { - final FileOutputStream os = new FileOutputStream(tmp, true); - final FileInputStream is = new FileInputStream(profile); - copyStream(is, os); - is.close(); - os.close(); - success = true; - } catch (final IOException e) { - e.printStackTrace(); - success = false; - } - - if (success && tmp.renameTo(profile) && tmp.delete()) { - ProfilingUtil.log(context, "put profile back success"); - } else { - ProfilingUtil.log(context, "put profile back failed"); - } - } else { - if (tmp.renameTo(profile)) { - ProfilingUtil.log(context, "put profile back success"); - } else { - ProfilingUtil.log(context, "put profile back failed"); - } - } - } -} diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java index fd1548bd0..ab18a63a8 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java @@ -50,7 +50,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; import org.mariotaku.twidere.util.AsyncTaskUtils; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator; import org.mariotaku.twidere.util.TwitterAPIFactory; -import org.mariotaku.twidere.util.TwitterAPIUtils; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; @@ -238,7 +237,7 @@ public class BrowserSignInActivity extends BaseSupportDialogActivity { consumerSecret = defConsumerSecret; } try { - final Endpoint endpoint = new Endpoint(TwitterAPIUtils.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", "oauth")); + final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", "oauth")); final Authorization auth = new OAuthAuthorization(consumerKey, consumerSecret); final TwitterOAuth twitter = TwitterAPIFactory.getInstance(mActivity, endpoint, auth, TwitterOAuth.class); return twitter.getRequestToken(OAUTH_CALLBACK_OOB); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java index 8e34940ab..b8dbe5125 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java @@ -87,6 +87,7 @@ import org.mariotaku.twidere.model.SupportTabSpec; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; import org.mariotaku.twidere.provider.TwidereDataStore.Mentions; import org.mariotaku.twidere.provider.TwidereDataStore.Statuses; +import org.mariotaku.twidere.service.StreamingService; import org.mariotaku.twidere.util.AsyncTaskUtils; import org.mariotaku.twidere.util.AsyncTwitterWrapper; import org.mariotaku.twidere.util.CustomTabUtils; @@ -120,7 +121,6 @@ import java.util.Map.Entry; import edu.tsinghua.spice.Utilies.NetworkStateUtil; import edu.tsinghua.spice.Utilies.SpiceProfilingUtil; -import edu.ucdavis.earlybird.ProfilingUtil; import static org.mariotaku.twidere.util.CompareUtils.classEquals; import static org.mariotaku.twidere.util.Utils.cleanDatabasesByItemLimit; @@ -428,6 +428,8 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen final int initialTabPosition = handleIntent(intent, savedInstanceState == null); setTabPosition(initialTabPosition); + + startService(new Intent(this, StreamingService.class)); } @Override @@ -440,8 +442,6 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen final Bus bus = TwidereApplication.getInstance(this).getMessageBus(); assert bus != null; bus.register(this); - // UCD - ProfilingUtil.profile(this, ProfilingUtil.FILE_NAME_APP, "App onStart"); // spice SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_APP, "App Launch" + "," + Build.MODEL + "," + "mediaPreview=" + mPreferences.getBoolean(KEY_MEDIA_PREVIEW, false)); @@ -480,8 +480,6 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen mPreferences.edit().putInt(KEY_SAVED_TAB_POSITION, mViewPager.getCurrentItem()).apply(); sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONSTOP)); - // UCD - ProfilingUtil.profile(this, ProfilingUtil.FILE_NAME_APP, "App onStop"); // spice SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_APP, "App Stop"); SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_ONLAUNCH, "App Stop" + "," + NetworkStateUtil.getConnectedType(this) + "," + Build.MODEL); @@ -621,6 +619,9 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen @Override protected void onDestroy() { + + stopService(new Intent(this, StreamingService.class)); + // Delete unused items in databases. cleanDatabasesByItemLimit(this); sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONDESTROY)); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java index 1c84b7b6e..cdfbe70db 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java @@ -91,7 +91,6 @@ import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.util.TwidereActionModeForChildListener; import org.mariotaku.twidere.util.TwidereColorUtils; import org.mariotaku.twidere.util.TwitterAPIFactory; -import org.mariotaku.twidere.util.TwitterAPIUtils; import org.mariotaku.twidere.util.support.ViewSupport; import org.mariotaku.twidere.util.support.view.ViewOutlineProviderCompat; import org.mariotaku.twidere.view.iface.TintedStatusLayout; @@ -599,7 +598,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList protected SignInResponse doInBackground(final Object... params) { try { final String versionSuffix = noVersionSuffix ? null : "1.1"; - final Endpoint endpoint = new Endpoint(TwitterAPIUtils.getApiUrl(apiUrlFormat, "api", versionSuffix)); + final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix)); final TwitterOAuth oauth = TwitterAPIFactory.getInstance(context, endpoint, new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret()), TwitterOAuth.class); final OAuthToken accessToken = oauth.getAccessToken(requestToken, oauthVerifier); @@ -684,7 +683,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList private SignInResponse authBasic() throws TwitterException { final String versionSuffix = noVersionSuffix ? null : "1.1"; - final Endpoint endpoint = new Endpoint(TwitterAPIUtils.getApiUrl(apiUrlFormat, "api", versionSuffix)); + final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix)); final Authorization auth = new BasicAuthorization(username, password); final Twitter twitter = TwitterAPIFactory.getInstance(context, endpoint, auth, Twitter.class); final User user = twitter.verifyCredentials(); @@ -698,9 +697,9 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList private SignInResponse authOAuth() throws AuthenticationException, TwitterException { String endpointUrl, signEndpointUrl; - endpointUrl = TwitterAPIUtils.getApiUrl(apiUrlFormat, "api", null); + endpointUrl = TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", null); if (!sameOAuthSigningUrl) { - signEndpointUrl = TwitterAPIUtils.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null); + signEndpointUrl = TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null); } else { signEndpointUrl = endpointUrl; } @@ -712,9 +711,9 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList final long userId = accessToken.getUserId(); if (userId <= 0) return new SignInResponse(false, false, null); final String versionSuffix = noVersionSuffix ? null : "1.1"; - endpointUrl = TwitterAPIUtils.getApiUrl(apiUrlFormat, "api", versionSuffix); + endpointUrl = TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix); if (!sameOAuthSigningUrl) { - signEndpointUrl = TwitterAPIUtils.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", versionSuffix); + signEndpointUrl = TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", versionSuffix); } else { signEndpointUrl = endpointUrl; } @@ -730,7 +729,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList private SignInResponse authTwipOMode() throws TwitterException { final String versionSuffix = noVersionSuffix ? null : "1.1"; - final Endpoint endpoint = new Endpoint(TwitterAPIUtils.getApiUrl(apiUrlFormat, "api", versionSuffix)); + final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix)); final Authorization auth = new EmptyAuthorization(); final Twitter twitter = TwitterAPIFactory.getInstance(context, endpoint, auth, Twitter.class); final User user = twitter.verifyCredentials(); @@ -742,7 +741,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList private SignInResponse authxAuth() throws TwitterException { final String versionSuffix = noVersionSuffix ? null : "1.1"; - final Endpoint endpoint = new Endpoint(TwitterAPIUtils.getApiUrl(apiUrlFormat, "api", versionSuffix)); + final Endpoint endpoint = new Endpoint(TwitterAPIFactory.getApiUrl(apiUrlFormat, "api", versionSuffix)); OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret()); final TwitterOAuth oauth = TwitterAPIFactory.getInstance(context, endpoint, auth, TwitterOAuth.class); final OAuthToken accessToken = oauth.getAccessToken(username, password, TwitterOAuth.XAuthMode.CLIENT); diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUserStream.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUserStream.java similarity index 100% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUserStream.java rename to twidere/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUserStream.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java similarity index 57% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java rename to twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java index b651a0f84..ba82faa9e 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java +++ b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java @@ -19,6 +19,8 @@ package org.mariotaku.twidere.api.twitter; +import android.util.Log; + import com.bluelinelabs.logansquare.LoganSquare; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -42,6 +44,8 @@ import java.io.InputStreamReader; */ public abstract class UserStreamCallback implements RawCallback { + private boolean connected; + private boolean disconnected; @Override @@ -54,78 +58,93 @@ public abstract class UserStreamCallback implements RawCallback { } final ObjectMapper mapper = new ObjectMapper(LoganSquare.JSON_FACTORY); final CRLFLineReader reader = new CRLFLineReader(new InputStreamReader(response.getBody().stream(), "UTF-8")); - for (String line; (line = reader.readLine()) != null && !disconnected; ) { - if (line.isEmpty()) continue; - JsonNode rootNode = mapper.readTree(line); - switch (JSONObjectType.determine(rootNode)) { - case SENDER: { - break; + try { + for (String line; (line = reader.readLine()) != null && !disconnected; ) { + if (!connected) { + onConnected(); + connected = true; } - case STATUS: { - onStatus(LoganSquare.mapperFor(Status.class).parse(rootNode.traverse())); - break; + if (line.isEmpty()) continue; + JsonNode rootNode = mapper.readTree(line); + switch (JSONObjectType.determine(rootNode)) { + case SENDER: { + break; + } + case STATUS: { + onStatus(LoganSquare.mapperFor(Status.class).parse(rootNode.traverse())); + break; + } + case DIRECT_MESSAGE: { + onDirectMessage(LoganSquare.mapperFor(DirectMessage.class).parse(rootNode.traverse())); + break; + } + case DELETE: { + break; + } + case LIMIT: + break; + case STALL_WARNING: + break; + case SCRUB_GEO: + break; + case FRIENDS: + break; + case FAVORITE: { + onFavorite(parse(User.class, rootNode.get("source")), + parse(User.class, rootNode.get("target")), + parse(Status.class, rootNode.get("target_object"))); + break; + } + case UNFAVORITE: { + onUnfavorite(parse(User.class, rootNode.get("source")), + parse(User.class, rootNode.get("target")), + parse(Status.class, rootNode.get("target_object"))); + break; + } + case FOLLOW: + break; + case UNFOLLOW: + break; + case USER_LIST_MEMBER_ADDED: + break; + case USER_LIST_MEMBER_DELETED: + break; + case USER_LIST_SUBSCRIBED: + break; + case USER_LIST_UNSUBSCRIBED: + break; + case USER_LIST_CREATED: + break; + case USER_LIST_UPDATED: + break; + case USER_LIST_DESTROYED: + break; + case USER_UPDATE: + break; + case USER_DELETE: + break; + case USER_SUSPEND: + break; + case BLOCK: + break; + case UNBLOCK: + break; + case DISCONNECTION: + break; + case UNKNOWN: + break; } - case DIRECT_MESSAGE: { - onDirectMessage(LoganSquare.mapperFor(DirectMessage.class).parse(rootNode.traverse())); - break; - } - case DELETE: { - break; - } - case LIMIT: - break; - case STALL_WARNING: - break; - case SCRUB_GEO: - break; - case FRIENDS: - break; - case FAVORITE: { - onFavorite(parse(User.class, rootNode.get("source")), - parse(User.class, rootNode.get("target")), - parse(Status.class, rootNode.get("target_object"))); - break; - } - case UNFAVORITE: - break; - case FOLLOW: - break; - case UNFOLLOW: - break; - case USER_LIST_MEMBER_ADDED: - break; - case USER_LIST_MEMBER_DELETED: - break; - case USER_LIST_SUBSCRIBED: - break; - case USER_LIST_UNSUBSCRIBED: - break; - case USER_LIST_CREATED: - break; - case USER_LIST_UPDATED: - break; - case USER_LIST_DESTROYED: - break; - case USER_UPDATE: - break; - case USER_DELETE: - break; - case USER_SUSPEND: - break; - case BLOCK: - break; - case UNBLOCK: - break; - case DISCONNECTION: - break; - case UNKNOWN: - break; } + } catch (IOException e) { + onException(e); + } finally { + Log.d("Twidere.Stream", "Cleaning up..."); + reader.close(); + response.close(); } - reader.close(); - response.close(); } + private static T parse(final Class cls, final JsonNode json) throws IOException { return LoganSquare.mapperFor(cls).parse(json.traverse()); } @@ -139,6 +158,8 @@ public abstract class UserStreamCallback implements RawCallback { disconnected = true; } + public abstract void onConnected(); + public abstract void onBlock(User source, User blockedUser); public abstract void onDeletionNotice(long directMessageId, long userId); diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/CRLFLineReader.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/CRLFLineReader.java similarity index 100% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/CRLFLineReader.java rename to twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/CRLFLineReader.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/JSONObjectType.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/JSONObjectType.java similarity index 100% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/JSONObjectType.java rename to twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/JSONObjectType.java diff --git a/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java b/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java index e5531d358..0ae72faab 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java +++ b/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java @@ -55,6 +55,7 @@ import org.mariotaku.twidere.activity.MainHondaJOJOActivity; import org.mariotaku.twidere.service.RefreshService; import org.mariotaku.twidere.util.AsyncTaskManager; import org.mariotaku.twidere.util.AsyncTwitterWrapper; +import org.mariotaku.twidere.util.DebugModeUtils; import org.mariotaku.twidere.util.ErrorLogger; import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.MediaLoaderWrapper; @@ -73,7 +74,6 @@ import org.mariotaku.twidere.util.net.TwidereHostAddressResolver; import java.io.File; import edu.tsinghua.spice.SpiceService; -import edu.ucdavis.earlybird.UCDService; import static org.mariotaku.twidere.util.Utils.getBestCacheDir; import static org.mariotaku.twidere.util.Utils.getInternalCacheDir; @@ -236,6 +236,7 @@ public class TwidereApplication extends MultiDexApplication implements Constants StrictModeUtils.detectAllVmPolicy(); } super.onCreate(); + initDebugMode(); initBugReport(); mDefaultUserAgent = UserAgentUtils.getDefaultUserAgentString(this); mHandler = new Handler(); @@ -269,6 +270,10 @@ public class TwidereApplication extends MultiDexApplication implements Constants reloadConnectivitySettings(); } + private void initDebugMode() { + DebugModeUtils.initForApplication(this); + } + private void initBugReport() { ACRA.init(this); ErrorLogger.setEnabled(BuildConfig.DEBUG); @@ -313,7 +318,6 @@ public class TwidereApplication extends MultiDexApplication implements Constants || KEY_PROXY_PORT.equals(key)) { reloadConnectivitySettings(); } else if (KEY_USAGE_STATISTICS.equals(key)) { - stopService(new Intent(this, UCDService.class)); //spice stopService(new Intent(this, SpiceService.class)); startUsageStatisticsServiceIfNeeded(this); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/AccountRefreshSettingsFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/AccountRefreshSettingsFragment.java index d98e12a50..261ebc778 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/AccountRefreshSettingsFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/AccountRefreshSettingsFragment.java @@ -19,6 +19,8 @@ package org.mariotaku.twidere.fragment; +import android.support.annotation.Nullable; + import org.mariotaku.twidere.R; public class AccountRefreshSettingsFragment extends BaseAccountPreferenceFragment { @@ -34,7 +36,8 @@ public class AccountRefreshSettingsFragment extends BaseAccountPreferenceFragmen } @Override + @Nullable protected String getSwitchPreferenceKey() { - return KEY_AUTO_REFRESH; + return null; } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/BaseAccountPreferenceFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/BaseAccountPreferenceFragment.java index 953dc2a80..43856c4bd 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/BaseAccountPreferenceFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/BaseAccountPreferenceFragment.java @@ -28,6 +28,8 @@ import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; +import android.support.annotation.Nullable; +import android.text.TextUtils; import android.view.Menu; import android.view.MenuInflater; import android.view.View; @@ -78,12 +80,15 @@ public abstract class BaseAccountPreferenceFragment extends PreferenceFragment i @Override public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { - inflater.inflate(R.menu.menu_switch_preference, menu); - final View actionView = menu.findItem(MENU_TOGGLE).getActionView(); - final CompoundButton toggle = (CompoundButton) actionView.findViewById(android.R.id.toggle); - final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); - toggle.setOnCheckedChangeListener(this); - toggle.setChecked(prefs.getBoolean(getSwitchPreferenceKey(), getSwitchPreferenceDefault())); + final String switchKey = getSwitchPreferenceKey(); + if (!TextUtils.isEmpty(switchKey)) { + inflater.inflate(R.menu.menu_switch_preference, menu); + final View actionView = menu.findItem(MENU_TOGGLE).getActionView(); + final CompoundButton toggle = (CompoundButton) actionView.findViewById(android.R.id.toggle); + final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + toggle.setOnCheckedChangeListener(this); + toggle.setChecked(prefs.getBoolean(switchKey, getSwitchPreferenceDefault())); + } super.onCreateOptionsMenu(menu, inflater); } @@ -104,6 +109,7 @@ public abstract class BaseAccountPreferenceFragment extends PreferenceFragment i protected abstract boolean getSwitchPreferenceDefault(); + @Nullable protected abstract String getSwitchPreferenceKey(); private void updatePreferenceScreen() { diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDashboardFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDashboardFragment.java index 113cadf4b..1eff07098 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDashboardFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDashboardFragment.java @@ -136,6 +136,7 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo private ActionMenuView mAccountsToggleMenu; private View mAccountProfileContainer; private View mNoAccountContainer; + private ActionMenuView mActionMenuView; private Context mThemedContext; private MediaLoaderWrapper mImageLoader; @@ -313,30 +314,6 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo break; } } - } else if (adapter instanceof AppMenuAdapter) { - if (!(item instanceof OptionItem)) return; - final OptionItem option = (OptionItem) item; - switch (option.id) { - case MENU_ACCOUNTS: { - Utils.openAccountsManager(getActivity()); - break; - } - case MENU_DRAFTS: { - Utils.openDrafts(getActivity()); - break; - } - case MENU_FILTERS: { - Utils.openFilters(getActivity()); - break; - } - case MENU_SETTINGS: { - final Intent intent = new Intent(getActivity(), SettingsActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - startActivityForResult(intent, REQUEST_SETTINGS); - break; - } - } - closeAccountsDrawer(); } } @@ -431,11 +408,41 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo mAdapter.addView(mAccountSelectorView, true); mAdapter.addAdapter(mAccountOptionsAdapter); - mAdapter.addView(mAppMenuSectionView, false); - mAdapter.addAdapter(mAppMenuAdapter); +// mAdapter.addView(mAppMenuSectionView, false); +// mAdapter.addAdapter(mAppMenuAdapter); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(this); mPreferences.registerOnSharedPreferenceChangeListener(this); + + menuInflater.inflate(R.menu.menu_dashboard, mActionMenuView.getMenu()); + + mActionMenuView.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(final MenuItem item) { + switch (item.getItemId()) { + case MENU_ACCOUNTS: { + Utils.openAccountsManager(getActivity()); + return true; + } + case MENU_DRAFTS: { + Utils.openDrafts(getActivity()); + return true; + } + case MENU_FILTERS: { + Utils.openFilters(getActivity()); + return true; + } + case MENU_SETTINGS: { + final Intent intent = new Intent(getActivity(), SettingsActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivityForResult(intent, REQUEST_SETTINGS); + return true; + } + } + return false; + } + }); + ThemeUtils.resetCheatSheet(mActionMenuView); getLoaderManager().initLoader(0, null, this); } @@ -448,6 +455,7 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo public void onBaseViewCreated(View view, Bundle savedInstanceState) { super.onBaseViewCreated(view, savedInstanceState); mListView = (ListView) view.findViewById(android.R.id.list); + mActionMenuView = (ActionMenuView) view.findViewById(R.id.dashboard_menu); } @Override @@ -849,7 +857,7 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo private final int mActionIconColor; public OptionItemsAdapter(final Context context) { - super(context, R.layout.list_item_menu); + super(context, R.layout.list_item_dashboard_menu); mActionIconColor = ThemeUtils.getThemeForegroundColor(context); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java index 7b2df7280..a8e20e9be 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/DirectMessagesFragment.java @@ -19,6 +19,7 @@ package org.mariotaku.twidere.fragment.support; +import android.app.NotificationManager; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; @@ -295,6 +296,16 @@ public class DirectMessagesFragment extends AbsContentRecyclerViewFragment accounts) { removeAll(); for (final ParcelableAccount account : accounts) { - final AccountItemPreference preference = new AccountItemPreference(getContext(), account, mSwitchKey, - mSwitchDefault); + final AccountItemPreference preference = new AccountItemPreference(getContext(), account, + mSwitchKey, mSwitchDefault); setupPreference(preference, account); addPreference(preference); } @@ -96,39 +93,23 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen protected abstract void setupPreference(AccountItemPreference preference, ParcelableAccount account); public static final class AccountItemPreference extends Preference implements ImageLoadingListener, - OnCheckedChangeListener, OnSharedPreferenceChangeListener, OnPreferenceClickListener, OnClickListener { + OnSharedPreferenceChangeListener { private final ParcelableAccount mAccount; private final SharedPreferences mSwitchPreference; private final MediaLoaderWrapper mImageLoader; - private final String mSwitchKey; - private final boolean mSwitchDefault; - private CompoundButton mToggle; - public AccountItemPreference(final Context context, final ParcelableAccount account, final String switchKey, final boolean switchDefault) { super(context); - setWidgetLayoutResource(R.layout.preference_widget_account_preference_item); - setOnPreferenceClickListener(this); final String switchPreferenceName = ACCOUNT_PREFERENCES_NAME_PREFIX + account.account_id; mAccount = account; mSwitchPreference = context.getSharedPreferences(switchPreferenceName, Context.MODE_PRIVATE); final TwidereApplication app = TwidereApplication.getInstance(context); mImageLoader = app.getMediaLoaderWrapper(); - mSwitchKey = switchKey; - mSwitchDefault = switchDefault; mSwitchPreference.registerOnSharedPreferenceChangeListener(this); } - @Override - public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { - if (mSwitchKey == null) return; - final SharedPreferences.Editor editor = mSwitchPreference.edit(); - editor.putBoolean(mSwitchKey, isChecked); - editor.apply(); - } - @Override public void onLoadingCancelled(final String imageUri, final View view) { // setIcon(R.drawable.ic_profile_image_default); @@ -164,16 +145,6 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen mImageLoader.loadProfileImage(mAccount.profile_image_url, this); } - @Override - protected View onCreateView(ViewGroup parent) { - final View view = super.onCreateView(parent); - view.findViewById(R.id.settings).setOnClickListener(this); - final CompoundButton toggle = (CompoundButton) view.findViewById(android.R.id.toggle); - toggle.setOnCheckedChangeListener(this); - mToggle = toggle; - return view; - } - @Override protected void onBindView(@NonNull final View view) { super.onBindView(view); @@ -190,26 +161,6 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen if (summaryView instanceof TextView) { ((TextView) summaryView).setSingleLine(true); } - final CompoundButton toggle = (CompoundButton) view.findViewById(android.R.id.toggle); - if (mSwitchKey != null) { - toggle.setChecked(mSwitchPreference.getBoolean(mSwitchKey, mSwitchDefault)); - } - } - - @Override - public boolean onPreferenceClick(Preference preference) { - if (mToggle != null) { - mToggle.toggle(); - } - return true; - } - - @Override - public void onClick(View v) { - final Context context = getContext(); - if (!(context instanceof PreferenceActivity)) return; - final PreferenceActivity activity = (PreferenceActivity) context; - activity.startPreferencePanel(getFragment(), getExtras(), getTitleRes(), getTitle(), null, 0); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/preference/AutoFixSwitchPreference.java b/twidere/src/main/java/org/mariotaku/twidere/preference/AutoFixSwitchPreference.java index 0531d8b90..79f234c4d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/preference/AutoFixSwitchPreference.java +++ b/twidere/src/main/java/org/mariotaku/twidere/preference/AutoFixSwitchPreference.java @@ -28,8 +28,6 @@ import org.jraf.android.backport.switchwidget.SwitchPreference; public class AutoFixSwitchPreference extends SwitchPreference { - private View mCachedView; - public AutoFixSwitchPreference(final Context context) { super(context); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/preference/DarkLightThemeTogglePreference.java b/twidere/src/main/java/org/mariotaku/twidere/preference/DarkLightThemeTogglePreference.java new file mode 100644 index 000000000..4c3e1e48a --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/preference/DarkLightThemeTogglePreference.java @@ -0,0 +1,55 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2015 Mariotaku Lee + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +package org.mariotaku.twidere.preference; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.AttributeSet; + +import org.jraf.android.backport.switchwidget.SwitchPreference; +import org.mariotaku.twidere.Constants; +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.util.ThemeUtils; + +public class DarkLightThemeTogglePreference extends SwitchPreference implements Constants { + + public DarkLightThemeTogglePreference(final Context context) { + this(context, null); + } + + public DarkLightThemeTogglePreference(final Context context, final AttributeSet attrs) { + this(context, attrs, R.attr.asb_switchPreferenceStyle); + } + + public DarkLightThemeTogglePreference(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected boolean getPersistedBoolean(final boolean defaultReturnValue) { + final SharedPreferences preferences = getSharedPreferences(); + return ThemeUtils.isDarkTheme(getPersistedString(VALUE_THEME_NAME_TWIDERE)); + } + + @Override + protected boolean persistBoolean(final boolean value) { + return persistString(value ? VALUE_THEME_NAME_DARK : VALUE_THEME_NAME_TWIDERE); + } +} diff --git a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/StreamingService.java b/twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java similarity index 68% rename from twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/StreamingService.java rename to twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java index 30d96219a..62eacdac1 100644 --- a/twidere.extension.streaming/src/main/java/org/mariotaku/twidere/extension/streaming/StreamingService.java +++ b/twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java @@ -1,6 +1,5 @@ -package org.mariotaku.twidere.extension.streaming; +package org.mariotaku.twidere.service; -import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; @@ -13,14 +12,19 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.IBinder; -import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.support.v4.util.LongSparseArray; import android.util.Log; -import android.widget.Toast; import org.mariotaku.restfu.http.Authorization; +import org.mariotaku.restfu.http.ContentType; import org.mariotaku.restfu.http.Endpoint; -import org.mariotaku.twidere.Twidere; -import org.mariotaku.twidere.TwidereSharedPreferences; +import org.mariotaku.restfu.http.RestHttpResponse; +import org.mariotaku.restfu.http.mime.TypedData; +import org.mariotaku.twidere.BuildConfig; +import org.mariotaku.twidere.Constants; +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.activity.SettingsActivity; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.TwitterUserStream; import org.mariotaku.twidere.api.twitter.UserStreamCallback; @@ -30,7 +34,7 @@ import org.mariotaku.twidere.api.twitter.model.StatusDeletionNotice; import org.mariotaku.twidere.api.twitter.model.User; import org.mariotaku.twidere.api.twitter.model.UserList; import org.mariotaku.twidere.api.twitter.model.Warning; -import org.mariotaku.twidere.extension.streaming.util.Utils; +import org.mariotaku.twidere.model.AccountPreferences; import org.mariotaku.twidere.model.ParcelableAccount; import org.mariotaku.twidere.model.ParcelableCredentials; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; @@ -38,19 +42,21 @@ import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages; import org.mariotaku.twidere.provider.TwidereDataStore.Mentions; import org.mariotaku.twidere.provider.TwidereDataStore.Statuses; import org.mariotaku.twidere.util.ContentValuesCreator; +import org.mariotaku.twidere.util.SharedPreferencesWrapper; import org.mariotaku.twidere.util.TwidereArrayUtils; -import org.mariotaku.twidere.util.TwitterAPIUtils; +import org.mariotaku.twidere.util.TwitterAPIFactory; +import org.mariotaku.twidere.util.Utils; -import java.lang.ref.WeakReference; -import java.util.ArrayList; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; import java.util.List; -public class StreamingService extends Service implements Constants, PrivateConstants { +public class StreamingService extends Service implements Constants { private static final int NOTIFICATION_SERVICE_STARTED = 1; - private static final int NOTIFICATION_REQUEST_PERMISSION = 2; - private final List> mTwitterInstances = new ArrayList<>(); + private final LongSparseArray mCallbacks = new LongSparseArray<>(); private ContentResolver mResolver; private SharedPreferences mPreferences; @@ -86,11 +92,11 @@ public class StreamingService extends Service implements Constants, PrivateConst @Override public void onCreate() { super.onCreate(); - mPreferences = PreferenceManager.getDefaultSharedPreferences(this); + mPreferences = SharedPreferencesWrapper.getInstance(this, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); mResolver = getContentResolver(); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); if (BuildConfig.DEBUG) { - Log.d(LOGTAG, "Stream service started."); + Log.d(Constants.LOGTAG, "Stream service started."); } initStreaming(); mResolver.registerContentObserver(Accounts.CONTENT_URI, true, mAccountChangeObserver); @@ -101,103 +107,93 @@ public class StreamingService extends Service implements Constants, PrivateConst clearTwitterInstances(); mResolver.unregisterContentObserver(mAccountChangeObserver); if (BuildConfig.DEBUG) { - Log.d(LOGTAG, "Stream service stopped."); + Log.d(Constants.LOGTAG, "Stream service stopped."); } super.onDestroy(); } private void clearTwitterInstances() { - for (final WeakReference reference : mTwitterInstances) { - final TwidereUserStreamCallback twitter = reference.get(); - new Thread(new ShutdownStreamTwitterRunnable(twitter)).start(); + for (int i = 0, j = mCallbacks.size(); i < j; i++) { + new Thread(new ShutdownStreamTwitterRunnable(mCallbacks.valueAt(i))).start(); } - mTwitterInstances.clear(); + mCallbacks.clear(); mNotificationManager.cancel(NOTIFICATION_SERVICE_STARTED); } @SuppressWarnings("deprecation") private void initStreaming() { - if (!mPreferences.getBoolean(PREFERENCE_KEY_ENABLE_STREAMING, true)) return; - final boolean granted; - try { - granted = Twidere.isPermissionGranted(this); - } catch (final SecurityException e) { - stopSelf(); - return; - } - if (granted) { - final TwidereSharedPreferences prefs = Twidere.getSharedPreferences(this); - if (setTwitterInstances(prefs)) { - final Intent intent = new Intent(this, SettingsActivity.class); - final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - final CharSequence contentTitle = getString(R.string.app_name); - final CharSequence contentText = getString(R.string.streaming_service_running); - final Notification notification = new Notification(); - notification.flags = Notification.FLAG_ONGOING_EVENT; - notification.icon = R.drawable.ic_stat_twidere; - notification.tickerText = getString(R.string.streaming_service_running); - notification.setLatestEventInfo(this, contentTitle, contentText, contentIntent); - mNotificationManager.notify(NOTIFICATION_SERVICE_STARTED, notification); - } else { - mNotificationManager.cancel(NOTIFICATION_SERVICE_STARTED); - } - } else { - final Intent intent = new Intent(this, SettingsActivity.class); - final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - final CharSequence contentTitle = getString(R.string.app_name); - final CharSequence contentText = getString(R.string.request_permission); - final Notification notification = new Notification(); - notification.flags = Notification.FLAG_AUTO_CANCEL; - notification.icon = R.drawable.ic_stat_login; - notification.tickerText = getString(R.string.request_permission); - notification.setLatestEventInfo(this, contentTitle, contentText, contentIntent); - mNotificationManager.notify(NOTIFICATION_REQUEST_PERMISSION, notification); - } + if (!BuildConfig.DEBUG) return; + setTwitterInstances(); + updateStreamState(); } - - private boolean setTwitterInstances(final TwidereSharedPreferences prefs) { - if (prefs == null) return false; + private boolean setTwitterInstances() { final List accountsList = ParcelableAccount.getCredentialsList(this, true); - if (BuildConfig.DEBUG) { - Log.d(LOGTAG, "Setting up twitter stream instances"); + final long[] accountIds = new long[accountsList.size()]; + for (int i = 0, j = accountIds.length; i < j; i++) { + accountIds[i] = accountsList.get(i).account_id; } - mAccountIds = new long[accountsList.size()]; + final AccountPreferences[] activitedPreferences = AccountPreferences.getAccountPreferences(this, accountIds); + if (BuildConfig.DEBUG) { + Log.d(Constants.LOGTAG, "Setting up twitter stream instances"); + } + mAccountIds = accountIds; clearTwitterInstances(); + boolean result = false; for (int i = 0, j = accountsList.size(); i < j; i++) { + final AccountPreferences preferences = activitedPreferences[i]; + if (!preferences.isStreamingEnabled()) continue; final ParcelableCredentials account = accountsList.get(i); - final Endpoint endpoint = TwitterAPIUtils.getEndpoint(account, TwitterUserStream.class); - final Authorization authorization = TwitterAPIUtils.getAuthorization(account); - final TwitterUserStream twitter = Utils.getInstance(this, endpoint, authorization, TwitterUserStream.class); - final long account_id = account.account_id; - mAccountIds[i] = account_id; + final Endpoint endpoint = TwitterAPIFactory.getEndpoint(account, TwitterUserStream.class); + final Authorization authorization = TwitterAPIFactory.getAuthorization(account); + final TwitterUserStream twitter = TwitterAPIFactory.getInstance(this, endpoint, authorization, TwitterUserStream.class); final TwidereUserStreamCallback callback = new TwidereUserStreamCallback(this, account); - mTwitterInstances.add(new WeakReference<>(callback)); + mCallbacks.put(account.account_id, callback); new Thread() { @Override public void run() { twitter.getUserStream(callback); - Log.d(LOGTAG, "Stream disconnected"); + Log.d(Constants.LOGTAG, String.format("Stream %d disconnected", account.account_id)); + mCallbacks.remove(account.account_id); + updateStreamState(); } }.start(); + result |= true; + } + return result; + } + + private void updateStreamState() { + if (mCallbacks.size() > 0) { + final Intent intent = new Intent(this, SettingsActivity.class); + final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, + PendingIntent.FLAG_UPDATE_CURRENT); + final CharSequence contentTitle = getString(R.string.app_name); + final CharSequence contentText = getString(R.string.timeline_streaming_running); + final NotificationCompat.Builder builder = new NotificationCompat.Builder(this); + builder.setOngoing(true); + builder.setSmallIcon(R.drawable.ic_stat_refresh); + builder.setContentTitle(contentTitle); + builder.setContentText(contentText); + builder.setContentIntent(contentIntent); + mNotificationManager.notify(NOTIFICATION_SERVICE_STARTED, builder.build()); + } else { + mNotificationManager.cancel(NOTIFICATION_SERVICE_STARTED); } - return true; } static class ShutdownStreamTwitterRunnable implements Runnable { - private final TwidereUserStreamCallback twitter; + private final UserStreamCallback callback; - ShutdownStreamTwitterRunnable(final TwidereUserStreamCallback twitter) { - this.twitter = twitter; + ShutdownStreamTwitterRunnable(final UserStreamCallback callback) { + this.callback = callback; } @Override public void run() { - if (twitter == null) return; - Log.d(LOGTAG, "Disconnecting stream"); - twitter.disconnect(); + if (callback == null) return; + Log.d(Constants.LOGTAG, "Disconnecting stream"); + callback.disconnect(); } } @@ -216,10 +212,15 @@ public class StreamingService extends Service implements Constants, PrivateConst resolver = context.getContentResolver(); } + @Override + public void onConnected() { + + } + @Override public void onBlock(final User source, final User blockedUser) { final String message = String.format("%s blocked %s", source.getScreenName(), blockedUser.getScreenName()); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + Log.d(LOGTAG, message); } @Override @@ -259,7 +260,7 @@ public class StreamingService extends Service implements Constants, PrivateConst final ContentValues values = ContentValuesCreator.createDirectMessage(directMessage, account.account_id, false); final Uri.Builder builder = DirectMessages.Inbox.CONTENT_URI.buildUpon(); - builder.appendQueryParameter(Twidere.QUERY_PARAM_NOTIFY, "true"); + builder.appendQueryParameter(QUERY_PARAM_NOTIFY, "true"); if (values != null) { resolver.insert(builder.build(), values); } @@ -271,8 +272,35 @@ public class StreamingService extends Service implements Constants, PrivateConst public void onException(final Throwable ex) { if (ex instanceof TwitterException) { Log.w(LOGTAG, String.format("Error %d", ((TwitterException) ex).getStatusCode()), ex); + final RestHttpResponse response = ((TwitterException) ex).getHttpResponse(); + if (response != null) { + try { + final TypedData body = response.getBody(); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + body.writeTo(os); + final String charsetName; + if (body != null) { + final ContentType contentType = body.contentType(); + if (contentType != null) { + final Charset charset = contentType.getCharset(); + if (charset != null) { + charsetName = charset.name(); + } else { + charsetName = Charset.defaultCharset().name(); + } + } else { + charsetName = Charset.defaultCharset().name(); + } + } else { + charsetName = Charset.defaultCharset().name(); + } + Log.w(LOGTAG, os.toString(charsetName)); + } catch (IOException e) { + e.printStackTrace(); + } + } } else { - Log.w(LOGTAG, ex); + Log.w(Constants.LOGTAG, ex); } } @@ -280,14 +308,14 @@ public class StreamingService extends Service implements Constants, PrivateConst public void onFavorite(final User source, final User target, final Status favoritedStatus) { final String message = String.format("%s favorited %s's tweet: %s", source.getScreenName(), target.getScreenName(), favoritedStatus.getText()); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + Log.d(LOGTAG, message); } @Override public void onFollow(final User source, final User followedUser) { final String message = String .format("%s followed %s", source.getScreenName(), followedUser.getScreenName()); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + Log.d(LOGTAG, message); } @Override @@ -339,15 +367,14 @@ public class StreamingService extends Service implements Constants, PrivateConst public void onUnblock(final User source, final User unblockedUser) { final String message = String.format("%s unblocked %s", source.getScreenName(), unblockedUser.getScreenName()); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + Log.d(LOGTAG, message); } @Override public void onUnfavorite(final User source, final User target, final Status unfavoritedStatus) { final String message = String.format("%s unfavorited %s's tweet: %s", source.getScreenName(), target.getScreenName(), unfavoritedStatus.getText()); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); - + Log.d(LOGTAG, message); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java index ac98da8b6..78c3d68ed 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java @@ -105,7 +105,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import edu.tsinghua.spice.Utilies.SpiceProfilingUtil; import edu.tsinghua.spice.Utilies.TypeMappingUtil; -import edu.ucdavis.earlybird.ProfilingUtil; import static org.mariotaku.twidere.provider.TwidereDataStore.STATUSES_URIS; import static org.mariotaku.twidere.util.ContentValuesCreator.createDirectMessage; @@ -2207,8 +2206,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper { rowsDeleted = 0; } countCur.close(); - // UCD - ProfilingUtil.profile(mContext, accountId, "Download tweets, " + TwidereArrayUtils.toString(statusIds, ',', true)); //spice SpiceProfilingUtil.profile(mContext, accountId, accountId + ",Refresh," + TwidereArrayUtils.toString(statusIds, ',', true)); //end diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java b/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java index da115fbb9..1bfb61d37 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java @@ -33,7 +33,6 @@ import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener; import edu.tsinghua.spice.Utilies.SpiceProfilingUtil; import edu.tsinghua.spice.Utilies.TypeMappingUtil; -import edu.ucdavis.earlybird.ProfilingUtil; import static org.mariotaku.twidere.util.Utils.openStatus; import static org.mariotaku.twidere.util.Utils.openTweetSearch; @@ -57,8 +56,6 @@ public class OnLinkClickHandler implements OnLinkClickListener, Constants { final boolean sensitive, int start, int end) { if (manager != null && manager.isActive()) return; if (!isPrivateData()) { - // UCD - ProfilingUtil.profile(context, accountId, "Click, " + link + ", " + type); //spice SpiceProfilingUtil.profile(context, accountId, accountId + ",Visit," + link + "," + TypeMappingUtil.getLinkType(type)); //end diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java index 8f02fa962..57209a0a5 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java @@ -1111,6 +1111,10 @@ public class ThemeUtils implements Constants { return context.getResources().getColor(R.color.background_color_action_bar_dark); } + public static boolean isDarkTheme(final String name) { + return VALUE_THEME_NAME_DARK.equals(name); + } + public static final class ActionBarContextThemeWrapper extends android.support.v7.internal.view.ContextThemeWrapper { public ActionBarContextThemeWrapper(Context base, int themeres) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java index b2568312a..ebd256e1c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java @@ -2,19 +2,43 @@ package org.mariotaku.twidere.util; import android.content.Context; import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.net.SSLCertificateSocketFactory; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Pair; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.internal.Internal; +import org.mariotaku.restfu.ExceptionFactory; +import org.mariotaku.restfu.HttpRequestFactory; +import org.mariotaku.restfu.RequestInfoFactory; import org.mariotaku.restfu.RestAPIFactory; +import org.mariotaku.restfu.RestMethodInfo; +import org.mariotaku.restfu.RestRequestInfo; +import org.mariotaku.restfu.annotation.RestMethod; import org.mariotaku.restfu.http.Authorization; import org.mariotaku.restfu.http.Endpoint; +import org.mariotaku.restfu.http.FileValue; import org.mariotaku.restfu.http.RestHttpClient; +import org.mariotaku.restfu.http.RestHttpRequest; +import org.mariotaku.restfu.http.RestHttpResponse; +import org.mariotaku.restfu.http.mime.StringTypedData; +import org.mariotaku.restfu.http.mime.TypedData; import org.mariotaku.twidere.TwidereConstants; import org.mariotaku.twidere.api.twitter.Twitter; +import org.mariotaku.twidere.api.twitter.TwitterException; +import org.mariotaku.twidere.api.twitter.TwitterOAuth; +import org.mariotaku.twidere.api.twitter.TwitterUpload; +import org.mariotaku.twidere.api.twitter.TwitterUserStream; +import org.mariotaku.twidere.api.twitter.auth.BasicAuthorization; +import org.mariotaku.twidere.api.twitter.auth.EmptyAuthorization; import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization; +import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint; +import org.mariotaku.twidere.api.twitter.auth.OAuthToken; import org.mariotaku.twidere.api.twitter.util.TwitterConverter; import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.model.ConsumerKeyType; @@ -24,7 +48,13 @@ import org.mariotaku.twidere.util.net.OkHttpRestClient; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketAddress; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static android.text.TextUtils.isEmpty; @@ -109,29 +139,237 @@ public class TwitterAPIFactory implements TwidereConstants { final String consumerSecret = ((OAuthAuthorization) auth).getConsumerSecret(); final ConsumerKeyType officialKeyType = TwitterContentUtils.getOfficialKeyType(context, consumerKey, consumerSecret); if (officialKeyType != ConsumerKeyType.UNKNOWN) { - userAgent = TwitterAPIUtils.getUserAgentName(officialKeyType); + userAgent = getUserAgentName(officialKeyType); } else { - userAgent = TwitterAPIUtils.getTwidereUserAgent(context); + userAgent = getTwidereUserAgent(context); } } else { - userAgent = TwitterAPIUtils.getTwidereUserAgent(context); + userAgent = getTwidereUserAgent(context); } factory.setClient(getDefaultHttpClient(context)); factory.setConverter(new TwitterConverter()); factory.setEndpoint(endpoint); factory.setAuthorization(auth); - factory.setRequestInfoFactory(new TwitterAPIUtils.TwidereRequestInfoFactory()); - factory.setHttpRequestFactory(new TwitterAPIUtils.TwidereHttpRequestFactory(userAgent)); - factory.setExceptionFactory(new TwitterAPIUtils.TwidereExceptionFactory()); + factory.setRequestInfoFactory(new TwidereRequestInfoFactory()); + factory.setHttpRequestFactory(new TwidereHttpRequestFactory(userAgent)); + factory.setExceptionFactory(new TwidereExceptionFactory()); return factory.build(cls); } public static T getInstance(final Context context, final Endpoint endpoint, final ParcelableCredentials credentials, Class cls) { - return TwitterAPIFactory.getInstance(context, endpoint, TwitterAPIUtils.getAuthorization(credentials), cls); + return TwitterAPIFactory.getInstance(context, endpoint, getAuthorization(credentials), cls); } static T getInstance(final Context context, final ParcelableCredentials credentials, final Class cls) { if (credentials == null) return null; - return TwitterAPIFactory.getInstance(context, TwitterAPIUtils.getEndpoint(credentials, cls), credentials, cls); + return TwitterAPIFactory.getInstance(context, getEndpoint(credentials, cls), credentials, cls); + } + + public static Endpoint getEndpoint(ParcelableCredentials credentials, Class cls) { + final String apiUrlFormat; + final boolean sameOAuthSigningUrl = credentials.same_oauth_signing_url; + final boolean noVersionSuffix = credentials.no_version_suffix; + if (!isEmpty(credentials.api_url_format)) { + apiUrlFormat = credentials.api_url_format; + } else { + apiUrlFormat = DEFAULT_TWITTER_API_URL_FORMAT; + } + final String domain, versionSuffix; + if (Twitter.class.isAssignableFrom(cls)) { + domain = "api"; + versionSuffix = noVersionSuffix ? null : "/1.1/"; + } else if (TwitterUpload.class.isAssignableFrom(cls)) { + domain = "upload"; + versionSuffix = noVersionSuffix ? null : "/1.1/"; + } else if (TwitterOAuth.class.isAssignableFrom(cls)) { + domain = "api"; + versionSuffix = "oauth"; + } else if (TwitterUserStream.class.isAssignableFrom(cls)) { + domain = "userstream"; + versionSuffix = noVersionSuffix ? null : "/1.1/"; + } else { + throw new TwitterConverter.UnsupportedTypeException(cls); + } + final String endpointUrl; + endpointUrl = getApiUrl(apiUrlFormat, domain, versionSuffix); + if (credentials.auth_type == ParcelableCredentials.AUTH_TYPE_XAUTH || credentials.auth_type == ParcelableCredentials.AUTH_TYPE_OAUTH) { + final String signEndpointUrl; + if (!sameOAuthSigningUrl) { + signEndpointUrl = getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix); + } else { + signEndpointUrl = endpointUrl; + } + return new OAuthEndpoint(endpointUrl, signEndpointUrl); + } + return new Endpoint(endpointUrl); + } + + public static Authorization getAuthorization(ParcelableCredentials credentials) { + switch (credentials.auth_type) { + case ParcelableCredentials.AUTH_TYPE_OAUTH: + case ParcelableCredentials.AUTH_TYPE_XAUTH: { + final String consumerKey = TextUtils.isEmpty(credentials.consumer_key) ? + TWITTER_CONSUMER_KEY_LEGACY : credentials.consumer_key; + final String consumerSecret = TextUtils.isEmpty(credentials.consumer_secret) ? + TWITTER_CONSUMER_SECRET_LEGACY : credentials.consumer_secret; + final OAuthToken accessToken = new OAuthToken(credentials.oauth_token, credentials.oauth_token_secret); + return new OAuthAuthorization(consumerKey, consumerSecret, accessToken); + } + case ParcelableCredentials.AUTH_TYPE_BASIC: { + final String screenName = credentials.screen_name; + final String username = credentials.basic_auth_username; + final String loginName = username != null ? username : screenName; + final String password = credentials.basic_auth_password; + if (isEmpty(loginName) || isEmpty(password)) return null; + return new BasicAuthorization(loginName, password); + } + } + return new EmptyAuthorization(); + } + + private static void addParameter(List> params, String name, Object value) { + params.add(Pair.create(name, String.valueOf(value))); + } + + private static void addPart(List> params, String name, Object value) { + final TypedData typedData = new StringTypedData(String.valueOf(value), Charset.defaultCharset()); + params.add(Pair.create(name, typedData)); + } + + public static String getApiBaseUrl(String format, final String domain) { + if (format == null) return null; + final Matcher matcher = Pattern.compile("\\[(\\.?)DOMAIN(\\.?)\\]").matcher(format); + if (!matcher.find()) { + // For backward compatibility + format = substituteLegacyApiBaseUrl(format, domain); + if (!format.endsWith("/1.1") && !format.endsWith("/1.1/")) { + return format; + } + final String versionSuffix = "/1.1"; + final int suffixLength = versionSuffix.length(); + final int lastIndex = format.lastIndexOf(versionSuffix); + return format.substring(0, lastIndex) + format.substring(lastIndex + suffixLength); + } + if (TextUtils.isEmpty(domain)) return matcher.replaceAll(""); + return matcher.replaceAll(String.format("$1%s$2", domain)); + } + + private static String substituteLegacyApiBaseUrl(@NonNull String format, String domain) { + final int startOfHost = format.indexOf("://") + 3, endOfHost = format.indexOf('/', startOfHost); + final String host = endOfHost != -1 ? format.substring(startOfHost, endOfHost) : format.substring(startOfHost); + if (!host.equalsIgnoreCase("api.twitter.com")) return format; + return format.substring(0, startOfHost) + domain + ".twitter.com" + format.substring(endOfHost); + } + + public static String getApiUrl(final String pattern, final String domain, final String appendPath) { + final String urlBase = getApiBaseUrl(pattern, domain); + if (urlBase == null) return null; + if (appendPath == null) return urlBase.endsWith("/") ? urlBase : urlBase + "/"; + final StringBuilder sb = new StringBuilder(urlBase); + if (urlBase.endsWith("/")) { + sb.append(appendPath.startsWith("/") ? appendPath.substring(1) : appendPath); + } else { + if (appendPath.startsWith("/")) { + sb.append(appendPath); + } else { + sb.append('/'); + sb.append(appendPath); + } + } + return sb.toString(); + } + + public static String getUserAgentName(ConsumerKeyType type) { + switch (type) { + case TWITTER_FOR_ANDROID: { + return "TwitterAndroid"; + } + case TWITTER_FOR_IPHONE: { + return "Twitter-iPhone"; + } + case TWITTER_FOR_IPAD: { + return "Twitter-iPad"; + } + case TWITTER_FOR_MAC: { + return "Twitter-Mac"; + } + } + return "Twitter"; + } + + public static String getTwidereUserAgent(final Context context) { + final PackageManager pm = context.getPackageManager(); + try { + final PackageInfo pi = pm.getPackageInfo(TWIDERE_PACKAGE_NAME, 0); + return TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL + " / " + pi.versionName; + } catch (final PackageManager.NameNotFoundException e) { + return TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL; + } + } + + public static class TwidereRequestInfoFactory implements RequestInfoFactory { + @Override + public RestRequestInfo create(RestMethodInfo methodInfo) { + final RestMethod method = methodInfo.getMethod(); + final String path = methodInfo.getPath(); + final List> queries = new ArrayList<>(methodInfo.getQueries()); + final List> forms = new ArrayList<>(methodInfo.getForms()); + final List> headers = methodInfo.getHeaders(); + final List> parts = methodInfo.getParts(); + final FileValue file = methodInfo.getFile(); + final Map extras = methodInfo.getExtras(); + if (parts.isEmpty()) { + final List> params = method.hasBody() ? forms : queries; + addParameter(params, "include_cards", true); + addParameter(params, "cards_platform", "Android-12"); + addParameter(params, "include_entities", true); + addParameter(params, "include_my_retweet", 1); + addParameter(params, "include_rts", 1); + addParameter(params, "include_reply_count", true); + addParameter(params, "include_descendent_reply_count", true); + } else { + addPart(parts, "include_cards", true); + addPart(parts, "cards_platform", "Android-12"); + addPart(parts, "include_entities", true); + addPart(parts, "include_my_retweet", 1); + addPart(parts, "include_rts", 1); + addPart(parts, "include_reply_count", true); + addPart(parts, "include_descendent_reply_count", true); + } + return new RestRequestInfo(method.value(), path, queries, forms, headers, parts, file, + methodInfo.getBody(), extras); + } + } + + public static class TwidereHttpRequestFactory implements HttpRequestFactory { + + private final String userAgent; + + public TwidereHttpRequestFactory(final String userAgent) { + this.userAgent = userAgent; + } + + @Override + public RestHttpRequest create(@NonNull Endpoint endpoint, @NonNull RestRequestInfo info, + @Nullable Authorization authorization) { + final String restMethod = info.getMethod(); + final String url = Endpoint.constructUrl(endpoint.getUrl(), info); + final ArrayList> headers = new ArrayList<>(info.getHeaders()); + + if (authorization != null && authorization.hasAuthorization()) { + headers.add(Pair.create("Authorization", authorization.getHeader(endpoint, info))); + } + headers.add(Pair.create("User-Agent", userAgent)); + return new RestHttpRequest(restMethod, url, headers, info.getBody(), null); + } + } + + public static class TwidereExceptionFactory implements ExceptionFactory { + @Override + public Exception newException(Throwable cause, RestHttpRequest request, RestHttpResponse response) { + final TwitterException te = new TwitterException(cause); + te.setResponse(response); + return te; + } } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java index 2ab1bbe5e..7c9ce3867 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -252,7 +252,6 @@ import java.util.zip.CRC32; import javax.net.ssl.SSLException; import edu.tsinghua.spice.SpiceService; -import edu.ucdavis.earlybird.UCDService; import static android.text.TextUtils.isEmpty; import static android.text.format.DateUtils.getRelativeTimeSpanString; @@ -3418,15 +3417,12 @@ public final class Utils implements Constants { public static void startUsageStatisticsServiceIfNeeded(final Context context) { final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - final Intent profilingServiceIntent = new Intent(context, UCDService.class); //spice final Intent spiceProfilingServiceIntent = new Intent(context, SpiceService.class); if (prefs.getBoolean(KEY_USAGE_STATISTICS, false)) { - context.startService(profilingServiceIntent); //spice context.startService(spiceProfilingServiceIntent); } else { - context.stopService(profilingServiceIntent); //spice context.stopService(spiceProfilingServiceIntent); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/TwidereImageDownloader.java b/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/TwidereImageDownloader.java index b425e33a6..2a3216eda 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/TwidereImageDownloader.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/imageloader/TwidereImageDownloader.java @@ -51,7 +51,6 @@ import org.mariotaku.twidere.model.ParcelableMedia; import org.mariotaku.twidere.util.MediaPreviewUtils; import org.mariotaku.twidere.util.SharedPreferencesWrapper; import org.mariotaku.twidere.util.TwidereLinkify; -import org.mariotaku.twidere.util.TwitterAPIUtils; import org.mariotaku.twidere.util.TwitterAPIFactory; import org.mariotaku.twidere.util.Utils; @@ -129,7 +128,7 @@ public class TwidereImageDownloader extends BaseImageDownloader implements Const final String host = uri.getHost(); final String domain = host.substring(0, host.lastIndexOf(".twitter.com")); final String path = uri.getPath(); - sb.append(TwitterAPIUtils.getApiUrl(apiUrlFormat, domain, path)); + sb.append(TwitterAPIFactory.getApiUrl(apiUrlFormat, domain, path)); final String query = uri.getQuery(); if (!TextUtils.isEmpty(query)) { sb.append("?"); @@ -152,7 +151,7 @@ public class TwidereImageDownloader extends BaseImageDownloader implements Const if (isTwitterAuthRequired(uri) && extras instanceof AccountExtra) { final AccountExtra accountExtra = (AccountExtra) extras; account = ParcelableAccount.getCredentials(mContext, accountExtra.account_id); - auth = TwitterAPIUtils.getAuthorization(account); + auth = TwitterAPIFactory.getAuthorization(account); } else { account = null; auth = null; diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/net/OkHttpRestClient.java b/twidere/src/main/java/org/mariotaku/twidere/util/net/OkHttpRestClient.java index 96b18024a..cb516dfef 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/net/OkHttpRestClient.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/net/OkHttpRestClient.java @@ -38,6 +38,7 @@ import org.mariotaku.restfu.http.RestHttpClient; import org.mariotaku.restfu.http.RestHttpRequest; import org.mariotaku.restfu.http.RestHttpResponse; import org.mariotaku.restfu.http.mime.TypedData; +import org.mariotaku.twidere.util.DebugModeUtils; import java.io.IOException; import java.io.InputStream; @@ -60,6 +61,7 @@ public class OkHttpRestClient implements RestHttpClient { public OkHttpRestClient(OkHttpClient client) { this.client = client; + DebugModeUtils.initForHttpClient(client); } @NonNull diff --git a/twidere/src/main/res-localized/layout/action_item_space.xml b/twidere/src/main/res-localized/layout/action_item_space.xml new file mode 100644 index 000000000..9066c7adf --- /dev/null +++ b/twidere/src/main/res-localized/layout/action_item_space.xml @@ -0,0 +1,24 @@ + + + + diff --git a/twidere/src/main/res-svg2png/drawable-hdpi/ic_stat_refresh.png b/twidere/src/main/res-svg2png/drawable-hdpi/ic_stat_refresh.png new file mode 100644 index 000000000..88ba05552 Binary files /dev/null and b/twidere/src/main/res-svg2png/drawable-hdpi/ic_stat_refresh.png differ diff --git a/twidere/src/main/res-svg2png/drawable-mdpi/ic_stat_refresh.png b/twidere/src/main/res-svg2png/drawable-mdpi/ic_stat_refresh.png new file mode 100644 index 000000000..3e21d72b8 Binary files /dev/null and b/twidere/src/main/res-svg2png/drawable-mdpi/ic_stat_refresh.png differ diff --git a/twidere/src/main/res-svg2png/drawable-xhdpi/ic_stat_refresh.png b/twidere/src/main/res-svg2png/drawable-xhdpi/ic_stat_refresh.png new file mode 100644 index 000000000..693a2ec15 Binary files /dev/null and b/twidere/src/main/res-svg2png/drawable-xhdpi/ic_stat_refresh.png differ diff --git a/twidere/src/main/res-svg2png/drawable-xxhdpi/ic_stat_refresh.png b/twidere/src/main/res-svg2png/drawable-xxhdpi/ic_stat_refresh.png new file mode 100644 index 000000000..5eb74d428 Binary files /dev/null and b/twidere/src/main/res-svg2png/drawable-xxhdpi/ic_stat_refresh.png differ diff --git a/twidere/src/main/res-svg2png/drawable-xxxhdpi/ic_stat_refresh.png b/twidere/src/main/res-svg2png/drawable-xxxhdpi/ic_stat_refresh.png new file mode 100644 index 000000000..8834f7a8c Binary files /dev/null and b/twidere/src/main/res-svg2png/drawable-xxxhdpi/ic_stat_refresh.png differ diff --git a/twidere/src/main/res/layout/fragment_accounts_dashboard.xml b/twidere/src/main/res/layout/fragment_accounts_dashboard.xml index 6a73c6859..3d665a5a6 100644 --- a/twidere/src/main/res/layout/fragment_accounts_dashboard.xml +++ b/twidere/src/main/res/layout/fragment_accounts_dashboard.xml @@ -18,12 +18,29 @@ ~ along with this program. If not, see . --> - + android:divider="?dividerVertical" + android:orientation="vertical" + android:showDividers="middle"> + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/list_item_dashboard_menu.xml b/twidere/src/main/res/layout/list_item_dashboard_menu.xml new file mode 100644 index 000000000..1d94cad89 --- /dev/null +++ b/twidere/src/main/res/layout/list_item_dashboard_menu.xml @@ -0,0 +1,52 @@ + + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/list_item_menu.xml b/twidere/src/main/res/layout/list_item_menu.xml index d07a7bb60..e231dc745 100644 --- a/twidere/src/main/res/layout/list_item_menu.xml +++ b/twidere/src/main/res/layout/list_item_menu.xml @@ -22,7 +22,7 @@ android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:gravity="center_vertical" - android:minHeight="48dp" + android:minHeight="?listPreferredItemHeightSmall" android:orientation="horizontal"> + + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/values/strings.xml b/twidere/src/main/res/values/strings.xml index d67d75a66..475f15117 100644 --- a/twidere/src/main/res/values/strings.xml +++ b/twidere/src/main/res/values/strings.xml @@ -44,6 +44,7 @@ Password Twidere database provider Refresh service + Streaming service Background operation service Open in browser Tap to load more @@ -754,4 +755,8 @@ Play Pause Jump to top + Timeline streaming running + Streaming + Enable streaming + Dark theme \ No newline at end of file diff --git a/twidere/src/main/res/xml/preferences_account_refresh.xml b/twidere/src/main/res/xml/preferences_account_refresh.xml index 0dc42c8dc..820014226 100644 --- a/twidere/src/main/res/xml/preferences_account_refresh.xml +++ b/twidere/src/main/res/xml/preferences_account_refresh.xml @@ -3,7 +3,13 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/auto_refresh"> + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/xml/preferences_notifications.xml b/twidere/src/main/res/xml/preferences_notifications.xml index fcc35ff46..dcb6da7ba 100644 --- a/twidere/src/main/res/xml/preferences_notifications.xml +++ b/twidere/src/main/res/xml/preferences_notifications.xml @@ -18,12 +18,6 @@ android:summary="@string/silent_notifications_summary" android:title="@string/silent_notifications"/> - - - @@ -7,20 +8,18 @@ android:key="cat_theme_preview" android:order="11" android:title="@string/preview"> - + - + android:key="theme" + android:title="@string/dark_theme"> - + android:value="true"/> + + android:value="true"/> + android:value="true"/> diff --git a/twidere/src/main/svg-png/ic_stat_refresh-mdpi.svg b/twidere/src/main/svg-png/ic_stat_refresh-mdpi.svg new file mode 100644 index 000000000..84c386e68 --- /dev/null +++ b/twidere/src/main/svg-png/ic_stat_refresh-mdpi.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twidere.extension.streaming/src/androidTest/java/org/mariotaku/twidere/extension/streaming/ApplicationTest.java b/twidere/src/release/java/org/mariotaku/twidere/util/DebugModeUtils.java similarity index 66% rename from twidere.extension.streaming/src/androidTest/java/org/mariotaku/twidere/extension/streaming/ApplicationTest.java rename to twidere/src/release/java/org/mariotaku/twidere/util/DebugModeUtils.java index 6f3b2f23d..a03bf90cf 100644 --- a/twidere.extension.streaming/src/androidTest/java/org/mariotaku/twidere/extension/streaming/ApplicationTest.java +++ b/twidere/src/release/java/org/mariotaku/twidere/util/DebugModeUtils.java @@ -1,5 +1,5 @@ /* - * Twidere - Twitter client for Android + * Twidere - Twitter client for Android * * Copyright (C) 2012-2015 Mariotaku Lee * @@ -17,16 +17,24 @@ * along with this program. If not, see . */ -package org.mariotaku.twidere.extension.streaming; +package org.mariotaku.twidere.util; import android.app.Application; -import android.test.ApplicationTestCase; + +import com.squareup.okhttp.OkHttpClient; /** - * Testing Fundamentals + * Created by mariotaku on 15/5/27. */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); +public class DebugModeUtils { + + public static void initForHttpClient(final OkHttpClient client) { + // No-op } -} \ No newline at end of file + + + public static void initForApplication(final Application application) { + // No-op + } + +}