Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions projects/sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ manager在加载"插件"时,首先需要先加载"插件"中的runtime和loade

在这个Sample目录下,提供了两种示例工程:

## 源码依赖SDK的Sample
## 源码依赖SDK的Sample(`projects/sample/source`)
* `sample-host`是宿主应用
* `sample-manager`是插件管理器的动态实现
* `sample-plugin/sample-loader`是loader的动态实现,业务主要在这里定义插件组件和壳子代理组件的配对关系等。
Expand All @@ -28,7 +28,7 @@ manager在加载"插件"时,首先需要先加载"插件"中的runtime和loade
使用时可以直接在Android Studio中选择运行`sample-host`模块。
`sample-host`在构建中会自动打包manager和"插件"到assets中,在运行时自动释放模拟下载过程。

## 二进制Maven依赖SDK的Sample
## 二进制Maven依赖SDK的Sample(`projects/sample/maven`)
源码依赖SDK的Sample中对Shadow SDK的依赖配置不适用于正式业务接入。
Shadow实现了完整的Maven发布脚本,支持方便的Maven依赖。

Expand Down
49 changes: 49 additions & 0 deletions projects/sample/source/sample-host-lib/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion project.COMPILE_SDK_VERSION


defaultConfig {
minSdkVersion project.MIN_SDK_VERSION
targetSdkVersion project.TARGET_SDK_VERSION
versionCode project.VERSION_CODE
versionName project.VERSION_NAME

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
consumerProguardFiles 'sample-host-lib.pro'
}
}

}

//下面的jarPackage和afterEvaluate负责让这个aar再生成一个输出jar包的任务
def jarPackage(buildType) {
return tasks.create("jar${buildType.capitalize()}Package", Copy) {
def aarFile = file(project.buildDir.path + "/outputs/aar/${project.name}-${buildType}.aar")
def outputDir = file(project.buildDir.path + "/outputs/jar")

from zipTree(aarFile)
into outputDir
include 'classes.jar'
rename 'classes.jar', "${project.name}-${buildType}.jar"
group = 'build'
description = '生成jar包'
}.dependsOn(project.getTasksByName("assemble${buildType.capitalize()}", false).first())
}

