added account operations in debug mode
fixed share media for ExoPlayer
This commit is contained in:
parent
4d4f6f382d
commit
7dfc647797
|
@ -39,6 +39,7 @@ import com.fasterxml.jackson.core.JsonToken;
|
|||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableNoThanks;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
|
||||
import org.mariotaku.commons.logansquare.JsonStringConverter;
|
||||
import org.mariotaku.twidere.annotation.AccountType;
|
||||
import org.mariotaku.twidere.model.account.AccountExtras;
|
||||
import org.mariotaku.twidere.model.account.cred.Credentials;
|
||||
|
@ -85,12 +86,13 @@ public class AccountDetails implements Parcelable, Comparable<AccountDetails> {
|
|||
@JsonField(name = "dummy")
|
||||
public boolean dummy;
|
||||
|
||||
@JsonField(name = "credentials")
|
||||
@JsonField(name = "credentials", typeConverter = JsonStringConverter.class)
|
||||
@ParcelableNoThanks
|
||||
String credentials_json;
|
||||
|
||||
public Credentials credentials;
|
||||
|
||||
@JsonField(name = "extras")
|
||||
@JsonField(name = "extras", typeConverter = JsonStringConverter.class)
|
||||
@ParcelableNoThanks
|
||||
String extras_json;
|
||||
public AccountExtras extras;
|
||||
|
|
|
@ -71,4 +71,11 @@ public class StatusNetAccountExtras implements Parcelable, AccountExtras {
|
|||
public void writeToParcel(Parcel dest, int flags) {
|
||||
StatusNetAccountExtrasParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StatusNetAccountExtras{" +
|
||||
"textLimit=" + textLimit +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,4 +71,11 @@ public class TwitterAccountExtras implements Parcelable, AccountExtras {
|
|||
public void writeToParcel(Parcel dest, int flags) {
|
||||
TwitterAccountExtrasParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TwitterAccountExtras{" +
|
||||
"officialCredentials=" + officialCredentials +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,14 @@ public class BasicCredentials extends Credentials implements Parcelable {
|
|||
BasicCredentialsParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BasicCredentials{" +
|
||||
"username='" + username + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
"} " + super.toString();
|
||||
}
|
||||
|
||||
public static final Creator<BasicCredentials> CREATOR = new Creator<BasicCredentials>() {
|
||||
public BasicCredentials createFromParcel(Parcel source) {
|
||||
BasicCredentials target = new BasicCredentials();
|
||||
|
|
|
@ -65,6 +65,14 @@ public class Credentials implements Parcelable {
|
|||
CredentialsParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Credentials{" +
|
||||
"api_url_format='" + api_url_format + '\'' +
|
||||
", no_version_suffix=" + no_version_suffix +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static final Creator<Credentials> CREATOR = new Creator<Credentials>() {
|
||||
public Credentials createFromParcel(Parcel source) {
|
||||
Credentials target = new Credentials();
|
||||
|
|
|
@ -44,6 +44,11 @@ public class EmptyCredentials extends Credentials implements Parcelable {
|
|||
EmptyCredentialsParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EmptyCredentials{} " + super.toString();
|
||||
}
|
||||
|
||||
public static final Creator<EmptyCredentials> CREATOR = new Creator<EmptyCredentials>() {
|
||||
public EmptyCredentials createFromParcel(Parcel source) {
|
||||
EmptyCredentials target = new EmptyCredentials();
|
||||
|
|
|
@ -44,6 +44,11 @@ public class OAuth2Credentials extends Credentials implements Parcelable {
|
|||
OAuth2CredentialsParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OAuth2Credentials{} " + super.toString();
|
||||
}
|
||||
|
||||
public static final Creator<OAuth2Credentials> CREATOR = new Creator<OAuth2Credentials>() {
|
||||
public OAuth2Credentials createFromParcel(Parcel source) {
|
||||
OAuth2Credentials target = new OAuth2Credentials();
|
||||
|
|
|
@ -58,6 +58,17 @@ public class OAuthCredentials extends Credentials implements Parcelable {
|
|||
OAuthCredentialsParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OAuthCredentials{" +
|
||||
"consumer_key='" + consumer_key + '\'' +
|
||||
", consumer_secret='" + consumer_secret + '\'' +
|
||||
", access_token='" + access_token + '\'' +
|
||||
", access_token_secret='" + access_token_secret + '\'' +
|
||||
", same_oauth_signing_url=" + same_oauth_signing_url +
|
||||
"} " + super.toString();
|
||||
}
|
||||
|
||||
public static final Creator<OAuthCredentials> CREATOR = new Creator<OAuthCredentials>() {
|
||||
public OAuthCredentials createFromParcel(Parcel source) {
|
||||
OAuthCredentials target = new OAuthCredentials();
|
||||
|
|
|
@ -34,8 +34,8 @@ android {
|
|||
applicationId "org.mariotaku.twidere"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 25
|
||||
versionCode 297
|
||||
versionName '3.4.35'
|
||||
versionCode 298
|
||||
versionName '3.4.36'
|
||||
multiDexEnabled true
|
||||
|
||||
buildConfigField 'boolean', 'LEAK_CANARY_ENABLED', 'Boolean.parseBoolean("true")'
|
||||
|
@ -117,6 +117,7 @@ dependencies {
|
|||
debugCompile "com.facebook.stetho:stetho-okhttp3:${libVersions['Stetho']}"
|
||||
debugCompile "com.facebook.stetho:stetho-js-rhino:${libVersions['Stetho']}"
|
||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
|
||||
debugCompile 'com.jayway.jsonpath:json-path:2.2.0'
|
||||
|
||||
provided 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
|
|
|
@ -19,22 +19,35 @@
|
|||
|
||||
package org.mariotaku.twidere.util.stetho
|
||||
|
||||
import android.accounts.Account
|
||||
import android.accounts.AccountManager
|
||||
import android.content.Context
|
||||
import android.util.Base64
|
||||
import android.util.Base64InputStream
|
||||
import android.util.Base64OutputStream
|
||||
import com.bluelinelabs.logansquare.LoganSquare
|
||||
import com.facebook.stetho.dumpapp.DumpException
|
||||
import com.facebook.stetho.dumpapp.DumperContext
|
||||
import com.facebook.stetho.dumpapp.DumperPlugin
|
||||
import com.jayway.jsonpath.Configuration
|
||||
import com.jayway.jsonpath.DocumentContext
|
||||
import com.jayway.jsonpath.JsonPath
|
||||
import com.jayway.jsonpath.TypeRef
|
||||
import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider
|
||||
import com.jayway.jsonpath.spi.mapper.MappingProvider
|
||||
import org.apache.commons.cli.GnuParser
|
||||
import org.apache.commons.cli.Options
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.mariotaku.ktextension.HexColorFormat
|
||||
import org.mariotaku.ktextension.subArray
|
||||
import org.mariotaku.ktextension.toHexColor
|
||||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.model.AccountDetails
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.util.DataStoreUtils
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
@ -99,12 +112,49 @@ class AccountsDumper(val context: Context) : DumperPlugin {
|
|||
}
|
||||
}
|
||||
"list" -> {
|
||||
val am = AccountManager.get(context)
|
||||
val accounts = AccountUtils.getAllAccountDetails(am, true)
|
||||
accounts.forEach {
|
||||
dumpContext.stdout.println(it.key)
|
||||
val keys = DataStoreUtils.getAccountKeys(context)
|
||||
keys.forEach {
|
||||
dumpContext.stdout.println(it)
|
||||
}
|
||||
}
|
||||
"get" -> {
|
||||
val subCommandArgs = argsAsList.subArray(1..argsAsList.lastIndex)
|
||||
if (subCommandArgs.isEmpty()) {
|
||||
throw DumpException("Account key required")
|
||||
}
|
||||
val docContext = try {
|
||||
accountDocContext(subCommandArgs[0])
|
||||
} catch (e: Utils.NoAccountException) {
|
||||
throw DumpException("Account not found")
|
||||
}
|
||||
if (subCommandArgs.size == 1) {
|
||||
val result = docContext.read("$", Object::class.java)
|
||||
dumpContext.stdout.println(result?.prettyPrint())
|
||||
} else for (i in 1..subCommandArgs.lastIndex) {
|
||||
val result = docContext.read(subCommandArgs[i], Object::class.java)
|
||||
dumpContext.stdout.println(result?.prettyPrint())
|
||||
}
|
||||
}
|
||||
"set" -> {
|
||||
val subCommandArgs = argsAsList.subArray(1..argsAsList.lastIndex)
|
||||
if (subCommandArgs.size != 3) {
|
||||
throw DumpException("Usage: accounts set <account_key> <field> <value>")
|
||||
}
|
||||
val docContext = try {
|
||||
accountDocContext(subCommandArgs[0])
|
||||
} catch (e: Utils.NoAccountException) {
|
||||
throw DumpException("Account not found")
|
||||
}
|
||||
val value = subCommandArgs[2]
|
||||
val path = subCommandArgs[1]
|
||||
docContext.set(path, value)
|
||||
val details = docContext.read("$", Object::class.java)?.let {
|
||||
LoganSquare.parse(it.toString(), AccountDetails::class.java)
|
||||
} ?: return
|
||||
val am = AccountManager.get(context)
|
||||
details.account.updateDetails(am, details)
|
||||
dumpContext.stdout.println("$path = ${docContext.read(path, Object::class.java)?.prettyPrint()}")
|
||||
}
|
||||
else -> {
|
||||
dumpContext.stderr.println("Usage: accounts [import|export] -p <password>")
|
||||
}
|
||||
|
@ -112,6 +162,25 @@ class AccountsDumper(val context: Context) : DumperPlugin {
|
|||
|
||||
}
|
||||
|
||||
private fun accountDocContext(forKey: String): DocumentContext {
|
||||
val accountKey = UserKey.valueOf(forKey)
|
||||
val am = AccountManager.get(context)
|
||||
val details = AccountUtils.getAccountDetails(am, accountKey, true) ?: throw Utils.NoAccountException()
|
||||
val configuration = Configuration.builder()
|
||||
.jsonProvider(JsonOrgJsonProvider())
|
||||
.mappingProvider(AsIsMappingProvider())
|
||||
.build()
|
||||
return JsonPath.parse(LoganSquare.serialize(details), configuration)
|
||||
}
|
||||
|
||||
private fun Any.prettyPrint() = if (this is JSONObject) {
|
||||
toString(4)
|
||||
} else if (this is JSONArray) {
|
||||
toString(4)
|
||||
} else {
|
||||
toString()
|
||||
}
|
||||
|
||||
private fun exportAccounts(password: String, output: OutputStream) {
|
||||
val secret = generateSecret(password)
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
|
@ -151,20 +220,24 @@ class AccountsDumper(val context: Context) : DumperPlugin {
|
|||
if (account !in usedAccounts) {
|
||||
am.addAccountExplicitly(account, null, null)
|
||||
}
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_KEY, details.key.toString())
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_TYPE, details.type)
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_CREDS_TYPE, details.credentials_type)
|
||||
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_ACTIVATED, true.toString())
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_COLOR, toHexColor(details.color, format = HexColorFormat.RGB))
|
||||
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_USER, LoganSquare.serialize(details.user))
|
||||
am.setUserData(account, ACCOUNT_USER_DATA_EXTRAS, details.extras?.let { LoganSquare.serialize(it) })
|
||||
am.setAuthToken(account, ACCOUNT_AUTH_TOKEN_TYPE, LoganSquare.serialize(details.credentials))
|
||||
account.updateDetails(am, details)
|
||||
}
|
||||
output.println("Done.")
|
||||
}
|
||||
|
||||
private fun Account.updateDetails(am: AccountManager, details: AccountDetails) {
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_KEY, details.key.toString())
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_TYPE, details.type)
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_CREDS_TYPE, details.credentials_type)
|
||||
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_ACTIVATED, true.toString())
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_COLOR, toHexColor(details.color, format = HexColorFormat.RGB))
|
||||
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_USER, LoganSquare.serialize(details.user))
|
||||
am.setUserData(this, ACCOUNT_USER_DATA_EXTRAS, details.extras?.let { LoganSquare.serialize(it) })
|
||||
am.setAuthToken(this, ACCOUNT_AUTH_TOKEN_TYPE, LoganSquare.serialize(details.credentials))
|
||||
}
|
||||
|
||||
fun ByteArray.toInt(): Int {
|
||||
val bb = ByteBuffer.wrap(this)
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN)
|
||||
|
@ -183,4 +256,17 @@ class AccountsDumper(val context: Context) : DumperPlugin {
|
|||
return SecretKeySpec(factory.generateSecret(spec).encoded, "AES")
|
||||
}
|
||||
|
||||
internal class AsIsMappingProvider : MappingProvider {
|
||||
override fun <T : Any?> map(source: Any?, type: Class<T>, configuration: Configuration): T {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return source as T
|
||||
}
|
||||
|
||||
override fun <T : Any?> map(source: Any?, type: TypeRef<T>, configuration: Configuration): T {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return source as T
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,7 +60,11 @@ class RawStreamDumper(val context: Context) : DumperPlugin {
|
|||
userStream.getUserStreamRaw(object : RawCallback<MicroBlogException> {
|
||||
override fun result(result: HttpResponse) {
|
||||
dumpContext.stdout.println("Response: ${result.status}")
|
||||
dumpContext.stdout.println("Headers: ${result.headers}")
|
||||
dumpContext.stdout.println("Headers:")
|
||||
result.headers.toList().forEach {
|
||||
dumpContext.stdout.println("${it.first}: ${it.second}")
|
||||
}
|
||||
dumpContext.stdout.println()
|
||||
result.body.writeTo(dumpContext.stdout)
|
||||
}
|
||||
|
||||
|
|
|
@ -197,7 +197,8 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos
|
|||
return true
|
||||
}
|
||||
R.id.share -> {
|
||||
if (obj is CacheDownloadMediaViewerFragment) {
|
||||
val fileInfo = obj.cacheFileInfo()
|
||||
if (fileInfo != null) {
|
||||
requestAndShareMedia(currentItem)
|
||||
} else {
|
||||
val media = media[currentItem]
|
||||
|
|
|
@ -134,6 +134,14 @@ fun <T> newMicroBlogInstance(context: Context, endpoint: Endpoint, auth: Authori
|
|||
holder.connectionPool, holder.cache)
|
||||
factory.setHttpClient(uploadHttpClient)
|
||||
}
|
||||
TwitterUserStream::class -> {
|
||||
val conf = HttpClientFactory.HttpClientConfiguration(holder.preferences)
|
||||
// Use longer read timeout for streaming
|
||||
conf.readTimeoutSecs = 300
|
||||
val uploadHttpClient = HttpClientFactory.createRestHttpClient(conf, holder.dns,
|
||||
holder.connectionPool, holder.cache)
|
||||
factory.setHttpClient(uploadHttpClient)
|
||||
}
|
||||
else -> {
|
||||
factory.setHttpClient(holder.restHttpClient)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue