-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0f75106
Showing
143 changed files
with
9,217 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Auto detect text files and perform LF normalization | ||
* text=auto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
*.iml | ||
.gradle | ||
/local.properties | ||
/.idea/* | ||
.DS_Store* | ||
/build | ||
/captures | ||
.externalNativeBuild | ||
.cxx | ||
local.properties |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
BSD 3-Clause License | ||
|
||
Copyright (c) 2024, Milk | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
3. Neither the name of the copyright holder nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# BlackShadow | ||
接入shadow需要大量的二次开发工作,其实一般小型项目其实并不想关心太多的逻辑和管理,只想开袋即食,奈何Shadow也并没有提供这方面的能力,所有开发者接入都需要二次开发才可以使用,包括本次我自己使用也是,所以花了点时间在Shadow的基础上包装了一层,几乎不需要任何二次开发,即可通过几个简单的接口使用与管理Shadow,屏蔽了Shadow所有的技术细节。 | ||
|
||
## 依赖安装 | ||
``` | ||
git clone https://github.com/Tencent/Shadow.git | ||
或者 | ||
git clone https://github.com/nnjun/Shadow.git (建议使用这个) | ||
``` | ||
|
||
拉下仓库后,进入仓库目录,将Shadow发布到本地maven仓库。 | ||
``` | ||
./gradlew publish | ||
``` | ||
|
||
|
||
## 使用方法 | ||
在Application#attachBaseContext中初始化 | ||
``` | ||
@Override | ||
protected void attachBaseContext(Context base) { | ||
super.attachBaseContext(base); | ||
BlackShadow.get().init(this); | ||
} | ||
``` | ||
|
||
安装与启动 | ||
``` | ||
InstallResult installResult = BlackShadow.get().installPlugin("plugin-key", new File(pluginAPk)); | ||
if (installResult.isSuccess()) { | ||
Intent intent = new Intent(); | ||
intent.xxxxxxxxxxxxx | ||
BlackShadow.get().launchPlugin("plugin-key", intent); | ||
} | ||
``` | ||
|
||
其余接口 | ||
``` | ||
// 仅启动application | ||
public boolean callApplication(String pluginKey) | ||
// 获取所有已安装的plugin | ||
public List<InstalledPlugin> getInstalledPlugins() | ||
// 获取某个已安装的plugin | ||
public InstalledPlugin getInstalledPlugin(String pluginKey); | ||
// 卸载某个plugin | ||
public void uninstallPlugin(String pluginKey) | ||
// 停止某个plugin | ||
public void stopPlugin(String pluginKey) | ||
// 停止所有plugin | ||
public void stopAllPlugin() | ||
// 获取正在运行的plugin | ||
public List<RunningPlugin> getRunningPlugins() | ||
``` | ||
|
||
## 基于Shadow的技术方案 | ||
BlackShadow使用的是非动态方案,支持同时最多10个插件运行,分别都是各自单独的进程。install与launch都有boolean返回值,可反馈出插件是否安装/启动成功。 | ||
|
||
## 插件包名与宿主包名不相同的需求 | ||
由于Shadow内核要求,plugin与宿主的包名必须一致,否则会出现问题,然而我方产品可能会存在不同的渠道包不同的包名,但是插件没有必要分开很多份,所以BlackShadow是支持插件与宿主不同的包名,处理的方法是在install时如果不一样,BlackShaodw会自动将插件的包名改成与宿主相同,不需要额外开发,直接进行install即可,BlackShadow会自动处理该问题。 | ||
|
||
假如你也有这个需求,则需要自行修改Shaodw内核,将这个检测去除,或者安装我这个内核。其余内容都是与官方保持一致。 | ||
|
||
https://github.com/nnjun/Shadow/commit/4f769afdd4e86814fa09d1ef9b19d6ea68f175fd | ||
|
||
### 不是修改了包名了吗?为什么还需要去除检测? | ||
因为Shadow的包名基准是由Shadow编译时生成的com.tencent.shadow.core.manifest_parser.PluginManifest文件来确定,BlackShadow只会修改Manifest中的包名,并不会修改PluginManifest.class内的硬编码包名,所以需要去除检测,否则无法运行。 | ||
|
||
如果你没有以上的场景,那么请无视上面这一段内容,直接使用即可。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
plugins { | ||
id 'com.android.application' | ||
} | ||
android { | ||
namespace rootProject.ext.hostPackageName | ||
compileSdk rootProject.ext.compileSdkVersion | ||
|
||
defaultConfig { | ||
applicationId rootProject.ext.hostPackageName | ||
minSdk rootProject.ext.minSdkVersion | ||
targetSdk rootProject.ext.targetSdkVersion | ||
versionCode 1 | ||
versionName "1.0" | ||
|
||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation 'androidx.appcompat:appcompat:1.4.1' | ||
implementation 'com.google.android.material:material:1.4.0' | ||
|
||
implementation project(":black-shadow") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile | ||
-keep class top.niunaijun.shadow.common.** { *; } | ||
|
||
-keep class top.niunaijun.shadow.BlackShadow { | ||
public *; | ||
} | ||
-keep class top.niunaijun.shadow.container.** { *; } | ||
-keep class com.tencent.shadow.** { *; } |
26 changes: 26 additions & 0 deletions
26
app/src/androidTest/java/top/niunaijun/blackshadow/ExampleInstrumentedTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package top.niunaijun.blackshadow; | ||
|
||
import android.content.Context; | ||
|
||
import androidx.test.platform.app.InstrumentationRegistry; | ||
import androidx.test.ext.junit.runners.AndroidJUnit4; | ||
|
||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a> | ||
*/ | ||
@RunWith(AndroidJUnit4.class) | ||
public class ExampleInstrumentedTest { | ||
@Test | ||
public void useAppContext() { | ||
// Context of the app under test. | ||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); | ||
assertEquals("top.niunaijun.blackshadow", appContext.getPackageName()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:tools="http://schemas.android.com/tools"> | ||
|
||
<application | ||
android:name="top.niunaijun.blackshadow.BlackShadowApplication" | ||
android:allowBackup="true" | ||
android:dataExtractionRules="@xml/data_extraction_rules" | ||
android:fullBackupContent="@xml/backup_rules" | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="@string/app_name" | ||
android:roundIcon="@mipmap/ic_launcher_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/Theme.BlackShadow" | ||
tools:targetApi="31"> | ||
|
||
<activity | ||
android:name="top.niunaijun.blackshadow.MainActivity" | ||
android:exported="true" | ||
android:label="@string/app_name" | ||
android:theme="@style/Theme.BlackShadow"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
|
||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
</application> | ||
|
||
</manifest> |
Binary file not shown.
28 changes: 28 additions & 0 deletions
28
app/src/main/java/top/niunaijun/blackshadow/BlackShadowApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package top.niunaijun.blackshadow; | ||
|
||
import android.app.Application; | ||
import android.content.Context; | ||
|
||
import top.niunaijun.blackshadow.utils.FileUtils; | ||
import top.niunaijun.shadow.BlackShadow; | ||
|
||
/** | ||
* Created by Milk on 2024/3/17. | ||
* * ∧_∧ | ||
* (`・ω・∥ | ||
* 丶 つ0 | ||
* しーJ | ||
* 此处无Bug | ||
*/ | ||
public class BlackShadowApplication extends Application { | ||
@Override | ||
protected void attachBaseContext(Context base) { | ||
super.attachBaseContext(base); | ||
BlackShadow.get().init(this); | ||
} | ||
|
||
@Override | ||
public void onCreate() { | ||
super.onCreate(); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
app/src/main/java/top/niunaijun/blackshadow/MainActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package top.niunaijun.blackshadow; | ||
|
||
import android.content.Intent; | ||
import android.os.Bundle; | ||
import android.util.Log; | ||
import android.widget.Toast; | ||
|
||
import androidx.appcompat.app.AppCompatActivity; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
|
||
import top.niunaijun.blackshadow.utils.FileUtils; | ||
import top.niunaijun.shadow.BlackShadow; | ||
import top.niunaijun.shadow.common.InstallResult; | ||
import top.niunaijun.shadow.common.InstalledPlugin; | ||
import top.niunaijun.shadow.host.R; | ||
|
||
public class MainActivity extends AppCompatActivity { | ||
public static final String TAG = "MainActivity"; | ||
|
||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
setContentView(R.layout.activity_main); | ||
|
||
findViewById(R.id.btn_start).setOnClickListener(v -> { | ||
Toast.makeText(this, "启动中", Toast.LENGTH_SHORT).show(); | ||
new Thread(this::handlePlugin).start(); | ||
}); | ||
} | ||
|
||
private void handlePlugin() { | ||
File plugin = new File(getFilesDir(), "plugin.apk"); | ||
copyAssetsPlugin(plugin); | ||
|
||
// 允许访问宿主的白名单类 | ||
String[] hostWhiteList = new String[]{ | ||
"com.tencent.*", | ||
"okhttp3", | ||
"okhttp3.*", | ||
"okhttp3.**", | ||
"com.google.**" | ||
}; | ||
|
||
Intent launcher = new Intent(); | ||
launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||
launcher.setClassName("top.niunaijun.shadow.host", "top.niunaijun.shadow.plugin.MainActivity"); | ||
|
||
String key = "app-plugin"; | ||
InstalledPlugin installedPlugin = BlackShadow.get().getInstalledPlugin(key); | ||
if (installedPlugin == null) { | ||
InstallResult installResult = BlackShadow.get().installPlugin(key, plugin, hostWhiteList, launcher); | ||
Log.d(TAG, "installPlugin: " + installResult); | ||
installedPlugin = BlackShadow.get().getInstalledPlugin(key); | ||
} | ||
BlackShadow.get().launchPlugin(installedPlugin.pluginKey, installedPlugin.launcher); | ||
} | ||
|
||
private void copyAssetsPlugin(File target) { | ||
try { | ||
if (target.exists()) { | ||
return; | ||
} | ||
FileUtils.copyFile(this.getAssets().open("plugin.apk"), target); | ||
} catch (IOException ioException) { | ||
ioException.printStackTrace(); | ||
} | ||
} | ||
} |
Oops, something went wrong.