阿里熱修復之Sophix——專有云釋出版整合步驟
阿里熱修復之Sophix——專有云
應公司業務需求,和阿里雲的阿里熱修復相關技術人員合作,整了波專有云的熱修復整合Demo
一、app/build.gradle下的程式碼
注意:第二行的程式碼在整合中要開啟的,這裡註釋掉是為讓app可以本地run起來看到介面
apply plugin: 'com.android.application'
//除錯無法安裝時註釋掉這行
//apply plugin: 'com.taobao.sophix.emas'
configurations {
providedCompile
all*.exclude group: 'com.taobao.android' , module: 'tnet-jni'
all*.exclude group: 'com.taobao.android', module: 'tlog_adapter'
all*.exclude group: 'com.aliyun.ams', module:'alicloud-android-utdid'
all*.exclude group: 'com.aliyun.ams', module: 'alicloud-android-ut'
}
configurations.all {
resolutionStrategy {
cacheChangingModulesFor(0 , 'SECONDS')
cacheChangingModulesFor(0, 'SECONDS')
}
}
//task wrapper(type: Wrapper) {
// gradleVersion = '4.1'
// distributionUrl = 'http://emas-deploy.oss-cn-hangzhou.aliyuncs.com/gradle-4.1-all.zip'
//}
//tasks.whenTaskAdded { task ->
// if (task.name.contains("DebugAndroidTest")) {
// task.setEnabled(false);
// }
//}
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.dotawang.sophixemasdemo"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'arm64-v8a'
}
//語言型別
resConfigs "en", "fr"
}
dexOptions{
javaMaxHeapSize = '2048m'
additionalParameters=["--no-strict"]
}
sourceSets {
main {
jniLibs.srcDirs = ['jniLibs']
}
}
signingConfigs {
releaseConfig {
storeFile file("release.keystore")
storePassword "hschyf"
keyAlias "hswinner"
keyPassword "hschyf"
}
debugConfig {
storeFile file("release.keystore")
storePassword "hschyf"
keyAlias "hswinner"
keyPassword "hschyf"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.releaseConfig
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// signingConfig signingConfigs.debugConfig
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support:design:26.1.0'
compile 'com.squareup.picasso:picasso:2.5.2'
//出現Error:Execution failed for task ':app:preDebugAndroidTestBuild'的解決方法
androidTestCompile('com.android.support:support-annotations:26.1.0') {
force = true
}
compile 'com.aliyun.ams:alicloud-android-hotfix:3.2.4'
compile('com.emas.lib:emas-core:[email protected]') { transitive true }
/************基礎庫 START**********/
compile('com.alibaba:fastjson:[email protected]') { transitive true }
compile('com.taobao.android:mtopsdk_allinone:[email protected]') { transitive true }
compile('com.taobao.android:networksdk:[email protected]') { transitive true }
compile('com.taobao.android:tnet4android:[email protected]') { transitive true }
compile('com.taobao.android:utdid4all:[email protected]') { transitive true }
/************基礎庫 END**********/
/************高可用 SDK START**********/
compile('com.taobao.android:accs_sdk_taobao:3.3.3.1-open') { transitive true }
compile('com.taobao.android:ut-analytics:[email protected]') { transitive true }
compile('com.alibaba.ha:alihatbadapter:[email protected]') {
transitive true
//exclude group:'com.taobao.android', module:'tlog_uploader_oss'
}
//compile ('com.taobao.android:tlog_uploader_ceph:[email protected]')
//預設oss通道需要依賴oss的三方庫
compile ('com.squareup.okhttp3:okhttp:[email protected]')
compile ('com.squareup.okio:okio:[email protected]')
compile ('com.aliyun.dpa:oss-android-sdk:[email protected]')
/************高可用 SDK END**********/
}
//Sophix
apply from: 'common.gradle'
group = "com.dotawang.sophixemasdemo"//包名
version = android.defaultConfig.versionName + '-SNAPSHOT'
apply plugin: 'maven'
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
if (project.gradle.startParameter.toString().contains("Debug")) {
artifact "${project.buildDir}/sophix/${project.name}-debug.sar"
artifactId "sar-debug"
} else {
artifact "${project.buildDir}/sophix/${project.name}-release.sar"
artifactId "sar-release"
}
}
}
repositories {
if (version.endsWith("-SNAPSHOT")) {
maven {
url "http://nexus.emas-ha.cn:8081/repository/maven-snapshots/"
credentials {
username = CUSTOM_REPOSITORY_USERNAME
password = CUSTOM_REPOSITORY_PASSWORD
}
}
} else {
maven {
url "http://nexus.emas-ha.cn:8081/repository/maven-releases/"
credentials {
username = CUSTOM_REPOSITORY_USERNAME
password = CUSTOM_REPOSITORY_PASSWORD
}
}
}
}
}
二、在專案的app資料夾下建立個common.gradle的檔案,位置如下圖:
common.gradle的程式碼如下:
def emas_version_name = getEnvValue('EMAS_VERSION_NAME')
def emas_version_code = getEnvValue('EMAS_VERSION_CODE')
def emas_base_version = getEnvValue('EMAS_BASE_VERSION')
if (emas_version_code) {
android.defaultConfig.versionCode = emas_version_code.toInteger()
println("emas_version_code=" + emas_version_code)
}
if (emas_base_version) {
println("emas_base_version=" + emas_base_version)
}
if (emas_version_name) {
android.defaultConfig.versionName = emas_version_name
println("emas_version_name=" + emas_version_name)
}
String getEnvValue(key) {
return getEnvValue(key, null)
}
String getEnvValue(key, defValue) {
def val = System.getProperty(key);
if (null != val) {
return val
}
val = System.getenv(key);
if (null != val) {
return val
}
return defValue
}
三、proguard-rules.pro混淆的程式碼
#基線包使用,生成mapping.txt
-printmapping mapping.txt
#生成的mapping.txt在app/build/outputs/mapping/release路徑下,移動到/app路徑下
#修復後的專案使用,保證混淆結果一致
#-applymapping mapping.txt
#hotfix
-keep class com.taobao.sophix.**{*;}
-keep class com.ta.utdid2.device.**{*;}
#防止inline
-dontoptimize
-keepclassmembers class com.dotawang.sophixemasdemo.WinnerApplication {
public <init>();
}
-keep class com.dotawang.sophixemasdemo.SophixStubApplication$RealApplicationStub
-dontpreverify
-dontusemixedcaseclassnames
-optimizations code/removal/simple,code/removal/advanced,code/removal/variable,code/removal/exception,code/simplification/branch,code/simplification/field,code/simplification/cast,code/simplification/arithmetic,code/simplification/variable
-keepattributes Exceptions,InnerClasses,Signature,SourceFile,LineNumberTable,*Annotation*
-renamesourcefileattribute Taobao
-allowaccessmodification
-optimizationpasses 1
#防止inline
-dontoptimize
-target 1.6
#-verbose
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontwarn okio.**
-dontwarn com.squareup.okhttp.**
-dontwarn okhttp3.**
-dontwarn javax.annotation.**
-dontwarn com.android.volley.toolbox.**
-dontwarn com.facebook.infer.**
-dontwarn org.mozilla.javascript.**
-dontwarn org.mozilla.classfile.**
-dontwarn java.awt.**
-dontwarn com.taobao.**
-dontwarn com.google.android.maps.**
-dontwarn android.support.v7.widget.**
-dontwarn android.support.v4.**
-dontwarn com.tencent.mm.sdk.**
-dontwarn org.android.agoo.**
-dontwarn com.amap.api.**
-dontwarn com.autonavi.amap.**
-dontwarn com.ut.**
-dontwarn com.robotium.**
-dontwarn com.alibaba.fastjson.**
-dontwarn android.taobao.**
-dontwarn com.alibaba.mobileim.**
-dontwarn com.autonavi.**
-dontwarn com.amap.**
-dontwarn ***
#############公共的混淆keep選項, 可刪除與工程中有重複部分 #############
-keep class * extends android.app.Application
-keep class * extends android.app.Activity
-keep class * extends android.app.Service
-keep class com.google.inject.Binder
-keepclassmembers class * {
@com.google.inject.Inject <init>(...);
}
# There's no way to keep all @Observes methods, so use the On*Event convention to identify event handlers
-keepclassmembers class * {
void *(**On*Event);
}
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keep public class roboguice.**
-keep class rx.**{*;}
# 為了atlas注入
-keepclassmembers class ** {
private <init>(...);
public <init>(...);
<init>(...);
}
-keepclassmembernames class **.R$* {*;}
-keepclassmembernames class **.R {*;}
-keepclassmembers class **{
public static final <fields>;
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
public void *(android.view.MenuItem);
}
-keepclassmembers class * implements android.os.Parcelable {
static ** CREATOR;
}
-keepclassmembers class * {
public static ** asInterface(***);
}
-keepclassmembers class ** {
public void onEvent*(***);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(...);
**[] $VALUES;
}
-keepclasseswithmembernames class * {
native <methods>;
}
# Keep native methods
-keepclassmembers class * {
native <methods>;
}
-keepclassmembers class * implements java.io.Serializable {
public <fields>;
public <methods>;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class * implements android.os.Parcelable {
public <fields>;
public <methods>;
public static final android.os.Parcelable$Creator *;
}
#############公共的混淆keep選項, 可刪除與工程中有重複部分 #############
##########################基礎庫##########################
#fastjson
-keep class com.alibaba.fastjson.** {*;}
#tnet
#-keepclasseswithmembernames class org.android.spdy.** {
# native <methods>;
#}
-keep public class org.android.spdy.**{*;}
#mtop
-keep class anetwork.network.cache.**{*;}
-keep class com.taobao.tao.remotebusiness.**{*;}
-keep class mtopsdk.**{*;}
#network
-keep class anet.channel.**{*;}
-keep class anetwork.channel.**{*;}
##########################基礎庫##########################
##########################高可用##########################
#keep ha alihatbadapter
-keep class com.alibaba.ha.**{*;}
-keep class com.taobao.tlog.**{*;}
#keep ha utdid
-keep class com.ut.device.**{*;}
-keep class com.ta.utdid2.device.**{*;}
#keep ha ut
-keep public class com.alibaba.mtl.** { *;}
-keep public class com.ut.mini.** { *;}
#keep ha crashreporter
-keep class com.alibaba.motu.crashreporter.**{ *;}
-keep class com.uc.crashsdk.**{*;}
#keep ha telescope
-keep class com.ali.telescope.**{ *;}
-keep class libcore.io.**{*;}
-keep class android.app.**{*;}
-keep class dalvik.system.**{*;}
#keep ha tlog
-keep class com.taobao.tao.log.**{*;}
-keep class com.taobao.android.tlog.**{*;}
#keep tbrest
-keep class com.alibaba.motu.**{*;}
##########################高可用##########################
###########################遠端配置##########################
-keep class com.taobao.orange.**{*;}
###########################遠端配置##########################
###########################其他##########################
-keep class sun.misc.Unsafe { *; }
-keep class com.alibaba.** {*;}
#關閉日誌
#-assumenosideeffects class android.util.Log {
# public static boolean isLoggable(java.lang.String, int);
# public static int v(...);
# public static int w(...);
# public static int d(...);
# public static int i(...);
#}
#-assumenosideeffects class java.lang.Throwable {
# public void printStackTrace();
#}
-keep public class android.support.design.widget.BottomNavigationView { *; }
-keep public class android.support.design.internal.BottomNavigationMenuView { *; }
-keep public class android.support.design.internal.BottomNavigationPresenter { *; }
-keep public class android.support.design.internal.BottomNavigationItemView { *; }
###########################其他##########################
## 去除BottomNavigationView的tab大於三個的時候的切換效果
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
四、專案下的build.gradle程式碼
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
mavenLocal()
maven {
url SDK_REPOSITORY_URL
credentials {
username = SDK_REPOSITORY_USERNAME
password = SDK_REPOSITORY_PASSWORD
}
}
maven { url "http://maven.aliyun.com/nexus/content/repositories/google/"}
maven { url "http://maven.aliyun.com/nexus/content/repositories/releases/"}
maven { url "http://maven.aliyun.com/nexus/content/groups/public/"}
maven { url "http://nexus.emas-ha.cn:8081/repository/maven-releases/" }
maven { url "http://nexus.emas-ha.cn:8081/repository/maven-snapshots/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.taobao.android:sophix-emas-plugin:0.5.10-SNAPSHOT'//Sophix
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
maven {
url SDK_REPOSITORY_URL
credentials {
//SDK中心倉庫
username = SDK_REPOSITORY_USERNAME
password = SDK_REPOSITORY_PASSWORD
}
}
maven { url "http://maven.aliyun.com/nexus/content/repositories/google/"}
maven { url "http://maven.aliyun.com/nexus/content/repositories/releases/"}
maven { url "http://maven.aliyun.com/nexus/content/groups/public/"}
maven { url "http://nexus.emas-ha.cn:8081/repository/maven-releases/" }
maven { url "http://nexus.emas-ha.cn:8081/repository/maven-snapshots/" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
五、gradle.properties的程式碼中加入下面程式碼
注意:這裡程式碼主要是用來配置sdk倉庫和產物倉庫的2組賬號密碼
#SDK中心倉庫
SDK_REPOSITORY_URL = http://nexus-ce.emas-poc.com/repository/maven-public/
SDK_REPOSITORY_USERNAME = developer
SDK_REPOSITORY_PASSWORD = fT&iXg$16jIh##yL
#產物倉庫
CUSTOM_REPOSITORY_HOST = nexus.emas-ha.cn:8081
CUSTOM_REPOSITORY_USERNAME = developer
CUSTOM_REPOSITORY_PASSWORD = RSs6KfAdXJOrA6rx
六、各大介面的程式碼
1)MainActivity的佈局xml程式碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_gravity="center"
tools:context="com.dotawang.sophixemasdemo.MainActivity">
<ImageView
android:id="@+id/iv"
android:src="@mipmap/ic_launcher"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp" />
<TextView
android:id="@+id/tv1"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="補丁內容修改"
android:layout_gravity="center"
android:gravity="center"/>
<Button
android:id="@+id/bt_crash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="崩潰"
android:layout_gravity="center"
android:gravity="center"/>
<Button
android:id="@+id/bt_ca"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="執行緒卡頓"
android:layout_gravity="center"
android:gravity="center"/>
<Button
android:id="@+id/bt_query"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拉取補丁"
android:layout_gravity="center"
android:gravity="center" />
<TextView
android:id="@+id/tv_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"/>
</LinearLayout>
2)MainActivity的介面程式碼
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import com.taobao.sophix.SophixManager;
/**
1、AndroidManifest不支援
2、build 基礎依賴包升級不支援
3、匯入sophix外掛,無法直接打包
*/
public class MainActivity extends Activity {
private ImageView imageView;
private TextView textView;
private TextView tv_code;
private Button bt_crash,bt_ca,bt_query;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initListener();
initThread();
}
private void initThread() {
updata(SophixStubApplication.cacheMsg.toString());
SophixStubApplication.msgDisplayListener = new SophixStubApplication.MsgDisplayListener() {
@Override
public void handle(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
updata(msg);
}
});
}
};
handler.postDelayed(new Runnable() {
@Override
public void run() {
// 請求補丁
SophixManager.getInstance().queryAndLoadNewPatch();
handler.postDelayed(this, 10 * 1000);
}
}, 1 * 1000);
}
private void updata(String cacheMsg) {
if (cacheMsg != null){
tv_code.setText(cacheMsg);
}
}
private void initListener() {
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//1、ic_launcher
//2、https://i.loli.net/2018/09/12/5b9881e9ed5e8.jpg
//3、test本地
Picasso.with(MainActivity.this).load("https://i.loli.net/2018/09/12/5b9881e9ed5e8.jpg").into(imageView);
}
});
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
textView.setText("修復1");
//textView.setText("修復2");
//textView.setText("修復3");
}
});
bt_crash.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
throw new RuntimeException();
}
});
bt_ca.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try{
Thread.sleep(20*1000);
}catch (Exception e){
e.printStackTrace();
}
}
});
bt_query.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SophixManager.getInstance().queryAndLoadNewPatch();
}
});
}
private void initData() {
imageView = findViewById(R.id.iv);
textView = findViewById(R.id.tv1);
tv_code = findViewById(R.id.tv_code);
bt_crash = findViewById(R.id.bt_crash);
bt_ca = findViewById(R.id.bt_ca);
bt_query = findViewById(R.id.bt_query);
}
}
3)SophixStubApplication的程式碼
import android.content.Context;
import android.support.annotation.Keep;
import android.util.Log;
import com.taobao.sophix.PatchStatus;
import com.taobao.sophix.SophixApplication;
import com.taobao.sophix.SophixEntry;
import com.taobao.sophix.SophixManager;
import com.taobao.sophix.listener.PatchLoadStatusListener;
/**
* Created on 2018/9/12
* Title:
* Description:
*
* @author Android-汪洋
* update 2018/9/12
*/
public class SophixStubApplication extends SophixApplication {
private final String TAG = "SophixStubApplication";
// 此處SophixEntry應指定真正的Application,並且保證RealApplicationStub類名不被混淆。
@Keep
@SophixEntry(WinnerApplication.class)
static class RealApplicationStub {}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// 如果需要使用MultiDex,需要在此處呼叫。
// MultiDex.install(this);
initSophix();
}
private void initSophix() {
String appVersion = "0.0.0";
try {
appVersion = this.getPackageManager()
.getPackageInfo(this.getPackageName(), 0)
.versionName;
} catch (Exception e) {
}
final SophixManager instance = SophixManager.getInstance();
instance.setContext(this)
.setAppVersion(appVersion)
//host 域名
.setHost("hotfix-gate.emas-poc.com", false)
.setEnableDebug(true)
.setEnableFullLog()
.setPatchLoadStatusStub(new PatchLoadStatusListener() {
@Override
public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
String msg = new StringBuilder("").append("Mode:").append(mode)
.append(" Code:").append(code)
.append(" Info:").append(info)
.append(" HandlePatchVersion:").append(handlePatchVersion).toString();
if (msgDisplayListener != null) {
msgDisplayListener.handle(msg);
} else {
cacheMsg.append("\n").append(msg);
}
if (code == PatchStatus.CODE_LOAD_SUCCESS) {
Log.i(TAG, "sophix load patch success!");
} else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
// 如果需要在後臺重啟,建議此處用SharePreference儲存狀態。
Log.i(TAG, "sophix preload patch success. restart app to make effect.");
}
}
}).initialize();
}
public interface MsgDisplayListener {
void handle(String msg);
}
public static MsgDisplayListener msgDisplayListener = null;
public static StringBuilder cacheMsg = new StringBuilder();
}
4)WinnerApplication的程式碼
import android.app.Application;
import com.taobao.sophix.SophixManager;
/**
* Created on 2018/9/12
* Title:
* Description:
*
* @author Android-汪洋
* update 2018/9/12
*/
public class WinnerApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
EmasInit emas = EmasInit.getInstance().setmApplication(this);
emas.initHA();
SophixManager.getInstance().queryAndLoadNewPatch();
}
}
5)EmasInit的程式碼
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.text.TextUtils;
import android.util.Log;
import com.alibaba.ha.adapter.AliHaAdapter;
import com.alibaba.ha.adapter.AliHaConfig;
import com.alibaba.ha.adapter.Plugin;
import com.alibaba.ha.adapter.Sampling;
import com.taobao.accs.ACCSClient;
import com.taobao.accs.ACCSManager;
import com.taobao.accs.AccsClientConfig;
import com.taobao.accs.AccsException;
import com.taobao.accs.IAppReceiver;
import com.taobao.accs.common.Constants;
import com.taobao.accs.utl.ALog;
import org.android.spdy.SpdyProtocol;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import anet.channel.AwcnConfig;
import anet.channel.SessionCenter;
import anet.channel.strategy.ConnEvent;
import anet.channel.strategy.ConnProtocol;
import anet.channel.strategy.IConnStrategy;
import anet.channel.strategy.IStrategyInstance;
import anet.channel.strategy.IStrategyListener;
import anet.channel.strategy.StrategyCenter;
import anet.channel.strategy.dispatch.HttpDispatcher;
import anetwork.channel.config.NetworkConfigCenter;
import anetwork.channel.http.NetworkSdkSetting;
import mtopsdk.common.util.TBSdkLog;
import mtopsdk.mtop.global.SwitchConfig;
import mtopsdk.mtop.intf.Mtop;
import mtopsdk.mtop.intf.MtopEnablePropertyType;
import mtopsdk.mtop.intf.MtopSetting;
import mtopsdk.security.LocalInnerSignImpl;
/**
* Created by jason on 18/1/15.
*/
public class EmasInit {
public static final int DEBUG = 1; //測試環境
public static final int RELEASE = 2; //釋出環境
/*配置資訊*/
protected String mAppkey = "20000297";//"10000066";//"10000039";//"10000078";//"60039748";
protected String mAppSecret = "53b92bd7eb29931ab25580506285c9b8";//"1426c10c5ce57d6cb29e016a816421a7";//"c7795717b2306055f21fb33418c1d011";//"2e00a7e9ab2048daabd4977170d37c4a";//"ab5ff148782b467bb0b310c4acd70abd"//"fe240d4b8f4b31283863cc9d707e2cb1"
protected String mCacheURL = "http://cdn.emas-poc.com/eweex/";
protected String mACCSDoman = "accs.emas-poc.com";
protected Map<String, String> mIPStrategy;
protected String mMTOPDoman = "aserver.emas-poc.com";
protected String mHAUniversalHost = "adash.emas-poc.com";
protected String mHAOSSBucketName = "emas-ha-remote-log-poc";
protected String mHARSAPublicKey;
protected String mStartActivity = "com.taobao.demo.WelcomActivity";
protected String mChannelID = "[email protected]_Android_" + BuildConfig.VERSION_NAME;
protected String PUSH_TAG = "POC";
protected boolean mUseHttp = true;
protected int mEnv = DEBUG;
private Application mApplication;
private static final String TAG = "EmasInit";
public final static String SERVICE_ID = "4272_mock";
//private static final String[] TEST_EMAS = new String[]{"acs.alibaba-inc.com", "11.163.130.35", "80"};
private final static Map<String, String> SERVICES = new HashMap<String, String>() {
private static final long serialVersionUID = 2527336442338823324L;
{
//自定義服務
put(SERVICE_ID, "com.taobao.demo.accs.TestAccsService");
}
};
/**
* 切換成單例
*/
private static class CreateInstance {
private static EmasInit instance = new EmasInit();
}
public static EmasInit getInstance() {
return CreateInstance.instance;
}
private EmasInit() {
//不能生成物件
}
//先設定mApplication
public EmasInit setmApplication(Application application) {
this.mApplication = application;
//初始化
firstInit();
return this;
}
private void firstInit() {
Application application = mApplication;
StringBuilder builder = new StringBuilder();
try {
int id = application.getResources().getIdentifier("ttid", "string", application.getPackageName());
if (id > 0) {
mChannelID = builder.append(application.getString(id))
.append("@")
.append(application.getResources().getString(application.getApplicationInfo().labelRes))
.append("_")
.append("Android")
.append("_")
.append(BuildConfig.VERSION_NAME).toString();
}
} catch (Resources.NotFoundException e) {
Log.d(TAG,
相關推薦
阿里熱修復之Sophix——專有云釋出版整合步驟
阿里熱修復之Sophix——專有云
應公司業務需求,和阿里雲的阿里熱修復相關技術人員合作,整了波專有云的熱修復整合Demo
一、app/build.gradle下的程式碼
注意:第二行的程式碼在整合中要開啟的,這裡註釋掉是為讓app可以本地run起來看到介面
apply
阿里熱修復之Sophix——公有云釋出版整合步驟
Sophix 公有云接入
去年的時候寫的一篇阿里雲熱修復的文章,那時它還是在公測階段,一直沒能投產,而今,公司專案需要整合已經投產的阿里Sophix功能,所以再次集成了一遍,記錄下了步驟和遇到的一些問題。
一、在app/build.gradle中新增依賴包
dependenc
Android探索之旅(第二十五篇)騰訊熱修復框架Tinker與阿里第三代熱修復框架Sophix對比
本人在開發專案中仍然使用的還是Tinker熱修復框架,在專案中遇到Bug,Tinker都能夠解決,可以說是萬無一失,但是在網際網路時代也必須懷揣著新生的事物必將取代先前的事物的心態,因此就索性集成了Sophix,下面由我來分析一下它們之間的區別
從上
Android熱修復之AndFix使用教程
AndFix的github地址
AndFix
全稱Android hot-fix,是alibaba的Android熱修復框架,支援Android 2.3到6.0的版本,支援arm與X86系統架構,支援Dalvik和ART Runtime。
原理
AndFix的原理就是方法的替換,把有bug的方法替換成
andfix熱修復之生成dex檔案
熱修復中用到把修改好的java檔案編譯成class再打包生成dex 步驟: 1、配置dx.bat到環境變數 選擇androidsdk\build-tools中任一版本的都行。 配置dx.bat的路徑到系統的PATH路徑。 3、將要生成dex的class檔案 連同全路徑資料夾拷貝
騰訊Tinker 熱修復 Andriod studio 3.0 配置和整合(二)多渠道打包和補丁釋出
騰訊Tinker 熱修復 Andriod studio 3.0 多渠道打包和釋出補丁方式推薦
本文說明 在之前我已經分享了Tinker 熱修復的 Andriod studio3.0 初次配置和整合,時隔這麼久來寫一下我對Thinker多渠道打包的理解和記錄,希望對大家有幫助。這篇文
android熱修復之Robust使用
最近美團點評開源了其基於Instant Run 的熱修復方案Robust,並且官方公佈了修復率達99.9%成功率,聽起來蠻誘人的。當然,市面上還有其他兩種熱修復方案:
基於multidex的熱更新方案,如企鵝的Tinker
基於native hook方案,如
IOS熱修復之 JSPatch 實現方案
1簡介
1.1目的
新版本上線後發現有個嚴重的bug,可能會導致crash率激增,可能會使網路請求無法發出,這時能做的只是趕緊修復bug然後提交等待漫長的appStore稽核,再盼望使用者
阿里熱修復學習總結
阿里熱修復學習
1.去官網https://github.com/alibaba/AndFix 專案檢視依賴並匯入依賴
compile 'com.alipay.euler:andfix:[email protected]'
2.在Application裡面做熱
Android熱修復之Tinker
前言
Tencent 開源 “Tinker–微信Android熱補丁方案” 已經很長時間了,無奈自己太懶了,一直沒有時間去嘗試一下。最近公司準備開新專案,我準備接入這個熱修復框架,這樣能夠及時去處理App中在使用過程產生的Bug問題,而不必為了處理一個
Android熱修復之QQ空間與QFix方案
前文介紹了阿里的Hotfix,它的熱修復思路是粗暴的底層方法指標的替換,今天我們來看看另一種思路,也就是QQ空間團隊提供的熱修復方案。要理解這個方案的思想,先要理解dex分包技術,這類文章很多,大家可以自己google研究學習,這裡通過簡單分析一下Android
Android基於TinkerPatch的超詳細熱修復之旅
在我們開始熱修復之旅之前,大家需要先明白的是這篇文章是基於TinkerPatch的,而不是微信的Tinker,雖然TinkerPatch是基於Tinker的專案,但他們終歸是兩碼事。先附上Tinkerpatch的官網地址。1.整合TinkerPathSDK:登入官網,獲取Ap
阿里熱修復SophixStubApplication中java.lang.ClassNotFoundException引起的閃退
ava.lang.ClassNotFoundExceptionat com.taobao.sophix.b.a.a.a.findClass(Sophix:199)at java.lang.ClassLoader.loadClass(ClassLoader.java:511)a
Android熱修復之微信Tinker使用初探
前幾天,萬眾期待的微信團隊的Android熱修復框架tinker終於在GitHub上開源了。
今天拿下來整合使用了一下,發現md上對整合使用的過程介紹的比較精簡(後來發現wiki上面倒是很詳細,需要的同學可以自己去看),這裡記錄一下我整合使用的過程。
一、
騰訊Tinker 熱修復 Andriod studio 3.0 配置和整合(三)Bugly整合
騰訊Tinker 熱修復 Andriod studio 3.0 Bugly整合和多渠道補丁管理髮布
本文說明 上一篇我說完了騰訊Tinker 熱修復之多渠道打包,這篇我們來初步瞭解下騰訊Tinker和Bugly結合來做熱修復多渠道補丁管理和整合。(其實在上週我已經整合測試完了dem
騰訊Tinker 熱修復 Andriod studio 3.0 配置和整合(一)
本文說明 面試的時候經常問我有沒有用過熱修復?用誰的?能說下原理嗎?當時我回答得不好,畢竟以前的專案都沒有用,又不敢裝逼,mmp,但是基本流程還是知道的,所以我們來初探下Tinker 這個熱修復,如果我是Andriod studio 2.3的話,我還不怎麼想寫這個文章,畢竟太多了,沒有
一步一步教你實現阿里巴巴的Sophix熱修復(一)
1.0 整合準備
gradle遠端倉庫依賴, 開啟專案找到app的build.gradle檔案,新增如下配置:
新增maven倉庫地址:
repositories {
maven {
url "http://maven.ali
百川熱修復sophix和阿里支付 UTDID 依賴衝突問題
今日在專案中新增sophix,參照官方文件走下來,最後編譯時候出現
Warning:com.ta.utdid2.b.a.j: can't find referenced field 'boolean e' in program class com.ta.utdid2.b.a.d
記錄一下阿里雲Sophix熱修復使用時的注意
1、確保沒有新增四大元件,沒有修改AndroidManifest.xml和入口Application中的程式碼。
2、如果使用了混淆,確保打包使用的新舊包的混淆保持已經確保一致,如新包apply了舊包的mapping檔案。
3、如果使用了加固,確保打包使用的新舊包都是
Android之移動熱修復
com don load query 監聽 基線 mis tps 事件 阿裏雲最近推出了移動熱修復服務,聽說這個服務傻瓜式接入,性能相對較好,對新技術比較好奇的我決定嘗試一下。
移動熱修復.png
首先,需要開通這個服務,創建應用
創建應用.png
然後,在