Skip to content

Commit

Permalink
add wrapper class to compatible android4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
leijf committed Oct 15, 2019
1 parent a93091e commit 332b3ab
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 43 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,39 @@ gradle demo:build
```

build the demo project to get example apk

> If you want to be compatible with android4.1~android4.4, all classes referenced to corestub in Application must add a wrapper to pass through methods in those classes. Such as:

Application中引用LIB:

```
import com.lxzh123.corestub.LIB;
...
int square = LIB.get().square(5);
Log.d(TAG, "call lib.square:" + square);
```

Add a wrapper class to ensure that LIB is not exposed to Application:

```
package com.lxzh123.sdkshellapp;
import com.lxzh123.libcore.LIB;
/**
* Compatible with android4.x version
*/
public class CoreStub {
public static int init(int param) {
return LIB.get().square(param);
}
}
```

Reference LIB indirectly by referencing the wrapper class:

```
int square = CoreStub.init(5);
Log.d(TAG, "call lib.square:" + square);
```
33 changes: 33 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,36 @@ gradle demo:build
```

编译demo工程生成演示apk

> 如果需要兼容android4.1~android4.4,所有Application中引用到corestub中的类必需增加一个包装类透传这些类中的方法,如:
Application中引用LIB:
```
import com.lxzh123.corestub.LIB;
...
int square = LIB.get().square(5);
Log.d(TAG, "call lib.square:" + square);
```
增加一个包装类,确保LIB不暴露在Application中:

```
package com.lxzh123.sdkshellapp;
import com.lxzh123.libcore.LIB;
/**
* Compatible with android4.x version
*/
public class CoreStub {
public static int init(int param) {
return LIB.get().square(param);
}
}
```

通过引用包装类间接引用LIB:

```
int square = CoreStub.init(5);
Log.d(TAG, "call lib.square:" + square);
```
12 changes: 10 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
apply plugin: 'com.android.application'

apply plugin: 'patch-gradle-plugin'
patchPlugin{
enable = true
// excludePackage = ['com/lxzh123/sdkshellapp/activity']
}

android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.lxzh123.sdkshellapp"
minSdkVersion 21
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// multiDexEnable true
}
buildTypes {
release {
Expand Down Expand Up @@ -43,7 +50,7 @@ build {
}
}

build.dependsOn([':corestub:build', ':libshell:build'])
//build.dependsOn([':corestub:build', ':libshell:build'])

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
Expand All @@ -54,4 +61,5 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
compileOnly project(':corestub')
implementation project(':libshell')
implementation 'com.android.support:multidex:1.0.0'
}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:name="com.lxzh123.sdkshellapp.App">
<activity android:name="com.lxzh123.sdkshellapp.MainActivity">
<activity android:name="com.lxzh123.sdkshellapp.activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
39 changes: 37 additions & 2 deletions app/src/main/java/com/lxzh123/sdkshellapp/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import android.content.Context;
import android.util.Log;

import com.lxzh123.libshell.Loader;
import com.lxzh123.libshell.Core;

import java.lang.reflect.Method;

public class App extends Application {

Expand All @@ -13,14 +15,47 @@ public class App extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
Log.d(TAG, "attachBaseContext");
try {
Loader.init(base);
Core.init(base);
} catch (Exception ex) {
Log.e(TAG, "attachBaseContext Exception ex=" + ex.getMessage());
ex.printStackTrace();
}
}

@Override
public void onCreate() {
super.onCreate();
Class clz = null;
Log.d(TAG, "onCreate");
while (clz == null) {
try {
clz = Class.forName("com.lxzh123.libcore.LIB");
if (clz != null) {
Log.d(TAG, "App.onCreate Class.forName success");
Method getMethod = clz.getDeclaredMethod("get");
Method squareMethod = clz.getDeclaredMethod("square", int.class);
Object LIBObj = getMethod.invoke(clz, null);
Object square = squareMethod.invoke(LIBObj, 5);
Log.d(TAG, "call LIBObj.square:" + square);
} else {
Log.d(TAG, "App.onCreate Class.forName failed");
}
} catch (Exception ex) {
ex.printStackTrace();
}
try {
Thread.sleep(200);
} catch (Exception ex) {
Log.d(TAG, "Class.forName sleep:200ms");
}
}

int square = CoreStub.init(5);
Log.d(TAG, "call lib.square:" + square);
}