afterEvaluate {
android {
buildTypes.findAll().each { buildType ->
def buildTypeName = buildType.getName()
jarPackage(buildTypeName)
}
}
}
4 changes: 4 additions & 0 deletions projects/sample/source/sample-host-lib/sample-host-lib.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#让宿主在打包时能够keep住插件要使用到的类名和方法
-keep class com.tencent.shadow.sample.host.lib.HostUiLayerProvider{
public *;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<manifest package="com.tencent.shadow.sample.host.lib" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Tencent is pleased to support the open source community by making Tencent Shadow available.
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of
* the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.tencent.shadow.sample.host.lib;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;

/**
* 这是一个将要打包到宿主中的类。原本的目的是宿主依赖插件,宿主
*/
public class HostUiLayerProvider {
private static HostUiLayerProvider sInstance;

public static void init(Context mHostApplicationContext) {
sInstance = new HostUiLayerProvider(mHostApplicationContext);
}

public static HostUiLayerProvider getInstance() {
return sInstance;
}

final private Context mHostApplicationContext;

private HostUiLayerProvider(Context mHostApplicationContext) {
this.mHostApplicationContext = mHostApplicationContext;
}

public View buildHostUiLayer() {
return LayoutInflater.from(mHostApplicationContext)
.inflate(R.layout.host_ui_layer_layout, null, false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/holo_red_dark"
android:text="Host UI Layer" />
</LinearLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies {
implementation 'com.tencent.shadow.core:common'
implementation 'com.tencent.shadow.dynamic:dynamic-host'
implementation project(':sample-constant')
implementation project(':sample-host-lib')
}

def createCopyTask(projectName, buildType, name, apkName, inputFile, taskName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.tencent.shadow.core.common.LoggerFactory;
import com.tencent.shadow.dynamic.host.DynamicRuntime;
import com.tencent.shadow.dynamic.host.PluginManager;
import com.tencent.shadow.sample.host.lib.HostUiLayerProvider;
import com.tencent.shadow.sample.host.manager.Shadow;

import java.io.File;
Expand All @@ -50,6 +51,7 @@ public void onCreate() {

PluginHelper.getInstance().init(this);

HostUiLayerProvider.init(this);
}

private static void detectNonSdkApiUsageOnAndroidP() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ dependencies {
implementation project(":pinnedheaderexpandablelistview")
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.android.support:support-v4:27.1.1'

//注意sample-host-lib要用compileOnly编译而不打包在插件中。在packagePlugin任务中配置hostWhiteList允许插件访问宿主的类。
compileOnly files("${project(":sample-host-lib").getBuildDir()}/outputs/jar/sample-host-lib-debug.jar")
}

preBuild.dependsOn(":sample-host-lib:jarDebugPackage")
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
<activity android:name="com.tencent.shadow.sample.plugin.app.lib.usecases.context.ActivityContextSubDirTestActivity" />

<activity android:name="com.tencent.shadow.sample.plugin.app.lib.usecases.context.ApplicationContextSubDirTestActivity" />
<activity android:name=".usecases.host_communication.PluginUseHostClassActivity" />

<provider
android:authorities="com.tencent.shadow.provider.test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import com.tencent.shadow.sample.plugin.app.lib.gallery.cases.entity.UseCase;
import com.tencent.shadow.sample.plugin.app.lib.gallery.cases.entity.UseCaseCategory;
import com.tencent.shadow.sample.plugin.app.lib.gallery.util.PluginChecker;
import com.tencent.shadow.sample.plugin.app.lib.usecases.activity.TestActivityOnCreate;
import com.tencent.shadow.sample.plugin.app.lib.usecases.activity.TestActivityOrientation;
import com.tencent.shadow.sample.plugin.app.lib.usecases.activity.TestActivityReCreate;
Expand All @@ -31,6 +30,7 @@
import com.tencent.shadow.sample.plugin.app.lib.usecases.dialog.TestDialogActivity;
import com.tencent.shadow.sample.plugin.app.lib.usecases.fragment.TestDynamicFragmentActivity;
import com.tencent.shadow.sample.plugin.app.lib.usecases.fragment.TestXmlFragmentActivity;
import com.tencent.shadow.sample.plugin.app.lib.usecases.host_communication.PluginUseHostClassActivity;
import com.tencent.shadow.sample.plugin.app.lib.usecases.packagemanager.TestPackageManagerActivity;
import com.tencent.shadow.sample.plugin.app.lib.usecases.provider.TestDBContentProviderActivity;
import com.tencent.shadow.sample.plugin.app.lib.usecases.provider.TestFileProviderActivity;
Expand Down Expand Up @@ -99,6 +99,11 @@ public static void initCase() {
new ApplicationContextSubDirTestActivity.Case(),
});
useCases.add(contextCategory);

UseCaseCategory communicationCategory = new UseCaseCategory("插件和宿主通信相关测试用例", new UseCase[]{
new PluginUseHostClassActivity.Case(),
});
useCases.add(communicationCategory);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Tencent is pleased to support the open source community by making Tencent Shadow available.
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of
* the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.tencent.shadow.sample.plugin.app.lib.usecases.host_communication;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.LinearLayout;

import com.tencent.shadow.sample.host.lib.HostUiLayerProvider;
import com.tencent.shadow.sample.plugin.app.lib.gallery.BaseActivity;
import com.tencent.shadow.sample.plugin.app.lib.gallery.cases.entity.UseCase;

public class PluginUseHostClassActivity extends BaseActivity {
public static class Case extends UseCase {
@Override
public String getName() {
return "插件使用宿主类测试";
}

@Override
public String getSummary() {
return "测试插件中调用宿主类的方法";
}

@Override
public Class getPageClass() {
return PluginUseHostClassActivity.class;
}
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

LinearLayout linearLayout = new LinearLayout(this);

HostUiLayerProvider hostUiLayerProvider = HostUiLayerProvider.getInstance();
View hostUiLayer = hostUiLayerProvider.buildHostUiLayer();
linearLayout.addView(hostUiLayer);

setContentView(linearLayout);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ shadow {
partKey = 'sample-plugin-app'
buildTask = ':sample-plugin-app:assembleDebug'
apkName = 'sample-plugin-app-debug.apk'
apkPath = 'projects/sample/sample-plugin/sample-plugin-app/build/outputs/apk/debug/sample-plugin-app-debug.apk'
apkPath = 'projects/sample/source/sample-plugin/sample-plugin-app/build/outputs/apk/debug/sample-plugin-app-debug.apk'
hostWhiteList = ["com.tencent.shadow.sample.host.lib"]
}
}
}
Expand All @@ -52,15 +53,16 @@ shadow {
partKey = 'sample-plugin-app'
buildTask = ':sample-plugin-app:assembleRelease'
apkName = 'sample-plugin-app-release.apk'
apkPath = 'projects/sample/sample-plugin/sample-plugin-app/build/outputs/apk/release/sample-plugin-app-release.apk'
apkPath = 'projects/sample/source/sample-plugin/sample-plugin-app/build/outputs/apk/release/sample-plugin-app-release.apk'
hostWhiteList = ["com.tencent.shadow.sample.host.lib"]
}
}
}
}

loaderApkProjectPath = 'projects/sample/sample-plugin/sample-loader'
loaderApkProjectPath = 'projects/sample/source/sample-plugin/sample-loader'

runtimeApkProjectPath = 'projects/sample/sample-plugin/sample-runtime'
runtimeApkProjectPath = 'projects/sample/source/sample-plugin/sample-runtime'

version = 4
compactVersion = [1, 2, 3]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 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
22 changes: 12 additions & 10 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def includeTest() {
def includeSample() {
include 'sample-constant',
'sample-host',
'sample-host-lib',
'sample-manager',
'sample-loader',
'sample-runtime',
Expand All @@ -55,14 +56,15 @@ def includeSample() {
'sample-app-lib',
'sample-normal-app',
'sample-plugin-app'
project(':sample-constant').projectDir = file('projects/sample/sample-constant')
project(':sample-host').projectDir = file('projects/sample/sample-host')
project(':sample-manager').projectDir = file('projects/sample/sample-manager')
project(':sample-loader').projectDir = file('projects/sample/sample-plugin/sample-loader')
project(':sample-runtime').projectDir = file('projects/sample/sample-plugin/sample-runtime')
project(':pinnedheaderexpandablelistview').projectDir = file('projects/sample/sample-plugin/third-party/pinnedheaderexpandablelistview')
project(':slidingmenu').projectDir = file('projects/sample/sample-plugin/third-party/slidingmenu')
project(':sample-app-lib').projectDir = file('projects/sample/sample-plugin/sample-app-lib')
project(':sample-normal-app').projectDir = file('projects/sample/sample-plugin/sample-normal-app')
project(':sample-plugin-app').projectDir = file('projects/sample/sample-plugin/sample-plugin-app')
project(':sample-constant').projectDir = file('projects/sample/source/sample-constant')
project(':sample-host').projectDir = file('projects/sample/source/sample-host')
project(':sample-host-lib').projectDir = file('projects/sample/source/sample-host-lib')
project(':sample-manager').projectDir = file('projects/sample/source/sample-manager')
project(':sample-loader').projectDir = file('projects/sample/source/sample-plugin/sample-loader')
project(':sample-runtime').projectDir = file('projects/sample/source/sample-plugin/sample-runtime')
project(':pinnedheaderexpandablelistview').projectDir = file('projects/sample/source/sample-plugin/third-party/pinnedheaderexpandablelistview')
project(':slidingmenu').projectDir = file('projects/sample/source/sample-plugin/third-party/slidingmenu')
project(':sample-app-lib').projectDir = file('projects/sample/source/sample-plugin/sample-app-lib')
project(':sample-normal-app').projectDir = file('projects/sample/source/sample-plugin/sample-normal-app')
project(':sample-plugin-app').projectDir = file('projects/sample/source/sample-plugin/sample-plugin-app')
}