pref: 修改高版本 API

This commit is contained in:
HuanCheng65 2022-06-23 20:19:42 +08:00
parent 06ea76c53f
commit b7ea0723f1
No known key found for this signature in database
GPG Key ID: E9031EF91A805148
18 changed files with 2357 additions and 27 deletions

View File

@ -2,6 +2,7 @@ plugins {
id "com.android.application"
id "kotlin-android"
id "kotlin-kapt"
id 'com.google.protobuf'
}
def keystoreProperties = new Properties()
@ -70,9 +71,20 @@ android {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
sourceSets {
main {
proto {
srcDir 'src/main/proto'
}
}
}
}
dependencies {
implementation 'com.google.protobuf:protobuf-java:3.21.1'
implementation 'com.github.gzu-liyujiang:Android_CN_OAID:4.2.4'
implementation 'org.jetbrains:annotations:23.0.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
@ -101,7 +113,6 @@ dependencies {
implementation "androidx.window:window:1.0.0-beta03"
implementation "androidx.startup:startup-runtime:1.1.0"
//Test
testImplementation "junit:junit:4.13.2"
androidTestImplementation "androidx.test:core:1.4.0"
@ -120,6 +131,7 @@ dependencies {
implementation "com.squareup.okhttp3:okhttp:4.9.1"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.retrofit2:converter-protobuf:$retrofit_version"
implementation 'com.google.code.gson:gson:2.9.0'
implementation "cn.dreamtobe.kpswitch:library:1.6.2"
@ -152,3 +164,20 @@ dependencies {
implementation "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}"
implementation "com.microsoft.appcenter:appcenter-distribute:${appCenterSdkVersion}"
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.21.1'
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option "lite"
// outputSubDir = "../" // debug / release
}
}
}
}
}

BIN
app/libs/common.jar Normal file

Binary file not shown.

View File

