移除flutter(家里电脑跑不起来-_-!!)
This commit is contained in:
@@ -172,7 +172,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def Lombok = "1.18.10"
|
def Lombok = "1.18.10"
|
||||||
def useFlutterAar = Boolean.parseBoolean(with_flutter_aar)
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
|
||||||
@@ -245,36 +244,19 @@ dependencies {
|
|||||||
implementation 'com.meizu.flyme.internet:push-internal:4.1.0'
|
implementation 'com.meizu.flyme.internet:push-internal:4.1.0'
|
||||||
//oppo推送需要
|
//oppo推送需要
|
||||||
implementation 'commons-codec:commons-codec:1.6'
|
implementation 'commons-codec:commons-codec:1.6'
|
||||||
|
|
||||||
// xplan flutter module
|
|
||||||
if (useFlutterAar) {
|
|
||||||
implementation 'com.mango.flutter.xplan:flutter_release:1.0'
|
|
||||||
} else {
|
|
||||||
implementation project(path: ':flutter')
|
|
||||||
implementation project(path: ':flutter_boost')
|
|
||||||
}
|
|
||||||
|
|
||||||
api 'com.tencent.vasdolly:helper:3.0.3'
|
api 'com.tencent.vasdolly:helper:3.0.3'
|
||||||
implementation "io.github.tencent:vap:2.0.24"
|
implementation "io.github.tencent:vap:2.0.24"
|
||||||
|
|
||||||
implementation 'com.github.mmin18:realtimeblurview:1.2.1'
|
implementation 'com.github.mmin18:realtimeblurview:1.2.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
flatDir {
|
flatDir {
|
||||||
dirs 'aliyun-libs','com.huawei.agconnect'
|
dirs 'aliyun-libs','com.huawei.agconnect'
|
||||||
}
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
maven {
|
|
||||||
url '../xplan-flutter/build/host/outputs/repo'
|
|
||||||
}
|
|
||||||
|
|
||||||
maven {
|
|
||||||
url "$storageUrl/download.flutter.io"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channel {
|
channel {
|
||||||
|
@@ -1161,10 +1161,6 @@
|
|||||||
android:name=".ui.webview.TarotPayWebViewActivity"
|
android:name=".ui.webview.TarotPayWebViewActivity"
|
||||||
android:theme="@style/dialog_web_view_activity" />
|
android:theme="@style/dialog_web_view_activity" />
|
||||||
<!-- Fix bug Only fullscreen opaque activities can request orientation -->
|
<!-- Fix bug Only fullscreen opaque activities can request orientation -->
|
||||||
<activity
|
|
||||||
android:name="com.sdk.base.module.permission.PermissionActivity"
|
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
|
||||||
tools:remove="android:screenOrientation" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.login.LoginPasswordActivity"
|
android:name=".ui.login.LoginPasswordActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
@@ -1172,23 +1168,6 @@
|
|||||||
android:name=".ui.setting.ResetPasswordActivity"
|
android:name=".ui.setting.ResetPasswordActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="com.idlefish.flutterboost.containers.FlutterBoostActivity"
|
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
|
||||||
android:hardwareAccelerated="true"
|
|
||||||
android:screenOrientation="portrait"
|
|
||||||
android:theme="@style/Theme.AppCompat"
|
|
||||||
android:windowSoftInputMode="adjustResize">
|
|
||||||
<meta-data
|
|
||||||
android:name="io.flutter.embedding.android.SplashScreenDrawable"
|
|
||||||
android:resource="@drawable/bg_flutter_splash" />
|
|
||||||
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="flutterEmbedding"
|
|
||||||
android:value="2" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".module_hall.hall.activity.SuperAdminManageActivity"
|
android:name=".module_hall.hall.activity.SuperAdminManageActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
@@ -1248,9 +1227,6 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".skill.activity.EditSkillActivity"
|
android:name=".skill.activity.EditSkillActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
|
||||||
android:name=".ui.setting.ScheduleManageActivity"
|
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".home.activity.VisitorListActivity"
|
android:name=".home.activity.VisitorListActivity"
|
||||||
|
@@ -132,7 +132,6 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterFragment;
|
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
|
||||||
@@ -387,9 +386,6 @@ public class MainActivity extends BaseMvpActivity<IMainView, MainPresenter>
|
|||||||
}
|
}
|
||||||
onParseIntent();
|
onParseIntent();
|
||||||
handleNimIntent();
|
handleNimIntent();
|
||||||
if (tempFragment instanceof FlutterFragment) {
|
|
||||||
((FlutterFragment) tempFragment).onNewIntent(intent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onParseIntent() {
|
private void onParseIntent() {
|
||||||
@@ -464,9 +460,6 @@ public class MainActivity extends BaseMvpActivity<IMainView, MainPresenter>
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
if (tempFragment instanceof FlutterFragment) {
|
|
||||||
((FlutterFragment) tempFragment).onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
@@ -965,42 +958,4 @@ public class MainActivity extends BaseMvpActivity<IMainView, MainPresenter>
|
|||||||
StatusBarUtil.transparencyBar(this);
|
StatusBarUtil.transparencyBar(this);
|
||||||
StatusBarUtil.StatusBarLightMode(this);
|
StatusBarUtil.StatusBarLightMode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPostResume() {
|
|
||||||
super.onPostResume();
|
|
||||||
if (tempFragment instanceof FlutterFragment) {
|
|
||||||
((FlutterFragment) tempFragment).onPostResume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(
|
|
||||||
int requestCode,
|
|
||||||
@NonNull String[] permissions,
|
|
||||||
@NonNull int[] grantResults
|
|
||||||
) {
|
|
||||||
if (tempFragment instanceof FlutterFragment) {
|
|
||||||
tempFragment.onRequestPermissionsResult(
|
|
||||||
requestCode,
|
|
||||||
permissions,
|
|
||||||
grantResults
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUserLeaveHint() {
|
|
||||||
if (tempFragment instanceof FlutterFragment) {
|
|
||||||
((FlutterFragment) tempFragment).onUserLeaveHint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTrimMemory(int level) {
|
|
||||||
super.onTrimMemory(level);
|
|
||||||
if (tempFragment instanceof FlutterFragment) {
|
|
||||||
((FlutterFragment) tempFragment).onTrimMemory(level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
package com.yizhuan.erban.flutter;
|
|
||||||
|
|
||||||
public class ChannelConstants {
|
|
||||||
public static final String CHANNEL_NAME = "com.mango.flutter.xplan";
|
|
||||||
|
|
||||||
public static final String METHOD_NAME_GETDIAMOND = "getDiamond";
|
|
||||||
public static final String METHOD_NAME_GETDEVICEINFO = "getDeviceInfo";
|
|
||||||
public static final String METHOD_NAME_GETAUTH = "getAuth";
|
|
||||||
public static final String METHOD_NAME_GETENCODEPWD = "getEncodePwd";
|
|
||||||
public static final String METHOD_NAME_NOTIFYSHOWINVITE = "notifyShowInvite";
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
package com.yizhuan.erban.flutter;
|
|
||||||
|
|
||||||
public class RouterConstants {
|
|
||||||
public static final String NATIVE_PAGE_CHARGE = "charge";
|
|
||||||
public static final String NATIVE_PAGE_BIND = "bindGameAccount";
|
|
||||||
public static final String NATIVE_PAGE_INVITE = "invite";
|
|
||||||
public static final String NATIVE_PAGE_BIND_PAYMENT_PWD = "bindPaymentPwd";
|
|
||||||
public static final String NATIVE_PAGE_BIND_ALIPAY = "bindAlipay";
|
|
||||||
public static final String NATIVE_PAGE_WEBVIEW = "openWebview";
|
|
||||||
public static final String NATIVE_PAGE_CHATROOM = "chatRoom";
|
|
||||||
|
|
||||||
public static final String NATIVE_PAGE_ARG_WEBVIEW_URL = "webviewUrl";
|
|
||||||
public static final String NATIVE_PAGE_ARG_CHATROOM_ID = "chatRoomID";
|
|
||||||
public static final String NATIVE_PAGE_ARG_FROM_TYPE = "chatRoomFromType";
|
|
||||||
public static final String NATIVE_PAGE_ARG_FROM_UID = "chatRoomFromUid";
|
|
||||||
public static final String NATIVE_PAGE_ARG_FROM_NICK = "chatRoomFromNick";
|
|
||||||
|
|
||||||
public static final String FLUTTER_PAGE_MAIN = "/";
|
|
||||||
public static final String FLUTTER_PAGE_MAIN_DEBUG = "debug";
|
|
||||||
public static final String FLUTTER_PAGE_SPLASH = "splash";
|
|
||||||
public static final String FLUTTER_PAGE_MALL = "mall";
|
|
||||||
public static final String FLUTTER_PAGE_RECORD = "quotaRecord";
|
|
||||||
public static final String FLUTTER_PAGE_BAG = "bag";
|
|
||||||
public static final String FLUTTER_PAGE_PERFORMANCE = "performance";
|
|
||||||
public static final String FLUTTER_PAGE_MATCH_DETAIL = "matchDetail";
|
|
||||||
public static final String FLUTTER_PAGE_PRIZE = "prize";
|
|
||||||
|
|
||||||
public static final String FLUTTER_PAGE_ARG_MATCH_ID = "matchId";
|
|
||||||
}
|
|
@@ -1,77 +0,0 @@
|
|||||||
package com.yizhuan.erban.flutter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import com.idlefish.flutterboost.FlutterBoost;
|
|
||||||
import com.yizhuan.erban.application.XChatApplication;
|
|
||||||
import com.yizhuan.erban.flutter.event.ShowInviteEvent;
|
|
||||||
import com.yizhuan.xchat_android_constants.XChatConstants;
|
|
||||||
import com.yizhuan.xchat_android_core.auth.AuthModel;
|
|
||||||
import com.yizhuan.xchat_android_core.pay.PayModel;
|
|
||||||
import com.yizhuan.xchat_android_library.utils.AppMetaDataUtil;
|
|
||||||
import com.yizhuan.xchat_android_library.utils.AppUtils;
|
|
||||||
import com.yizhuan.xchat_android_library.utils.DeviceUuidFactory;
|
|
||||||
import com.yizhuan.xchat_android_library.utils.SystemUtils;
|
|
||||||
import com.yizhuan.xchat_android_library.utils.VersionUtil;
|
|
||||||
import com.yizhuan.xchat_android_library.utils.codec.DESUtils;
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.flutter.embedding.engine.FlutterEngine;
|
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
|
|
||||||
public class XplanFlutterBoostCallback implements FlutterBoost.Callback {
|
|
||||||
|
|
||||||
private MethodChannel mMethodChannel;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart(FlutterEngine engine) {
|
|
||||||
Context context = XChatApplication.instance();
|
|
||||||
|
|
||||||
mMethodChannel = new MethodChannel(engine.getDartExecutor(), ChannelConstants.CHANNEL_NAME);
|
|
||||||
mMethodChannel.setMethodCallHandler(((call, result) -> {
|
|
||||||
if (call.method.equals(ChannelConstants.METHOD_NAME_GETDIAMOND)) {
|
|
||||||
PayModel.get().getWalletInfo()
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(walletInfo -> {
|
|
||||||
result.success(walletInfo.diamonds);
|
|
||||||
});
|
|
||||||
} else if (call.method.equals(ChannelConstants.METHOD_NAME_GETDEVICEINFO)) {
|
|
||||||
Map<String, String> httpParams = new HashMap<>();
|
|
||||||
httpParams.put("os", "android");
|
|
||||||
httpParams.put("osVersion", Build.VERSION.RELEASE);
|
|
||||||
httpParams.put("app", XChatConstants.APP_MARK);
|
|
||||||
httpParams.put("ispType", String.valueOf(SystemUtils.getIspType(context)));
|
|
||||||
httpParams.put("netType", String.valueOf(SystemUtils.getNetworkType(context)));
|
|
||||||
httpParams.put("model", SystemUtils.getPhoneModel());
|
|
||||||
httpParams.put("appVersion", VersionUtil.getLocalName(context));
|
|
||||||
httpParams.put("appVersionCode", String.valueOf(AppUtils.getVersionCode(context)));
|
|
||||||
httpParams.put("deviceId", DeviceUuidFactory.getDeviceId(context));
|
|
||||||
httpParams.put("channel", AppMetaDataUtil.getChannelID());
|
|
||||||
result.success(httpParams);
|
|
||||||
} else if (call.method.equals(ChannelConstants.METHOD_NAME_GETAUTH)) {
|
|
||||||
Map<String, String> headerParams = new HashMap<>();
|
|
||||||
headerParams.put("pub_uid", String.valueOf(AuthModel.get().getCurrentUid()));
|
|
||||||
headerParams.put("pub_ticket", AuthModel.get().getTicket());
|
|
||||||
result.success(headerParams);
|
|
||||||
} else if (call.method.equals(ChannelConstants.METHOD_NAME_GETENCODEPWD)) {
|
|
||||||
try {
|
|
||||||
result.success(DESUtils.DESAndBase64Encrypt(String.valueOf(call.arguments)));
|
|
||||||
} catch (Exception e) {
|
|
||||||
result.error("", "", null);
|
|
||||||
}
|
|
||||||
} else if (call.method.equals(ChannelConstants.METHOD_NAME_NOTIFYSHOWINVITE)) {
|
|
||||||
EventBus.getDefault().post(new ShowInviteEvent(Boolean.valueOf(call.arguments.toString())));
|
|
||||||
} else {
|
|
||||||
result.notImplemented();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,102 +0,0 @@
|
|||||||
package com.yizhuan.erban.flutter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import com.idlefish.flutterboost.FlutterBoost;
|
|
||||||
import com.idlefish.flutterboost.FlutterBoostDelegate;
|
|
||||||
import com.idlefish.flutterboost.containers.FlutterBoostActivity;
|
|
||||||
import com.yizhuan.erban.avroom.activity.AVRoomActivity;
|
|
||||||
import com.yizhuan.erban.ui.login.BindPhoneActivity;
|
|
||||||
import com.yizhuan.erban.ui.pay.ChargeActivity;
|
|
||||||
import com.yizhuan.erban.ui.setting.ModifyPwdActivity;
|
|
||||||
import com.yizhuan.erban.ui.webview.CommonWebViewActivity;
|
|
||||||
import com.yizhuan.erban.ui.withdraw.BinderAlipayActivity;
|
|
||||||
import com.yizhuan.xchat_android_core.UriProvider;
|
|
||||||
import com.yizhuan.xchat_android_core.statistic.StatisticManager;
|
|
||||||
import com.yizhuan.xchat_android_core.statistic.StatisticModel;
|
|
||||||
import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol;
|
|
||||||
import com.yizhuan.xchat_android_core.user.UserModel;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivityLaunchConfigs;
|
|
||||||
|
|
||||||
public class XplanFlutterBoostDelegate implements FlutterBoostDelegate {
|
|
||||||
@Override
|
|
||||||
public void pushNativeRoute(String pageName, Map<String, Object> arguments) {
|
|
||||||
if (pageName == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_CHARGE)) {
|
|
||||||
ChargeActivity.start(FlutterBoost.instance().currentActivity());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_BIND)) {
|
|
||||||
CommonWebViewActivity.start(FlutterBoost.instance().currentActivity(), UriProvider.getLinkAccountUrl());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_BIND_PAYMENT_PWD)) {
|
|
||||||
Context context = FlutterBoost.instance().currentActivity();
|
|
||||||
if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) {
|
|
||||||
ModifyPwdActivity.start(context, ModifyPwdActivity.PAY_PWD);
|
|
||||||
} else {
|
|
||||||
BindPhoneActivity.start(context);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_BIND_ALIPAY)) {
|
|
||||||
Context context = FlutterBoost.instance().currentActivity();
|
|
||||||
if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) {
|
|
||||||
Intent intent = new Intent(context, BinderAlipayActivity.class);
|
|
||||||
context.startActivity(intent);
|
|
||||||
} else {
|
|
||||||
BindPhoneActivity.start(context);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_WEBVIEW)) {
|
|
||||||
String url = (String) arguments.get(RouterConstants.NATIVE_PAGE_ARG_WEBVIEW_URL);
|
|
||||||
if (url == null || url.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Context context = FlutterBoost.instance().currentActivity();
|
|
||||||
Intent intent = new Intent(context, CommonWebViewActivity.class);
|
|
||||||
intent.putExtra("url", url);
|
|
||||||
intent.putExtra("from", "xplan_flutter");
|
|
||||||
context.startActivity(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_INVITE)) {
|
|
||||||
CommonWebViewActivity.start(FlutterBoost.instance().currentActivity(), UriProvider.getGameShareUrl());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pageName.equals(RouterConstants.NATIVE_PAGE_CHATROOM)) {
|
|
||||||
StatisticManager.Instance().onEvent(StatisticsProtocol.EVENT_OPERATIONAL_ROOM_SUCCESS, "赛事详情成功进入聊天室 ");
|
|
||||||
long uid = Long.valueOf((Integer) arguments.get(RouterConstants.NATIVE_PAGE_ARG_CHATROOM_ID));
|
|
||||||
int fromType = arguments.containsKey(RouterConstants.NATIVE_PAGE_ARG_FROM_TYPE) ?
|
|
||||||
(Integer) arguments.get(RouterConstants.NATIVE_PAGE_ARG_FROM_TYPE) : 0;
|
|
||||||
String fromUid = arguments.containsKey(RouterConstants.NATIVE_PAGE_ARG_FROM_UID) ?
|
|
||||||
(String) arguments.get(RouterConstants.NATIVE_PAGE_ARG_FROM_UID) : "";
|
|
||||||
String fromNick = arguments.containsKey(RouterConstants.NATIVE_PAGE_ARG_FROM_UID) ?
|
|
||||||
(String) arguments.get(RouterConstants.NATIVE_PAGE_ARG_FROM_NICK) : "";
|
|
||||||
AVRoomActivity.startForFromType(FlutterBoost.instance().currentActivity(), uid, fromType, fromNick, fromUid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void pushFlutterRoute(String pageName, String uniqueId, Map<String, Object> arguments) {
|
|
||||||
if (arguments == null) {
|
|
||||||
arguments = new HashMap<>();
|
|
||||||
}
|
|
||||||
Intent intent = new FlutterBoostActivity.CachedEngineIntentBuilder(FlutterBoostActivity.class, FlutterBoost.ENGINE_ID)
|
|
||||||
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.opaque)
|
|
||||||
.destroyEngineWithActivity(false)
|
|
||||||
.url(pageName)
|
|
||||||
.urlParams(arguments)
|
|
||||||
.build(FlutterBoost.instance().currentActivity());
|
|
||||||
FlutterBoost.instance().currentActivity().startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
package com.yizhuan.erban.flutter.event;
|
|
||||||
|
|
||||||
public class ShowInviteEvent {
|
|
||||||
public boolean mShowInvite;
|
|
||||||
|
|
||||||
public ShowInviteEvent(boolean show) {
|
|
||||||
mShowInvite = show;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
package com.yizhuan.erban.home.fragment;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.idlefish.flutterboost.containers.FlutterBoostFragment;
|
|
||||||
import com.yizhuan.erban.R;
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.DrawableSplashScreen;
|
|
||||||
import io.flutter.embedding.android.SplashScreen;
|
|
||||||
|
|
||||||
public class GameFragment extends FlutterBoostFragment {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public SplashScreen provideSplashScreen() {
|
|
||||||
return new DrawableSplashScreen(getResources().getDrawable(R.drawable.bg_flutter_splash));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
|
||||||
try {
|
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -25,7 +25,6 @@ import com.yizhuan.erban.ui.im.chat.MsgViewHolderGift;
|
|||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderHello;
|
import com.yizhuan.erban.ui.im.chat.MsgViewHolderHello;
|
||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderLevel;
|
import com.yizhuan.erban.ui.im.chat.MsgViewHolderLevel;
|
||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderLottery;
|
import com.yizhuan.erban.ui.im.chat.MsgViewHolderLottery;
|
||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderMatch;
|
|
||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderOnline;
|
import com.yizhuan.erban.ui.im.chat.MsgViewHolderOnline;
|
||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderRedPackage;
|
import com.yizhuan.erban.ui.im.chat.MsgViewHolderRedPackage;
|
||||||
import com.yizhuan.erban.ui.im.chat.MsgViewHolderRedPacket;
|
import com.yizhuan.erban.ui.im.chat.MsgViewHolderRedPacket;
|
||||||
@@ -159,9 +158,6 @@ public class ImInitHelper {
|
|||||||
NimUIKit.registerMsgItemViewHolder(WorldDynamicAttachment.class, WorldDynamicShareViewHolder.class);
|
NimUIKit.registerMsgItemViewHolder(WorldDynamicAttachment.class, WorldDynamicShareViewHolder.class);
|
||||||
|
|
||||||
NimUIKit.registerMsgItemViewHolder(ChatHintAttachment.class, MsgViewHolderChatHint.class);
|
NimUIKit.registerMsgItemViewHolder(ChatHintAttachment.class, MsgViewHolderChatHint.class);
|
||||||
|
|
||||||
NimUIKit.registerMsgItemViewHolder(MatchAttachment.class, MsgViewHolderMatch.class);
|
|
||||||
|
|
||||||
//技能卡
|
//技能卡
|
||||||
NimUIKit.registerMsgItemViewHolder(SkillMsgAttachment.class, MsgViewHolderSkill.class);
|
NimUIKit.registerMsgItemViewHolder(SkillMsgAttachment.class, MsgViewHolderSkill.class);
|
||||||
//CP
|
//CP
|
||||||
|
@@ -38,7 +38,6 @@ import com.yizhuan.erban.ui.patriarch.PatriarchModeActivity;
|
|||||||
import com.yizhuan.erban.ui.pay.ChargeActivity;
|
import com.yizhuan.erban.ui.pay.ChargeActivity;
|
||||||
import com.yizhuan.erban.ui.setting.FeedbackActivity;
|
import com.yizhuan.erban.ui.setting.FeedbackActivity;
|
||||||
import com.yizhuan.erban.ui.setting.ModifyPwdActivity;
|
import com.yizhuan.erban.ui.setting.ModifyPwdActivity;
|
||||||
import com.yizhuan.erban.ui.setting.ScheduleManageActivity;
|
|
||||||
import com.yizhuan.erban.ui.user.UserInfoActivity;
|
import com.yizhuan.erban.ui.user.UserInfoActivity;
|
||||||
import com.yizhuan.erban.ui.webview.CommonWebViewActivity;
|
import com.yizhuan.erban.ui.webview.CommonWebViewActivity;
|
||||||
import com.yizhuan.erban.ui.withdraw.BinderAlipayActivity;
|
import com.yizhuan.erban.ui.withdraw.BinderAlipayActivity;
|
||||||
@@ -307,7 +306,6 @@ public class RouterHandler {
|
|||||||
break;
|
break;
|
||||||
case RouterType.SCHEDULE_MANAGE:
|
case RouterType.SCHEDULE_MANAGE:
|
||||||
//赛程管理
|
//赛程管理
|
||||||
ScheduleManageActivity.Companion.start(context);
|
|
||||||
break;
|
break;
|
||||||
case RouterType.VISITOR_LIST:
|
case RouterType.VISITOR_LIST:
|
||||||
//访客记录
|
//访客记录
|
||||||
|
@@ -1,68 +0,0 @@
|
|||||||
package com.yizhuan.erban.ui.im.chat;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.idlefish.flutterboost.FlutterBoost;
|
|
||||||
import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase;
|
|
||||||
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter;
|
|
||||||
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
|
|
||||||
import com.yizhuan.erban.MainActivity;
|
|
||||||
import com.yizhuan.erban.R;
|
|
||||||
import com.yizhuan.erban.flutter.RouterConstants;
|
|
||||||
import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment;
|
|
||||||
import com.yizhuan.xchat_android_core.im.custom.bean.MatchAttachment;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p> 文字消息holder </p>
|
|
||||||
*
|
|
||||||
* @author jiahui
|
|
||||||
* @date 2018/1/10
|
|
||||||
*/
|
|
||||||
public class MsgViewHolderMatch extends MsgViewHolderBase {
|
|
||||||
private TextView mTvMsg;
|
|
||||||
private MatchAttachment matchAttachment;
|
|
||||||
|
|
||||||
public MsgViewHolderMatch(BaseMultiItemFetchLoadAdapter adapter) {
|
|
||||||
super(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getContentResId() {
|
|
||||||
return R.layout.layout_msg_view_holder_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void inflateContentView() {
|
|
||||||
mTvMsg = findViewById(R.id.tv_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void bindContentView() {
|
|
||||||
CharSequence text = "";
|
|
||||||
MsgAttachment attachment = message.getAttachment();
|
|
||||||
if (attachment instanceof MatchAttachment) {
|
|
||||||
matchAttachment = (MatchAttachment) attachment;
|
|
||||||
text = matchAttachment.getContent();
|
|
||||||
}
|
|
||||||
mTvMsg.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onItemClick() {
|
|
||||||
if (matchAttachment != null && matchAttachment.isNeedForwardToMatchDetail()) {
|
|
||||||
HashMap<String, Object> args = new HashMap<>();
|
|
||||||
args.put(RouterConstants.FLUTTER_PAGE_ARG_MATCH_ID, matchAttachment.getMatchId());
|
|
||||||
FlutterBoost.instance().open(RouterConstants.FLUTTER_PAGE_MATCH_DETAIL, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (matchAttachment != null && matchAttachment.getSecond() == CustomAttachment.CUSTOM_MSG_QUICK_DISMISS) {
|
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.putExtra(MainActivity.GAME_TAB, true);
|
|
||||||
MainActivity.start(context, intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -5,16 +5,12 @@ import android.view.View;
|
|||||||
import android.widget.RadioButton;
|
import android.widget.RadioButton;
|
||||||
import android.widget.RadioGroup;
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
import com.idlefish.flutterboost.FlutterBoost;
|
|
||||||
import com.yizhuan.erban.R;
|
import com.yizhuan.erban.R;
|
||||||
import com.yizhuan.erban.base.BaseActivity;
|
import com.yizhuan.erban.base.BaseActivity;
|
||||||
import com.yizhuan.erban.ui.utils.ImageLoadKt;
|
import com.yizhuan.erban.ui.utils.ImageLoadKt;
|
||||||
import com.yizhuan.xchat_android_core.DemoCache;
|
|
||||||
import com.yizhuan.xchat_android_core.Env;
|
import com.yizhuan.xchat_android_core.Env;
|
||||||
import com.yizhuan.xchat_android_core.auth.AuthModel;
|
import com.yizhuan.xchat_android_core.auth.AuthModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by chenran on 2017/10/16.
|
* Created by chenran on 2017/10/16.
|
||||||
@@ -25,7 +21,6 @@ public class LabActivity extends BaseActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_lab);
|
setContentView(R.layout.activity_lab);
|
||||||
findViewById(R.id.rb_flutter_test).setOnClickListener(v -> FlutterBoost.instance().open("/", null));
|
|
||||||
findViewById(R.id.rb_vap_test).setOnClickListener(v ->
|
findViewById(R.id.rb_vap_test).setOnClickListener(v ->
|
||||||
ImageLoadKt.loadAnim(
|
ImageLoadKt.loadAnim(
|
||||||
findViewById(R.id.anim_vap_test),
|
findViewById(R.id.anim_vap_test),
|
||||||
|
@@ -1,46 +0,0 @@
|
|||||||
package com.yizhuan.erban.ui.setting
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.view.View
|
|
||||||
import com.idlefish.flutterboost.FlutterBoost
|
|
||||||
import com.yizhuan.erban.R
|
|
||||||
import com.yizhuan.erban.base.BaseBindingActivity
|
|
||||||
import com.yizhuan.erban.databinding.ActivityScheduleManageBinding
|
|
||||||
import com.yizhuan.erban.flutter.RouterConstants
|
|
||||||
import com.yizhuan.erban.ui.webview.CommonWebViewActivity
|
|
||||||
import com.yizhuan.xchat_android_core.UriProvider
|
|
||||||
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
|
|
||||||
|
|
||||||
@ActLayoutRes(R.layout.activity_schedule_manage)
|
|
||||||
class ScheduleManageActivity : BaseBindingActivity<ActivityScheduleManageBinding>() {
|
|
||||||
override fun init() {
|
|
||||||
initTitleBar("赛程管理")
|
|
||||||
mBinding.click = this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
|
||||||
super.onClick(v)
|
|
||||||
when (v.id) {
|
|
||||||
R.id.match_quota_record -> FlutterBoost.instance()
|
|
||||||
.open(RouterConstants.FLUTTER_PAGE_RECORD, null)
|
|
||||||
R.id.match_prize -> FlutterBoost.instance()
|
|
||||||
.open(RouterConstants.FLUTTER_PAGE_PRIZE, null)
|
|
||||||
R.id.match_performance -> FlutterBoost.instance()
|
|
||||||
.open(RouterConstants.FLUTTER_PAGE_PERFORMANCE, null)
|
|
||||||
R.id.match_bag -> FlutterBoost.instance().open(RouterConstants.FLUTTER_PAGE_BAG, null)
|
|
||||||
R.id.match_mall -> FlutterBoost.instance().open(RouterConstants.FLUTTER_PAGE_MALL, null)
|
|
||||||
R.id.tv_link_account -> CommonWebViewActivity.start(
|
|
||||||
this,
|
|
||||||
UriProvider.getLinkAccountUrl()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun start(context: Context) {
|
|
||||||
val intent = Intent(context, ScheduleManageActivity::class.java)
|
|
||||||
context.startActivity(intent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
568
packer-ng-v2.py
568
packer-ng-v2.py
@@ -1,568 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Author: mcxiaoke
|
|
||||||
# @Date: 2017-06-06 14:03:18
|
|
||||||
# @Last Modified by: mcxiaoke
|
|
||||||
# @Last Modified time: 2017-06-22 17:26:29
|
|
||||||
from __future__ import print_function
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import mmap
|
|
||||||
import struct
|
|
||||||
import zipfile
|
|
||||||
import logging
|
|
||||||
import time
|
|
||||||
|
|
||||||
logging.basicConfig(format='%(levelname)s:%(lineno)s: %(funcName)s() %(message)s',
|
|
||||||
level=logging.ERROR)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
AUTHOR = 'mcxiaoke'
|
|
||||||
VERSION = '2.0.0'
|
|
||||||
try:
|
|
||||||
props = dict(line.strip().split('=') for line in
|
|
||||||
open('../gradle.properties') if line.strip())
|
|
||||||
VERSION = props.get('VERSION_NAME')
|
|
||||||
except Exception as e:
|
|
||||||
VERSION = '2.0.0'
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
|
|
||||||
# ref: https://android.googlesource.com/platform/tools/apksig/+/master
|
|
||||||
# ref: https://source.android.com/security/apksigning/v2
|
|
||||||
|
|
||||||
ZIP_EOCD_REC_MIN_SIZE = 22
|
|
||||||
ZIP_EOCD_REC_SIG = 0x06054b50
|
|
||||||
ZIP_EOCD_CENTRAL_DIR_TOTAL_RECORD_COUNT_OFFSET = 10
|
|
||||||
ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET = 12
|
|
||||||
ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET = 16
|
|
||||||
ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET = 20
|
|
||||||
ZIP_EOCD_COMMENT_MIN_LENGTH = 0
|
|
||||||
|
|
||||||
UINT16_MAX_VALUE = 0xffff # 65535
|
|
||||||
|
|
||||||
BlOCK_MAX_SIZE = 0x100000 # 1m=1024k
|
|
||||||
|
|
||||||
APK_SIG_BLOCK_MAGIC = 'APK Sig Block 42'
|
|
||||||
APK_SIG_BLOCK_MAGIC_HI = 0x3234206b636f6c42
|
|
||||||
APK_SIG_BLOCK_MAGIC_LO = 0x20676953204b5041
|
|
||||||
APK_SIG_BLOCK_MIN_SIZE = 32
|
|
||||||
APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a
|
|
||||||
|
|
||||||
# plugin channel key
|
|
||||||
PLUGIN_CHANNEL_KEY = 'CHANNEL'
|
|
||||||
# plugin block id
|
|
||||||
PLUGIN_BLOCK_ID = 0x7a786b21
|
|
||||||
# plugin block magic
|
|
||||||
PLUGIN_BLOCK_MAGIC = 'Packer Ng Sig V2'
|
|
||||||
|
|
||||||
SEP_KV = '∘'
|
|
||||||
SEP_LINE = '∙'
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
|
|
||||||
class ZipFormatException(Exception):
|
|
||||||
'''ZipFormatException'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SignatureNotFoundException(Exception):
|
|
||||||
'''SignatureNotFoundException'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MagicNotFoundException(Exception):
|
|
||||||
'''MagicNotFoundException'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
|
|
||||||
class ByteDecoder(object):
|
|
||||||
'''
|
|
||||||
byte array decoder
|
|
||||||
https://docs.python.org/2/library/struct.html
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, buf, littleEndian=True):
|
|
||||||
self.buf = buf
|
|
||||||
self.sign = '<' if littleEndian else '>'
|
|
||||||
|
|
||||||
def getShort(self, offset=0):
|
|
||||||
return struct.unpack('{}h'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 2])[0]
|
|
||||||
|
|
||||||
def getUShort(self, offset=0):
|
|
||||||
return struct.unpack('{}H'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 2])[0]
|
|
||||||
|
|
||||||
def getInt(self, offset=0):
|
|
||||||
return struct.unpack('{}i'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 4])[0]
|
|
||||||
|
|
||||||
def getUInt(self, offset=0):
|
|
||||||
return struct.unpack('{}I'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 4])[0]
|
|
||||||
|
|
||||||
def getLong(self, offset=0):
|
|
||||||
return struct.unpack('{}q'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 8])[0]
|
|
||||||
|
|
||||||
def getULong(self, offset=0):
|
|
||||||
return struct.unpack('{}Q'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 8])[0]
|
|
||||||
|
|
||||||
def getFloat(self, offset=0):
|
|
||||||
return struct.unpack('{}f'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 4])[0]
|
|
||||||
|
|
||||||
def getDouble(self, offset=0):
|
|
||||||
return struct.unpack('{}d'.format(self.sign),
|
|
||||||
self.buf[offset:offset + 8])[0]
|
|
||||||
|
|
||||||
def getChars(self, offset=0, size=16):
|
|
||||||
return struct.unpack('{}{}'.format(self.sign, 's' * size),
|
|
||||||
self.buf[offset:offset + size])
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
|
|
||||||
class ZipSections(object):
|
|
||||||
'''
|
|
||||||
long centralDirectoryOffset,
|
|
||||||
long centralDirectorySizeBytes,
|
|
||||||
int centralDirectoryRecordCount,
|
|
||||||
long eocdOffset,
|
|
||||||
ByteBuffer eocd
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, cdStartOffset,
|
|
||||||
cdSizeBytes,
|
|
||||||
cdRecordCount,
|
|
||||||
eocdOffset,
|
|
||||||
eocd):
|
|
||||||
self.cdStartOffset = cdStartOffset
|
|
||||||
self.cdSizeBytes = cdSizeBytes
|
|
||||||
self.cdRecordCount = cdRecordCount
|
|
||||||
self.eocdOffset = eocdOffset
|
|
||||||
self.eocd = eocd
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
|
|
||||||
def parseValues(content):
|
|
||||||
'''
|
|
||||||
PLUGIN BLOCK LAYOUT
|
|
||||||
OFFSET DATA TYPE DESCRIPTION
|
|
||||||
@+0 magic string magic string 16 bytes
|
|
||||||
@+16 payload length payload length int 4 bytes
|
|
||||||
@+20 payload payload data bytes
|
|
||||||
@-4 payload length same as @+16 4 bytes
|
|
||||||
'''
|
|
||||||
magicLen = len(PLUGIN_BLOCK_MAGIC)
|
|
||||||
logger.debug('content:%s', content)
|
|
||||||
if not content or len(content) < magicLen + 4 * 2:
|
|
||||||
return None
|
|
||||||
content = content[magicLen + 4: -4]
|
|
||||||
values = dict(line.split(SEP_KV)
|
|
||||||
for line in content.split(SEP_LINE) if line.strip())
|
|
||||||
logger.debug('values:%s', values)
|
|
||||||
return values
|
|
||||||
|
|
||||||
|
|
||||||
def createMap(apk):
|
|
||||||
with open(apk, "rb") as f:
|
|
||||||
size = os.path.getsize(apk)
|
|
||||||
offset = max(0, size - BlOCK_MAX_SIZE)
|
|
||||||
length = min(size, BlOCK_MAX_SIZE)
|
|
||||||
offset = offset - offset % mmap.PAGESIZE
|
|
||||||
logger.debug('file size=%s', size)
|
|
||||||
logger.debug('file offset=%s', offset)
|
|
||||||
return mmap.mmap(f.fileno(),
|
|
||||||
length=length,
|
|
||||||
offset=offset,
|
|
||||||
access=mmap.ACCESS_READ)
|
|
||||||
|
|
||||||
|
|
||||||
def findBlockByPluginMagic(apk):
|
|
||||||
mm = createMap(apk)
|
|
||||||
magicLen = len(PLUGIN_BLOCK_MAGIC)
|
|
||||||
start = mm.rfind(PLUGIN_BLOCK_MAGIC)
|
|
||||||
if start == -1:
|
|
||||||
return None
|
|
||||||
d = ByteDecoder(mm)
|
|
||||||
logger.debug('magic start offset=%s', start)
|
|
||||||
magic = ''.join(d.getChars(start, magicLen))
|
|
||||||
logger.debug('magic start string=%s', magic)
|
|
||||||
payloadLen = d.getInt(start + magicLen)
|
|
||||||
logger.debug('magic payloadLen1=%s', payloadLen)
|
|
||||||
|
|
||||||
end = start + magicLen + 4 + payloadLen + 4
|
|
||||||
logger.debug('magic end offset=%s', end)
|
|
||||||
logger.debug('magic payloadLen2=%s', d.getInt(end - 4))
|
|
||||||
|
|
||||||
block = mm[start:end]
|
|
||||||
mm.close()
|
|
||||||
return block
|
|
||||||
|
|
||||||
|
|
||||||
def findBlockBySigningMagic(apk):
|
|
||||||
# search APK Signing Block Magic words
|
|
||||||
signingBlock = findBySigningMagic(apk)
|
|
||||||
if signingBlock:
|
|
||||||
return parseApkSigningBlock(signingBlock, PLUGIN_BLOCK_ID)
|
|
||||||
|
|
||||||
|
|
||||||
def findBlockByZipSections(apk):
|
|
||||||
# find zip centralDirectory, then find apkSigningBlock
|
|
||||||
signingBlock = findByZipSections(apk)
|
|
||||||
if signingBlock:
|
|
||||||
return parseApkSigningBlock(signingBlock, PLUGIN_BLOCK_ID)
|
|
||||||
|
|
||||||
|
|
||||||
def findBySigningMagic(apk):
|
|
||||||
# findApkSigningBlockUsingSigningMagic
|
|
||||||
mm = createMap(apk)
|
|
||||||
index = mm.rfind(APK_SIG_BLOCK_MAGIC)
|
|
||||||
if index == -1:
|
|
||||||
raise MagicNotFoundException(
|
|
||||||
'APK Signing Block Magic not found')
|
|
||||||
d = ByteDecoder(mm)
|
|
||||||
logger.debug('magic index=%s', index)
|
|
||||||
logger.debug('magic string=%s', ''.join(d.getChars(index, 16)))
|
|
||||||
bEnd = index + 16
|
|
||||||
logger.debug('block end=%s', bEnd)
|
|
||||||
bSize = d.getLong(bEnd - 24) + 8
|
|
||||||
logger.debug('block size=%s', bSize)
|
|
||||||
bStart = bEnd - bSize
|
|
||||||
logger.debug('block start=%s', bStart)
|
|
||||||
block = mm[bStart:bEnd]
|
|
||||||
mm.close()
|
|
||||||
return block
|
|
||||||
|
|
||||||
|
|
||||||
def findByZipSections(apk):
|
|
||||||
# findApkSigningBlockUsingZipSections
|
|
||||||
with open(apk, "rb") as f:
|
|
||||||
mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
|
|
||||||
sections = findZipSections(mm)
|
|
||||||
|
|
||||||
centralDirStartOffset = sections.cdStartOffset
|
|
||||||
centralDirEndOffset = centralDirStartOffset + sections.cdSizeBytes
|
|
||||||
eocdStartOffset = sections.eocdOffset
|
|
||||||
logger.debug('centralDirStartOffset:%s', centralDirStartOffset)
|
|
||||||
logger.debug('centralDirEndOffset:%s', centralDirEndOffset)
|
|
||||||
logger.debug('eocdStartOffset:%s', eocdStartOffset)
|
|
||||||
if centralDirEndOffset != eocdStartOffset:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"ZIP Central Directory is not "
|
|
||||||
"immediately followed by "
|
|
||||||
"End of Central Directory. CD end: {} eocd start: {}"
|
|
||||||
.format(centralDirEndOffset, eocdStartOffset))
|
|
||||||
if centralDirStartOffset < APK_SIG_BLOCK_MIN_SIZE:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"APK too small for APK Signing Block. "
|
|
||||||
"ZIP Central Directory offset:{} "
|
|
||||||
.format(centralDirStartOffset))
|
|
||||||
|
|
||||||
fStart = centralDirStartOffset - 24
|
|
||||||
mStart = centralDirStartOffset - 16
|
|
||||||
fEnd = centralDirStartOffset
|
|
||||||
logger.debug('fStart:%s', fStart)
|
|
||||||
logger.debug('mStart:%s', mStart)
|
|
||||||
logger.debug('fEnd:%s', fEnd)
|
|
||||||
footer = mm[fStart:fEnd]
|
|
||||||
footerSize = len(footer)
|
|
||||||
# logger.debug('footer:%s',to_hex(footer))
|
|
||||||
fd = ByteDecoder(footer)
|
|
||||||
magic = ''.join(fd.getChars(8, 16))
|
|
||||||
# logger.debug('magic str:%s', magic)
|
|
||||||
lo = fd.getLong(8)
|
|
||||||
hi = fd.getLong(16)
|
|
||||||
logger.debug('magic lo:%s', hex(lo))
|
|
||||||
logger.debug('magic hi:%s', hex(hi))
|
|
||||||
|
|
||||||
if magic != APK_SIG_BLOCK_MAGIC:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"No APK Signing Block before ZIP Central Directory")
|
|
||||||
# if lo != APK_SIG_BLOCK_MAGIC_LO or hi != APK_SIG_BLOCK_MAGIC_HI:
|
|
||||||
# raise SignatureNotFoundException(
|
|
||||||
# "No APK Signing Block before ZIP Central Directory")
|
|
||||||
|
|
||||||
apkSigBlockSizeInFooter = fd.getLong(0)
|
|
||||||
logger.debug('apkSigBlockSizeInFooter:%s', apkSigBlockSizeInFooter)
|
|
||||||
|
|
||||||
if apkSigBlockSizeInFooter < footerSize or \
|
|
||||||
apkSigBlockSizeInFooter > sys.maxsize - 8:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"APK Signing Block size out of range: {}"
|
|
||||||
.format(apkSigBlockSizeInFooter))
|
|
||||||
|
|
||||||
totalSize = apkSigBlockSizeInFooter + 8
|
|
||||||
logger.debug('totalSize:%s', totalSize)
|
|
||||||
apkSigBlockOffset = centralDirStartOffset - totalSize
|
|
||||||
logger.debug('apkSigBlockOffset:%s', apkSigBlockOffset)
|
|
||||||
|
|
||||||
if apkSigBlockOffset < 0:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"APK Signing Block offset out of range: " + apkSigBlockOffset)
|
|
||||||
|
|
||||||
apkSigBlock = mm[apkSigBlockOffset:apkSigBlockOffset + 8]
|
|
||||||
# logger.debug('apkSigBlock:%s', to_hex(apkSigBlock))
|
|
||||||
apkSigBlockSizeInHeader = ByteDecoder(apkSigBlock).getLong(0)
|
|
||||||
logger.debug('apkSigBlockSizeInHeader:%s', apkSigBlockSizeInHeader)
|
|
||||||
|
|
||||||
if apkSigBlockSizeInHeader != apkSigBlockSizeInFooter:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"APK Signing Block sizes in header and"
|
|
||||||
"footer do not match: {} vs {}"
|
|
||||||
.format(apkSigBlockSizeInHeader, apkSigBlockSizeInFooter))
|
|
||||||
|
|
||||||
block = mm[apkSigBlockOffset:apkSigBlockOffset + totalSize]
|
|
||||||
mm.close()
|
|
||||||
return block
|
|
||||||
|
|
||||||
|
|
||||||
def parseApkSigningBlock(block, blockId):
|
|
||||||
# parseApkSigningBlock
|
|
||||||
if not block or not blockId:
|
|
||||||
return None
|
|
||||||
'''
|
|
||||||
// APK Signing Block
|
|
||||||
// FORMAT:
|
|
||||||
// OFFSET DATA TYPE DESCRIPTION
|
|
||||||
// * @+0 bytes uint64: size in bytes(excluding this field)
|
|
||||||
// * @+8 bytes payload
|
|
||||||
// * @-24 bytes uint64: size in bytes(same as the one above)
|
|
||||||
// * @-16 bytes uint128: magic
|
|
||||||
'''
|
|
||||||
totalSize = len(block)
|
|
||||||
bd0 = ByteDecoder(block)
|
|
||||||
blockSizeInHeader = bd0.getULong(0)
|
|
||||||
logger.debug('blockSizeInHeader:%s', blockSizeInHeader)
|
|
||||||
blockSizeInFooter = bd0.getULong(totalSize - 24)
|
|
||||||
logger.debug('blockSizeInFooter:%s', blockSizeInFooter)
|
|
||||||
# slice only payload
|
|
||||||
block = block[8:-24]
|
|
||||||
bd = ByteDecoder(block)
|
|
||||||
size = len(block)
|
|
||||||
logger.debug('payloadSize:%s', size)
|
|
||||||
|
|
||||||
entryCount = 0
|
|
||||||
position = 0
|
|
||||||
signingBlock = None
|
|
||||||
channelBlock = None
|
|
||||||
while position < size:
|
|
||||||
entryCount += 1
|
|
||||||
logger.debug('entryCount:%s', entryCount)
|
|
||||||
if size - position < 8:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"Insufficient data to read size "
|
|
||||||
"of APK Signing Block entry: {}"
|
|
||||||
.format(entryCount))
|
|
||||||
lenLong = bd.getLong(position)
|
|
||||||
logger.debug('lenLong:%s', lenLong)
|
|
||||||
position += 8
|
|
||||||
if lenLong < 4 or lenLong > sys.maxsize - 8:
|
|
||||||
raise SignatureNotFoundException(
|
|
||||||
"APK Signing Block entry #{} size out of range: {}"
|
|
||||||
.format(entryCount, lenLong))
|
|
||||||
nextEntryPos = position + lenLong
|
|
||||||
logger.debug('nextEntryPos:%s', nextEntryPos)
|
|
||||||
if nextEntryPos > size:
|
|
||||||
SignatureNotFoundException(
|
|
||||||
"APK Signing Block entry #{}, available: {}"
|
|
||||||
.format(entryCount, (size - position)))
|
|
||||||
sid = bd.getInt(position)
|
|
||||||
logger.debug('blockId:%s', hex(sid))
|
|
||||||
position += 4
|
|
||||||
if sid == APK_SIGNATURE_SCHEME_V2_BLOCK_ID:
|
|
||||||
logger.debug('found signingBlock')
|
|
||||||
signingBlock = block[position:position + lenLong - 4]
|
|
||||||
signingBlockSize = len(signingBlock)
|
|
||||||
logger.debug('signingBlockSize:%s', signingBlockSize)
|
|
||||||
# logger.debug('signingBlockHex:%s', to_hex(signingBlock[0:32]))
|
|
||||||
elif sid == blockId:
|
|
||||||
logger.debug('found pluginBlock')
|
|
||||||
pluginBlock = block[position:position + lenLong - 4]
|
|
||||||
pluginBlockSize = len(pluginBlock)
|
|
||||||
logger.debug('pluginBlockSize:%s', pluginBlockSize)
|
|
||||||
logger.debug('pluginBlock:%s', pluginBlock)
|
|
||||||
# logger.debug('pluginBlockHex:%s', to_hex(pluginBlock))
|
|
||||||
return pluginBlock
|
|
||||||
else:
|
|
||||||
logger.debug('found unknown block:%s', hex(sid))
|
|
||||||
position = nextEntryPos
|
|
||||||
|
|
||||||
|
|
||||||
def findZipSections(mm):
|
|
||||||
eocd = findEocdRecord(mm)
|
|
||||||
if not eocd:
|
|
||||||
raise ZipFormatException(
|
|
||||||
"ZIP End of Central Directory record not found")
|
|
||||||
eocdOffset, eocdBuf = eocd
|
|
||||||
ed = ByteDecoder(eocdBuf)
|
|
||||||
# logger.debug('eocdBuf:%s', to_hex(eocdBuf))
|
|
||||||
cdStartOffset = ed.getUInt(ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET)
|
|
||||||
logger.debug('cdStartOffset:%s', cdStartOffset)
|
|
||||||
if cdStartOffset > eocdOffset:
|
|
||||||
raise ZipFormatException(
|
|
||||||
"ZIP Central Directory start offset out of range: {}"
|
|
||||||
". ZIP End of Central Directory offset: {}"
|
|
||||||
.format(cdStartOffset, eocdOffset))
|
|
||||||
cdSizeBytes = ed.getUInt(ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET)
|
|
||||||
logger.debug('cdSizeBytes:%s', cdSizeBytes)
|
|
||||||
cdEndOffset = cdStartOffset + cdSizeBytes
|
|
||||||
logger.debug('cdEndOffset:%s', cdEndOffset)
|
|
||||||
if cdEndOffset > eocdOffset:
|
|
||||||
raise ZipFormatException(
|
|
||||||
"ZIP Central Directory overlaps with End of Central Directory"
|
|
||||||
". CD end: {}, EoCD start: {}"
|
|
||||||
.format(cdEndOffset, eocdOffset))
|
|
||||||
cdRecordCount = ed.getUShort(
|
|
||||||
ZIP_EOCD_CENTRAL_DIR_TOTAL_RECORD_COUNT_OFFSET)
|
|
||||||
logger.debug('cdRecordCount:%s', cdRecordCount)
|
|
||||||
sections = ZipSections(cdStartOffset,
|
|
||||||
cdSizeBytes,
|
|
||||||
cdRecordCount,
|
|
||||||
eocdOffset,
|
|
||||||
eocdBuf)
|
|
||||||
return sections
|
|
||||||
|
|
||||||
|
|
||||||
def findEocdRecord(mm):
|
|
||||||
fileSize = mm.size()
|
|
||||||
logger.debug('fileSize:%s', fileSize)
|
|
||||||
if fileSize < ZIP_EOCD_REC_MIN_SIZE:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# 99.99% of APKs have a zero-length comment field
|
|
||||||
maxCommentSize = min(UINT16_MAX_VALUE, fileSize - ZIP_EOCD_REC_MIN_SIZE)
|
|
||||||
maxEocdSize = ZIP_EOCD_REC_MIN_SIZE + maxCommentSize
|
|
||||||
logger.debug('maxCommentSize:%s', maxCommentSize)
|
|
||||||
logger.debug('maxEocdSize:%s', maxEocdSize)
|
|
||||||
bufOffsetInFile = fileSize - maxEocdSize
|
|
||||||
logger.debug('bufOffsetInFile:%s', bufOffsetInFile)
|
|
||||||
buf = mm[bufOffsetInFile:bufOffsetInFile + maxEocdSize]
|
|
||||||
# logger.debug('buf:%s',to_hex(buf))
|
|
||||||
eocdOffsetInBuf = findEocdStartOffset(buf)
|
|
||||||
logger.debug('eocdOffsetInBuf:%s', eocdOffsetInBuf)
|
|
||||||
if eocdOffsetInBuf != -1:
|
|
||||||
return bufOffsetInFile + eocdOffsetInBuf, buf[eocdOffsetInBuf:]
|
|
||||||
|
|
||||||
|
|
||||||
def findEocdStartOffset(buf):
|
|
||||||
archiveSize = len(buf)
|
|
||||||
logger.debug('archiveSize:%s', archiveSize)
|
|
||||||
maxCommentLength = min(
|
|
||||||
archiveSize - ZIP_EOCD_REC_MIN_SIZE, UINT16_MAX_VALUE)
|
|
||||||
logger.debug('maxCommentLength:%s', maxCommentLength)
|
|
||||||
eocdEmptyCommentStartPos = archiveSize - ZIP_EOCD_REC_MIN_SIZE
|
|
||||||
logger.debug('eocdEmptyCommentStartPos:%s',
|
|
||||||
eocdEmptyCommentStartPos)
|
|
||||||
expectedCommentLength = 0
|
|
||||||
eocdOffsetInBuf = -1
|
|
||||||
while expectedCommentLength <= maxCommentLength:
|
|
||||||
eocdStartPos = eocdEmptyCommentStartPos - expectedCommentLength
|
|
||||||
logger.debug('expectedCommentLength:%s', expectedCommentLength)
|
|
||||||
# logger.debug('eocdStartPos:%s', eocdStartPos)
|
|
||||||
seg = ByteDecoder(buf).getInt(eocdStartPos)
|
|
||||||
logger.debug('seg:%s', hex(seg))
|
|
||||||
if seg == ZIP_EOCD_REC_SIG:
|
|
||||||
actualCommentLength = ByteDecoder(buf).getUShort(
|
|
||||||
eocdStartPos + ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET)
|
|
||||||
logger.debug('actualCommentLength:%s', actualCommentLength)
|
|
||||||
if actualCommentLength == expectedCommentLength:
|
|
||||||
logger.debug('found eocdStartPos:%s', eocdStartPos)
|
|
||||||
return eocdStartPos
|
|
||||||
expectedCommentLength += 1
|
|
||||||
return -1
|
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
|
|
||||||
def timeit(method):
|
|
||||||
|
|
||||||
def timed(*args, **kw):
|
|
||||||
ts = time.time() * 1000
|
|
||||||
result = method(*args, **kw)
|
|
||||||
te = time.time() * 1000
|
|
||||||
|
|
||||||
print('%s() executed in %.2f msec' % (method.__name__, te - ts))
|
|
||||||
return result
|
|
||||||
|
|
||||||
return timed
|
|
||||||
|
|
||||||
|
|
||||||
def to_hex(s):
|
|
||||||
return " ".join("{:02x}".format(ord(c)) for c in s) if s else ""
|
|
||||||
|
|
||||||
|
|
||||||
def getChannel(apk):
|
|
||||||
apk = os.path.abspath(apk)
|
|
||||||
logger.debug('apk:%s', apk)
|
|
||||||
try:
|
|
||||||
zp = zipfile.ZipFile(apk)
|
|
||||||
zp.testzip()
|
|
||||||
content = findBlockByZipSections(apk)
|
|
||||||
values = parseValues(content)
|
|
||||||
if values:
|
|
||||||
channel = values.get(PLUGIN_CHANNEL_KEY)
|
|
||||||
logger.debug('channel:%s', channel)
|
|
||||||
return channel
|
|
||||||
else:
|
|
||||||
logger.debug('channel not found')
|
|
||||||
except Exception as e:
|
|
||||||
logger.error('%s: %s', type(e).__name__, e)
|
|
||||||
|
|
||||||
|
|
||||||
def showInfo(apk):
|
|
||||||
try:
|
|
||||||
from apkinfo import APK
|
|
||||||
info = APK(apk)
|
|
||||||
print('Package: \t{}'.format(info.get_package()))
|
|
||||||
print('Version: \t{}'.format(info.get_version_name()))
|
|
||||||
print('Build: \t\t{}'.format(info.get_version_code()))
|
|
||||||
print('File: \t\t{}'.format(os.path.basename(apk)))
|
|
||||||
print('Size: \t\t{}'.format(os.path.getsize(apk)))
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
logger.debug('AUTHOR:%s', AUTHOR)
|
|
||||||
logger.debug('VERSION:%s', VERSION)
|
|
||||||
prog = os.path.basename(sys.argv[0])
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print('Usage: {} app.apk'.format(prog))
|
|
||||||
sys.exit(1)
|
|
||||||
apk = os.path.abspath(sys.argv[1])
|
|
||||||
if os.path.isdir(apk):
|
|
||||||
files = getListFiles(apk)
|
|
||||||
for each in files:
|
|
||||||
showChannel(each)
|
|
||||||
elif os.path.isfile(apk):
|
|
||||||
showChannel(apk)
|
|
||||||
|
|
||||||
def showChannel(apk):
|
|
||||||
print("\n")
|
|
||||||
channel = getChannel(apk)
|
|
||||||
print('Channel: \t{}'.format(channel))
|
|
||||||
showInfo(apk)
|
|
||||||
|
|
||||||
def getListFiles(path):
|
|
||||||
ret = []
|
|
||||||
for root, dirs, files in os.walk(path):
|
|
||||||
# print(root)
|
|
||||||
# print(dirs)
|
|
||||||
# print(files)
|
|
||||||
for filepath in files:
|
|
||||||
# print(filepath)
|
|
||||||
ret.append(os.path.join(root, filepath))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@@ -3,9 +3,3 @@ include ':trtc_release'
|
|||||||
include ':core'
|
include ':core'
|
||||||
include ':library'
|
include ':library'
|
||||||
include ':nim_uikit'
|
include ':nim_uikit'
|
||||||
// 添加 flutter module 依赖
|
|
||||||
if (!Boolean.parseBoolean(with_flutter_aar)){
|
|
||||||
setBinding(new Binding([gradle: this]))
|
|
||||||
evaluate(new File(settingsDir,
|
|
||||||
'/xplan-flutter/.android/include_flutter.groovy'))
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user