@Override
public void onTerminate() {
super.onTerminate();
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/com/lxzh123/sdkshellapp/CoreStub.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.lxzh123.sdkshellapp;

import com.lxzh123.libcore.LIB;

/**
* Compatible with android4.x version
*/
public class CoreStub {
public static int init(int param) {
return LIB.get().square(param);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.lxzh123.sdkshellapp;
package com.lxzh123.sdkshellapp.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import com.lxzh123.libcore.LIB;
import com.lxzh123.sdkshellapp.R;

public class MainActivity extends AppCompatActivity {

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
xmlns:tools="http:https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
tools:context=".activity.MainActivity">

<TextView
android:id="@+id/text"
Expand Down
9 changes: 7 additions & 2 deletions corestub/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ android {

}

def copyFile(String fromFile, String intoDir, String fileName) {
def copyFile(String fromFileName, String intoDir, String fileName) {
def fromFile = new File(fromFileName)
if (!fromFile.exists()) {
println("copyFile error: fromFile:" + fromFile.getAbsolutePath() + " is not exists")
return
}
def intoFileName = intoDir + fileName
def intoFile = new File(intoFileName)
if (intoFile.exists()) {
intoFile.delete()
}
println("fromFile=" + fromFile + ", exists=" + (new File(fromFile).exists()))
println("fromFile=" + fromFileName)
println("intoDir=" + intoDir)
println("fileName=" + fileName)
println("before copy, file=" + intoFile.getAbsolutePath() + ", exists=" + intoFile.exists())
Expand Down
2 changes: 1 addition & 1 deletion libshell/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ android {


defaultConfig {
minSdkVersion 16
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
Expand Down
Binary file modified libshell/src/main/assets/sdk.data
Binary file not shown.
59 changes: 29 additions & 30 deletions libshell/src/main/cpp/injector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,20 @@
#include <sys/stat.h>
#include <sys/mman.h>

const char* PKG_NAME = "com/lxzh123/libshell";
#define JNIREG_CLASS "com/lxzh123/libshell/Helper" //指定要注册的类
const char *PKG_NAME = "com/lxzh123/libshell";
const char *SHELL_CONFIG_NAME = "com/lxzh123/libshell/BuildConfig";
#define JNIREG_CLASS "com/lxzh123/libshell/Helper"

int g_sdk_int = 0;
bool g_isArt = false;
char g_priv_dir[256] = {0};
const char *g_file_dir = nullptr;
const char BUILD_CONFIG[] = "/BuildConfig";
#define MAGIC ".shell"
const char* DAT_NAME = ".data";
const char* TAR_NAME = ".dex";
const char *DAT_NAME = ".data";
const char *TAR_NAME = ".dex";

void inject_dex(JNIEnv *env, jobject ctx, const char *dex_path);

char *get_config_class_name(JNIEnv *env, jstring pkg_name) {
int pkg_name_len = env->GetStringLength(pkg_name);
char *config_name = (char *) env->GetStringUTFChars(pkg_name, NULL);

strcat(config_name, BUILD_CONFIG);
for (int i = 0; i < pkg_name_len; i++) {
if (config_name[i] == '.') {
config_name[i] = '/';
}
}

return config_name;
}

extern "C"
JNIEXPORT jstring JNICALL Helper_init
(JNIEnv *env, jclass, jobject ctx, jboolean injectDex) {
Expand All @@ -59,17 +45,30 @@ JNIEXPORT jstring JNICALL Helper_init
"()Ljava/lang/String;");
jstring pkg_name = static_cast<jstring >( env->CallObjectMethod(ctx, getPackageNameMethod));
char *c_pkg_name = (char *) env->GetStringUTFChars(pkg_name, NULL);
char *config_name = get_config_class_name(env, env->NewStringUTF(PKG_NAME));
// char *config_name = get_config_class_name();
LOGD("[+] pkgName:%s configName:%s", c_pkg_name, config_name);
LOGD("[+] pkgName:%s configName:%s", c_pkg_name, SHELL_CONFIG_NAME);

jclass BuildConfigClass = env->FindClass(config_name);
jfieldID sdkDexNameFieldId = env->GetStaticFieldID(BuildConfigClass, "SDK_DEX_NAME", "Ljava/lang/String;");
jfieldID sdkMixNameFieldId = env->GetStaticFieldID(BuildConfigClass, "SDK_MIX_NAME", "Ljava/lang/String;");
jclass BuildConfigClass = env->FindClass(SHELL_CONFIG_NAME);
if (env->ExceptionCheck()) {
LOGE("[-] FindClass:%s failed", SHELL_CONFIG_NAME);
return env->NewStringUTF("error");
}
jfieldID sdkDexNameFieldId = env->GetStaticFieldID(BuildConfigClass, "SDK_DEX_NAME",
"Ljava/lang/String;");
if (env->ExceptionCheck()) {
LOGE("[-] GetStaticFieldID:%s failed", "SDK_DEX_NAME");
return env->NewStringUTF("error");
}
jfieldID sdkMixNameFieldId = env->GetStaticFieldID(BuildConfigClass, "SDK_MIX_NAME",
"Ljava/lang/String;");
if (env->ExceptionCheck()) {
LOGE("[-] GetStaticFieldID:%s failed", "SDK_MIX_NAME");
return env->NewStringUTF("error");
}

jstring dexName = (jstring)env->GetStaticObjectField(BuildConfigClass, sdkDexNameFieldId);
jstring mixName = (jstring)env->GetStaticObjectField(BuildConfigClass, sdkMixNameFieldId);
LOGD("[+] dexName:%s mixName:%s", env->GetStringUTFChars(dexName, NULL), env->GetStringUTFChars(mixName, NULL));
jstring dexName = (jstring) env->GetStaticObjectField(BuildConfigClass, sdkDexNameFieldId);
jstring mixName = (jstring) env->GetStaticObjectField(BuildConfigClass, sdkMixNameFieldId);
LOGD("[+] dexName:%s mixName:%s", env->GetStringUTFChars(dexName, NULL),
env->GetStringUTFChars(mixName, NULL));

DAT_NAME = env->GetStringUTFChars(mixName, NULL);
TAR_NAME = env->GetStringUTFChars(dexName, NULL);
Expand Down Expand Up @@ -163,10 +162,10 @@ void inject_dex(JNIEnv *env, jobject ctx, const char *dex_path) {
jclass ElementClass = env->GetObjectClass(env->GetObjectArrayElement(dexElement1, 0));
// jclass ElementClass = env->FindClass("dalvik/system/DexPathList$Element");
jobjectArray newElements = env->NewObjectArray(len + 1, ElementClass, NULL);
env->SetObjectArrayElement(newElements, 0, env->GetObjectArrayElement(dexElement2, 0));
for (int i = 0; i < len; ++i) {
env->SetObjectArrayElement(newElements, i, env->GetObjectArrayElement(dexElement1, i));
env->SetObjectArrayElement(newElements, i + 1, env->GetObjectArrayElement(dexElement1, i));
}
env->SetObjectArrayElement(newElements, len, env->GetObjectArrayElement(dexElement2, 0));
env->SetObjectField(pathList1, dexElementsId, newElements);

LOGD("[+] inject_dex 7");
Expand Down
Loading

0 comments on commit 332b3ab

Please sign in to comment.