@ -25,6 +25,9 @@ import androidx.annotation.Keep
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate
import com.github.gzuliyujiang.oaid.DeviceID
import com.github.gzuliyujiang.oaid.DeviceIdentifier
import com.github.gzuliyujiang.oaid.IGetter
import com.huanchengfly.tieba.post.activities.BaseActivity
import com.huanchengfly.tieba.post.api.interfaces.CommonCallback
import com.huanchengfly.tieba.post.components.dialogs.LoadingDialog
@ -74,6 +77,18 @@ class BaseApplication : Application(), IApp {
override fun onCreate() {
instance = this
super.onCreate()
DeviceIdentifier.register(this)
DeviceID.getOAID(this, object : IGetter {
override fun onOAIDGetComplete(result: String) {
oaid = UIDUtil.Encoder(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
).encode(result.encodeToByteArray())
}
override fun onOAIDGetError(error: Exception) {
oaid = ""
}
})
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
setWebViewPath(this)
}
@ -342,6 +357,9 @@ class BaseApplication : Application(), IApp {
lateinit var instance: BaseApplication
private set
@JvmStatic
lateinit var oaid: String
val isSystemNight: Boolean
get() = nightMode == Configuration.UI_MODE_NIGHT_YES

View File

@ -278,6 +278,7 @@ open class MainActivity : BaseActivity(), NavigationBarView.OnItemSelectedListen
Log.i(TAG, "recreate: ")
}
@SuppressLint("MissingPermission")
override fun onStart() {
super.onStart()
registerReceiver(

View File

@ -36,6 +36,7 @@ public class WebViewActivity extends BaseActivity implements OnReceivedTitleList
Uri uri = Uri.parse(url);
if (TextUtils.equals(uri.getPath(), "/mo/q/checkurl")) {
url = uri.getQueryParameter("url");
url = url.replace("http://https://", "https://");
}
context.startActivity(newIntent(context, url));
}

View File

@ -46,8 +46,12 @@ object Header {
const val USER_AGENT = "User-Agent"
const val PRAGMA = "Pragma"
const val CUID = "cuid"
const val CHARSET = "Charset"
const val CUID_GALAXY2 = "cuid_galaxy2"
const val CUID_GALAXY3 = "c3_aid"
const val CUID_GID = "cuid_gid"
const val CLIENT_TYPE = "client_type"
const val X_BD_DATA_TYPE = "x_bd_data_type"
}
@ -59,6 +63,8 @@ object Param {
const val PHONE_IMEI = "_phone_imei"
const val CUID = "cuid"
const val CUID_GALAXY2 = "cuid_galaxy2"
const val CUID_GALAXY3 = "c3_aid"
const val OAID = "oaid"
const val CUID_GID = "cuid_gid"
const val FROM = "from"
const val NET_TYPE = "net_type"

View File

@ -0,0 +1,15 @@
package com.huanchengfly.tieba.post.api.models
import com.github.gzuliyujiang.oaid.DeviceID
import com.google.gson.annotations.SerializedName
import com.huanchengfly.tieba.post.BaseApplication
data class OAID(
@SerializedName("v")
val encodedOAID: String,
@SerializedName("sc")
val statusCode: Int = 0,
@SerializedName("sup")
val support: Int = if (DeviceID.supportedOAID(BaseApplication.instance)) 1 else 0,
val tl: Int = 0
)

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@ import com.huanchengfly.tieba.post.BaseApplication
import com.huanchengfly.tieba.post.api.Header
import com.huanchengfly.tieba.post.api.Param
import com.huanchengfly.tieba.post.api.interceptors.SortAndSignInterceptor
import com.huanchengfly.tieba.post.api.models.OAID
import com.huanchengfly.tieba.post.api.retrofit.adapter.DeferredCallAdapterFactory
import com.huanchengfly.tieba.post.api.retrofit.converter.gson.GsonConverterFactory
import com.huanchengfly.tieba.post.api.retrofit.interceptors.*
@ -12,13 +13,16 @@ import com.huanchengfly.tieba.post.api.retrofit.interfaces.MiniTiebaApi
import com.huanchengfly.tieba.post.api.retrofit.interfaces.NewTiebaApi
import com.huanchengfly.tieba.post.api.retrofit.interfaces.OfficialTiebaApi
import com.huanchengfly.tieba.post.api.retrofit.interfaces.WebTiebaApi
import com.huanchengfly.tieba.post.toJson
import com.huanchengfly.tieba.post.utils.AccountUtil
import com.huanchengfly.tieba.post.utils.CuidUtils
import com.huanchengfly.tieba.post.utils.MobileInfoUtil
import com.huanchengfly.tieba.post.utils.UIDUtil
import okhttp3.ConnectionPool
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.protobuf.ProtoConverterFactory
object RetrofitTiebaApi {
@ -93,21 +97,25 @@ object RetrofitTiebaApi {
val OFFICIAL_TIEBA_API: OfficialTiebaApi by lazy {
createAPI<OfficialTiebaApi>("http://c.tieba.baidu.com/",
defaultCommonHeaderInterceptor,
CommonHeaderInterceptor(
Header.USER_AGENT to { "bdtb for Android 12.25.1.0" },
Header.CUID to { UIDUtil.getNewCUID() },
Header.CUID_GALAXY2 to { UIDUtil.getFinalCUID() },
Header.CUID_GID to { "" }
Header.CUID to { CuidUtils.getNewCuid() },
Header.CUID_GALAXY2 to { CuidUtils.getNewCuid() },
Header.CUID_GID to { "" },
Header.CUID_GALAXY3 to { UIDUtil.getAid() },
Header.CLIENT_TYPE to { "2" },
Header.CHARSET to { "UTF-8" },
),
defaultCommonParamInterceptor,
stParamInterceptor,
CommonParamInterceptor(
Param.CUID to { UIDUtil.getNewCUID() },
Param.CUID_GALAXY2 to { UIDUtil.getFinalCUID() },
Param.CUID to { CuidUtils.getNewCuid() },
Param.CUID_GALAXY2 to { CuidUtils.getNewCuid() },
Param.CUID_GID to { "" },
Param.FROM to { "tieba" },
Param.CLIENT_VERSION to { "12.25.1.0" }
Param.CLIENT_VERSION to { "12.25.1.0" },
Param.CUID_GALAXY3 to { UIDUtil.getAid() },
Param.OAID to { OAID(BaseApplication.oaid).toJson() },
))
}
@ -119,6 +127,7 @@ object RetrofitTiebaApi {
.addCallAdapterFactory(DeferredCallAdapterFactory.invoke())
.addConverterFactory(NullOnEmptyConverterFactory())
.addConverterFactory(gsonConverterFactory)
.addConverterFactory(ProtoConverterFactory.create())
.client(OkHttpClient.Builder().apply {
interceptors.forEach {
addInterceptor(it)

View File

@ -1,12 +1,10 @@
package com.huanchengfly.tieba.post.api.retrofit.interceptors
import android.util.Log
import com.google.gson.Gson
import com.huanchengfly.tieba.post.api.models.CommonResponse
import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaApiException
import okhttp3.Interceptor
import okhttp3.Response
import java.nio.charset.StandardCharsets
object FailureResponseInterceptor : Interceptor {
private val gson = Gson()
@ -24,18 +22,9 @@ object FailureResponseInterceptor : Interceptor {
contentType.charset(Charsets.UTF_8)!!
}
val inputStream = body.source().also {
val inputStreamReader = body.source().also {
it.request(Long.MAX_VALUE)
}.buffer.clone().inputStream()
val length: Int = inputStream.available()
val buffer = ByteArray(length)
inputStream.read(buffer)
val bodyString = String(buffer, StandardCharsets.UTF_8)
Log.i("ResponseI", bodyString)
val inputStreamReader = inputStream.reader(charset)
}.buffer.clone().inputStream().reader(charset)
val jsonObject = try {
gson.fromJson<CommonResponse>(

View File

@ -7,7 +7,10 @@ import com.huanchengfly.tieba.post.api.getScreenHeight
import com.huanchengfly.tieba.post.api.getScreenWidth
import com.huanchengfly.tieba.post.api.models.CommonResponse
import com.huanchengfly.tieba.post.api.models.ThreadContentBean
import com.huanchengfly.tieba.post.api.models.protos.PbProto
import com.huanchengfly.tieba.post.api.retrofit.ApiResult
import com.huanchengfly.tieba.post.utils.AccountUtil
import kotlinx.coroutines.Deferred
import retrofit2.Call
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
@ -32,7 +35,9 @@ interface OfficialTiebaApi {
@Field("with_floor") with_floor: String = "1",
@Field("scr_dip") scr_dip: String = ScreenInfo.DENSITY.toString(),
@Field("scr_h") scr_h: String = getScreenHeight().toString(),
@Field("scr_w") scr_w: String = getScreenWidth().toString()
@Field("scr_w") scr_w: String = getScreenWidth().toString(),
@retrofit2.http.Header("thread_id") threadIdHeader: String = threadId,
@retrofit2.http.Header("client_logid") clientLogidHeader: String = "${System.currentTimeMillis()}",
): Call<ThreadContentBean>
@POST("/c/f/pb/page")
@ -51,9 +56,49 @@ interface OfficialTiebaApi {
@Field("with_floor") with_floor: String = "1",
@Field("scr_dip") scr_dip: String = ScreenInfo.DENSITY.toString(),
@Field("scr_h") scr_h: String = getScreenHeight().toString(),
@Field("scr_w") scr_w: String = getScreenWidth().toString()
@Field("scr_w") scr_w: String = getScreenWidth().toString(),
@retrofit2.http.Header("thread_id") threadIdHeader: String = threadId,
@retrofit2.http.Header("client_logid") clientLogidHeader: String = "${System.currentTimeMillis()}",
): Call<ThreadContentBean>
@POST("/c/f/pb/page")
@FormUrlEncoded
fun pbPageAsync(
@Field("kz") threadId: String,
@Field("pn") page: Int,
@Field("last") last: String?,
@Field("r") r: String?,
@Field("lz") lz: Int,
@Field("st_type") st_type: String = "tb_frslist",
@Field("back") back: String = "0",
@Field("floor_rn") floor_rn: String = "3",
@Field("mark") mark: String = "0",
@Field("rn") rn: String = "30",
@Field("with_floor") with_floor: String = "1",
@Field("scr_dip") scr_dip: String = ScreenInfo.DENSITY.toString(),
@Field("scr_h") scr_h: String = getScreenHeight().toString(),
@Field("scr_w") scr_w: String = getScreenWidth().toString()
): Deferred<ApiResult<PbProto.Pb>>
@POST("/c/f/pb/page")
@FormUrlEncoded
fun pbPageAsync(
@Field("kz") threadId: String,
@Field("pid") postId: String?,
@Field("last") last: String?,
@Field("r") r: String?,
@Field("lz") lz: Int,
@Field("st_type") st_type: String = "tb_frslist",
@Field("back") back: String = "0",
@Field("floor_rn") floor_rn: String = "3",
@Field("mark") mark: String = "0",
@Field("rn") rn: String = "30",
@Field("with_floor") with_floor: String = "1",
@Field("scr_dip") scr_dip: String = ScreenInfo.DENSITY.toString(),
@Field("scr_h") scr_h: String = getScreenHeight().toString(),
@Field("scr_w") scr_w: String = getScreenWidth().toString()
): Deferred<ApiResult<PbProto.Pb>>
@Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}")
@POST("/c/c/excellent/submitDislike")
@FormUrlEncoded

View File

@ -0,0 +1,12 @@
package com.huanchengfly.tieba.post.utils
object CuidUtils {
fun getNewCuid(): String {
val cuid = UIDUtil.getCUID()
val b = aid.common.cc.b().y(cuid.encodeToByteArray())
val encode = UIDUtil.Encoder(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
).encode(b)
return "$cuid|V$encode"
}
}

View File

@ -186,6 +186,7 @@ public final class NavigationHelper {
}
if (path.equalsIgnoreCase("/mo/q/checkurl")) {
url = uri.getQueryParameter("url");
url = url.replace("http://https://", "https://");
uri = Uri.parse(url);
host = uri.getHost();
path = uri.getPath();

View File

@ -7,22 +7,50 @@ import android.text.TextUtils;
import com.huanchengfly.tieba.post.BaseApplication;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.UUID;
public class UIDUtil {
@SuppressLint("HardwareIds")
public static String getAndroidId() {
return getAndroidId("");
}
@SuppressLint("HardwareIds")
public static String getAndroidId(String defaultValue) {
String androidId = Settings.Secure.getString(BaseApplication.getInstance().getContentResolver(), Settings.Secure.ANDROID_ID);
return androidId == null ? "" : androidId;
return androidId == null ? defaultValue : androidId;
}
public static String getAid() {
String raw = "com.helios" + getAndroidId("000000000") + getUUID();
byte[] bytes = getSHA1(raw);
return aid.ids.a.ag("A00", new Encoder("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=").encode(bytes));
}
public static byte[] getSHA1(String str) {
byte[] sha1 = null;
try {
MessageDigest digest = MessageDigest.getInstance("SHA1");
sha1 = digest.digest(str.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
e.printStackTrace();
}
return sha1;
}
public static String getNewCUID() {
return "baidutiebaapp" + getUUID();
}
private static String getCUID() {
public static String getCUID() {
String androidId = getAndroidId();
String imei = MobileInfoUtil.getIMEI(BaseApplication.getInstance());
if (TextUtils.isEmpty(imei)) {
imei = "0";
}
return MD5Util.toMd5((Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? imei + androidId + getUUID() : "com.baidu" + androidId).getBytes()).toUpperCase();
}
@ -47,4 +75,74 @@ public class UIDUtil {
}
return uuid;
}
public static class Encoder {
private final String secret;
public Encoder(String secret) {
this.secret = secret;
}
private static int dt(int var0) {
byte var1;
switch (var0) {
case 1:
var1 = 6;
break;
case 2:
var1 = 4;
break;
case 3:
var1 = 3;
break;
case 4:
var1 = 1;
break;
case 5:
var1 = 0;
break;
default:
var1 = -1;
}
return var1;
}
public String encode(byte[] bytes) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (int i = 0; i < (bytes.length + 4) / 5; ++i) {
short[] shorts = new short[5];
int[] ints = new int[8];
int i1 = 0;
int i2;
for (i2 = 5; i1 < 5; ++i1) {
if (i * 5 + i1 < bytes.length) {
shorts[i1] = (short) (bytes[i * 5 + i1] & 255);
} else {
shorts[i1] = 0;
--i2;
}
}
int dt = dt(i2);
ints[0] = (byte) (shorts[0] >> 3 & 31);
ints[1] = (byte) ((shorts[0] & 7) << 2 | shorts[1] >> 6 & 3);
ints[2] = (byte) (shorts[1] >> 1 & 31);
ints[3] = (byte) ((shorts[1] & 1) << 4 | shorts[2] >> 4 & 15);
ints[4] = (byte) ((shorts[2] & 15) << 1 | shorts[3] >> 7 & 1);
ints[5] = (byte) (shorts[3] >> 2 & 31);
ints[6] = (byte) ((shorts[3] & 3) << 3 | shorts[4] >> 5 & 7);
ints[7] = (byte) (shorts[4] & 31);
for (i1 = 0; i1 < ints.length - dt; ++i1) {
outputStream.write(this.secret.charAt(ints[i1]));
}
}
return outputStream.toString();
}
}
}

View File

@ -15,7 +15,8 @@ public final class PreloadUtil {
}
public static boolean isPreloading(Activity context) {
return getPreloadId(context) != -1;
int id = getPreloadId(context);
return id != -1 && PreLoader.exists(id);
}
public static int getPreloadId(Activity context) {

View File

@ -0,0 +1,53 @@
package proto;
option java_package = "com.huanchengfly.tieba.post.api.models.protos";
option java_outer_classname = "PbProto";
message Pb {
required Error error = 1;
required Data data = 2;
message Error {
required int32 errorCode = 1;
required string errorMsg = 2;
}
message Data {
required CurrentUser currentUser = 1;
optional Forum forum = 2;
repeated User user = 13;
optional Forum displayForum = 39;
message CurrentUser {
required int32 isLogin = 1;
optional int64 id = 2;
optional string name = 3;
optional string nameShow = 4;
optional string portrait = 5;
optional int32 levelId = 23;
}
message User {
required int64 id = 2;
optional string name = 3;
optional string nameShow = 4;
optional string portrait = 5;
optional int32 levelId = 23;
optional int32 isBawu = 25;
optional string bawuType = 26;
}
message Forum {
required int64 id = 1;
required string name = 2;
required int32 isExists = 3;
required string avatar = 4;
required int32 isLiked = 5;
required string firstClass = 7;
required string secondClass = 8;
optional int64 memberNum = 12;
optional int64 postNum = 13;
required int32 isBrandForum = 14;
}
}
}

View File

@ -9,7 +9,7 @@
<dimen name="space_toolbar_top">45dp</dimen>
<dimen name="text_size_user_name">16sp</dimen>
<dimen name="text_size_user_small">13sp</dimen>
<dimen name="text_size_user_small">12sp</dimen>
<dimen name="radius">8dp</dimen>
<dimen name="text_size_hot_title">16sp</dimen>

View File

@ -5,6 +5,7 @@ buildscript {
glide_version = '4.13.2'
retrofit_version = "2.9.0"
kotlin_version = '1.7.0'
grpc_version = '1.47.0'
}
repositories {
google()
@ -14,6 +15,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.18'
}
}