├── .gitignore ├── AndroidStub ├── README.md ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── aidl │ └── android │ │ ├── app │ │ ├── IActivityManager.aidl │ │ ├── IApplicationThread.aidl │ │ ├── INotificationManager.aidl │ │ └── IServiceConnection.aidl │ │ └── content │ │ ├── IIntentReceiver.aidl │ │ └── IIntentSender.aidl │ └── java │ ├── android │ ├── app │ │ ├── ActivityManagerNative.java │ │ ├── ActivityThread.java │ │ ├── ApplicationThreadNative.java │ │ ├── Instrumentation.java │ │ ├── LoadedApk.java │ │ └── ResourcesManager.java │ ├── content │ │ ├── ContentResolver.java │ │ ├── IContentProvider.java │ │ ├── pm │ │ │ ├── ManifestDigest.java │ │ │ ├── PackageParser.java │ │ │ ├── PackageUserState.java │ │ │ └── VerifierInfo.java │ │ └── res │ │ │ ├── CompatibilityInfo.java │ │ │ ├── Resources.java │ │ │ ├── ResourcesImpl.java │ │ │ └── ResourcesKey.java │ ├── databinding │ │ ├── DataBinderMapper.java │ │ └── DataBindingComponent.java │ ├── os │ │ ├── ServiceManager.java │ │ └── SystemProperties.java │ └── util │ │ └── Singleton.java │ └── com │ └── android │ └── internal │ └── R.java ├── CONTRIBUTING.md ├── CoreLibrary ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro ├── src │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── didi │ │ │ └── virtualapk │ │ │ └── core │ │ │ └── ApplicationTest.java │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ ├── android │ │ │ │ ├── content │ │ │ │ │ └── ContentResolverWrapper.java │ │ │ │ └── databinding │ │ │ │ │ └── DataBinderMapperProxy.java │ │ │ └── com │ │ │ │ └── didi │ │ │ │ └── virtualapk │ │ │ │ ├── PluginManager.java │ │ │ │ ├── delegate │ │ │ │ ├── ActivityManagerProxy.java │ │ │ │ ├── IContentProviderProxy.java │ │ │ │ ├── LocalService.java │ │ │ │ ├── RemoteContentProvider.java │ │ │ │ ├── RemoteService.java │ │ │ │ └── StubActivity.java │ │ │ │ ├── internal │ │ │ │ ├── ActivityLifecycleCallbacksProxy.java │ │ │ │ ├── ComponentsHandler.java │ │ │ │ ├── Constants.java │ │ │ │ ├── LoadedPlugin.java │ │ │ │ ├── PluginContentResolver.java │ │ │ │ ├── PluginContext.java │ │ │ │ ├── ResourcesManager.java │ │ │ │ ├── StubActivityInfo.java │ │ │ │ ├── VAInstrumentation.java │ │ │ │ └── utils │ │ │ │ │ ├── DexUtil.java │ │ │ │ │ ├── PackageParserCompat.java │ │ │ │ │ ├── PluginUtil.java │ │ │ │ │ └── Settings.java │ │ │ │ └── utils │ │ │ │ ├── Reflector.java │ │ │ │ ├── RunUtil.java │ │ │ │ └── ZipVerifyUtil.java │ │ └── res │ │ │ └── values │ │ │ └── strings.xml │ └── test │ │ └── java │ │ └── com │ │ └── didi │ │ └── virtualapk │ │ └── core │ │ └── ExampleUnitTest.java └── upload.gradle ├── LICENSE ├── PluginDemo ├── app │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── aidl │ │ └── com │ │ │ └── didi │ │ │ └── virtualapk │ │ │ └── demo │ │ │ ├── aidl │ │ │ ├── Book.aidl │ │ │ ├── IBookManager.aidl │ │ │ └── IOnNewBookArrivedListener.aidl │ │ │ ├── binderpool │ │ │ ├── IBinderPool.aidl │ │ │ ├── ICompute.aidl │ │ │ └── ISecurityCenter.aidl │ │ │ └── manualbinder │ │ │ └── Book.aidl │ │ ├── java │ │ └── com │ │ │ └── didi │ │ │ └── virtualapk │ │ │ └── demo │ │ │ ├── MainActivity.java │ │ │ ├── MyApplication.java │ │ │ ├── SecondActivity.java │ │ │ ├── ThirdActivity.java │ │ │ ├── aidl │ │ │ ├── Book.java │ │ │ ├── BookManagerActivity.java │ │ │ └── BookManagerService.java │ │ │ ├── binderpool │ │ │ ├── BinderPool.java │ │ │ ├── BinderPoolActivity.java │ │ │ ├── BinderPoolService.java │ │ │ ├── ComputeImpl.java │ │ │ └── SecurityCenterImpl.java │ │ │ ├── manager │ │ │ ├── BookManager.java │ │ │ └── UserManager.java │ │ │ ├── manualbinder │ │ │ ├── Book.java │ │ │ ├── BookManagerImpl.java │ │ │ └── IBookManager.java │ │ │ ├── messenger │ │ │ ├── MessengerActivity.java │ │ │ └── MessengerService.java │ │ │ ├── model │ │ │ └── User.java │ │ │ ├── provider │ │ │ ├── BookProvider.java │ │ │ ├── DbOpenHelper.java │ │ │ └── ProviderActivity.java │ │ │ ├── socket │ │ │ ├── TCPClientActivity.java │ │ │ └── TCPServerService.java │ │ │ └── utils │ │ │ ├── MyConstants.java │ │ │ └── MyUtils.java │ │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── drawable │ │ └── edit.xml │ │ ├── layout │ │ ├── activity_binder_pool.xml │ │ ├── activity_book_manager.xml │ │ ├── activity_main.xml │ │ ├── activity_messenger.xml │ │ ├── activity_provider.xml │ │ ├── activity_second.xml │ │ ├── activity_tcpclient.xml │ │ └── activity_third.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── make.sh └── settings.gradle ├── README.md ├── RELEASE-NOTES.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── didi │ │ └── virtualapk │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── didi │ │ │ └── virtualapk │ │ │ ├── MainActivity.java │ │ │ └── VAApplication.java │ ├── jniLibs │ │ └── armeabi │ │ │ └── libaa.so │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-en │ │ └── strings.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── didi │ └── virtualapk │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── imgs ├── demo-1.png ├── demo-2.png ├── demo-3.png ├── didi.png ├── uber-china.png ├── va-logo.png ├── va.png └── va1.png ├── keystore ├── test.cer └── test.keystore ├── settings.gradle └── virtualapk-gradle-plugin ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── src └── main │ ├── groovy │ └── com.didi.virtualapk │ │ ├── BasePlugin.groovy │ │ ├── Constants.groovy │ │ ├── VAExtention.groovy │ │ ├── VAHostPlugin.groovy │ │ ├── VAPlugin.groovy │ │ ├── aapt │ │ ├── AXmlEditor.groovy │ │ ├── Aapt.groovy │ │ ├── ArscEditor.groovy │ │ ├── AssetEditor.groovy │ │ ├── CppHexEditor.groovy │ │ ├── ResAttr.groovy │ │ ├── ResStringFlag.groovy │ │ ├── ResStringPoolSpan.groovy │ │ ├── ResTableEntry.groovy │ │ ├── ResTableType.groovy │ │ ├── ResType.groovy │ │ ├── ResValueDataType.groovy │ │ ├── SymbolParser.groovy │ │ └── packageinfo │ │ ├── collector │ │ ├── HostClassAndResCollector.groovy │ │ ├── HostJniLibsCollector.groovy │ │ ├── ResourceCollector.groovy │ │ ├── dependence │ │ │ ├── AarDependenceInfo.groovy │ │ │ ├── DependenceInfo.groovy │ │ │ └── JarDependenceInfo.groovy │ │ └── res │ │ │ ├── ResourceEntry.groovy │ │ │ └── StyleableEntry.groovy │ │ ├── hooker │ │ ├── DxTaskHooker.groovy │ │ ├── GradleTaskHooker.groovy │ │ ├── MergeAssetsHooker.groovy │ │ ├── MergeJniLibsHooker.groovy │ │ ├── MergeManifestsHooker.groovy │ │ ├── PrepareDependenciesHooker.groovy │ │ ├── ProcessResourcesHooker.groovy │ │ ├── ProguardHooker.groovy │ │ ├── ShrinkResourcesHooker.groovy │ │ └── TaskHookerManager.groovy │ │ ├── tasks │ │ └── AssemblePlugin.groovy │ │ ├── transform │ │ ├── StripClassAndResTransform.groovy │ │ └── TransformWrapper.groovy │ │ └── utils │ │ ├── CheckList.groovy │ │ ├── FileBinaryCategory.groovy │ │ ├── FileUtil.groovy │ │ ├── PackagingUtils.java │ │ ├── Reflect.java │ │ └── ZipUtil.groovy │ ├── java │ └── com │ │ └── didi │ │ └── virtualapk │ │ ├── databinding │ │ └── annotationprocessor │ │ │ └── ProcessDataBinding.java │ │ └── utils │ │ └── Log.java │ └── resources │ └── META-INF │ ├── gradle-plugins │ ├── com.didi.virtualapk.host.properties │ └── com.didi.virtualapk.plugin.properties │ └── services │ └── javax.annotation.processing.Processor └── upload.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by MacOSX 2 | .DS_Store 3 | 4 | # Generated by VIM 5 | .*.swp 6 | 7 | # Generated by IntelliJ 8 | .idea/ 9 | *.iml 10 | /*/*.iml 11 | /*/*/*.iml 12 | 13 | # PluginDemo 14 | PluginDemo/.idea/ 15 | PluginDemo/.gradle/ 16 | PluginDemo/build/ 17 | PluginDemo/*.iml 18 | PluginDemo/local.properties 19 | PluginDemo/host/ 20 | 21 | # Generated by Gradle 22 | .gradle 23 | build/ 24 | 25 | # Generated by Eclipse 26 | .metadata 27 | .settings 28 | .project 29 | .classpath 30 | 31 | # Files generated by Maven 32 | target/ 33 | pom.xml.tag 34 | pom.xml.releaseBackup 35 | pom.xml.versionsBackup 36 | pom.xml.next 37 | release.properties 38 | dependency-reduced-pom.xml 39 | buildNumber.properties 40 | 41 | local.properties 42 | buildSrc 43 | -------------------------------------------------------------------------------- /AndroidStub/README.md: -------------------------------------------------------------------------------- 1 | # Android Framework Stub 2 | 3 | 该库主要是针对在 app 中无法直接调用 Android Framework 中很多隐藏的 API 而创造的一系列 stub 类用来欺骗编译器,从而避免了使用反射去调用造成性能损失 4 | -------------------------------------------------------------------------------- /AndroidStub/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.didichuxing.foundation' 2 | version = '0.0.5' 3 | 4 | apply plugin: 'com.android.library' 5 | 6 | android { 7 | compileSdkVersion VERSION_COMPILE_SDK 8 | buildToolsVersion VERSION_BUILD_TOOLS 9 | 10 | defaultConfig { 11 | minSdkVersion VERSION_MIN_SDK 12 | targetSdkVersion VERSION_TARGET_SDK 13 | versionCode 1 14 | versionName "1.0" 15 | } 16 | compileOptions { 17 | sourceCompatibility SOURCE_COMPATIBILITY 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | lintOptions { 27 | abortOnError false 28 | } 29 | } 30 | 31 | android.libraryVariants.all { variant -> 32 | def jarTask = project.tasks.create("jar${variant.name.capitalize()}", Jar) 33 | jarTask.excludes = [ 34 | 'android/BuildConfig.class', 35 | 'android/R.class' 36 | ] 37 | jarTask.dependsOn variant.javaCompile 38 | jarTask.from variant.javaCompile.destinationDir 39 | artifacts.add('archives', jarTask) 40 | } 41 | 42 | apply plugin: 'maven' 43 | 44 | uploadArchives { 45 | repositories { 46 | mavenDeployer { 47 | pom.project { 48 | groupId project.group 49 | artifactId 'android-framework' 50 | version project.version 51 | description project.description ?: '' 52 | packaging 'jar' 53 | } 54 | repository(url: MAVEN_RELEASES_REPOSITORY_URL) { 55 | authentication(userName: MAVEN_USERNAME, password: MAVEN_PASSWORD) 56 | } 57 | snapshotRepository(url: MAVEN_SNAPSHOTS_REPOSITORY_URL) { 58 | authentication(userName: MAVEN_USERNAME, password: MAVEN_PASSWORD) 59 | } 60 | } 61 | } 62 | } 63 | 64 | dependencies { 65 | api 'com.android.support:support-annotations:22.2.0' 66 | api 'com.android.databinding:library:1.3.1' 67 | api 'com.android.databinding:baseLibrary:3.0.0' 68 | } -------------------------------------------------------------------------------- /AndroidStub/gradle.properties: -------------------------------------------------------------------------------- 1 | MAVEN_RELEASES_REPOSITORY_URL= 2 | MAVEN_SNAPSHOTS_REPOSITORY_URL= 3 | MAVEN_USERNAME=test 4 | MAVEN_PASSWORD=test 5 | -------------------------------------------------------------------------------- /AndroidStub/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/johnson/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /AndroidStub/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /AndroidStub/src/main/aidl/android/app/IActivityManager.aidl: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | import android.app.IApplicationThread; 4 | import android.app.IServiceConnection; 5 | import android.content.ComponentName; 6 | import android.content.Intent; 7 | import android.content.IIntentSender; 8 | import android.os.IBinder; 9 | import android.os.IInterface; 10 | 11 | /** 12 | * @author johnsonlee 13 | */ 14 | interface IActivityManager { 15 | 16 | ComponentName startService(in IApplicationThread caller, in Intent service, in String resolvedType, in String callingPackage, in int userId); 17 | 18 | int stopService(in IApplicationThread caller, in Intent service, in String resolvedType, in int userId); 19 | 20 | boolean stopServiceToken(in ComponentName className, in IBinder token, in int startId); 21 | 22 | void setServiceForeground(in ComponentName className, in IBinder token, in int id, in Notification notification, in boolean keepNotification); 23 | 24 | int bindService(in IApplicationThread caller, in IBinder token, in Intent service, in String resolvedType, in IServiceConnection connection, in int flags, in String callingPackage, in int userId); 25 | 26 | boolean unbindService(in IServiceConnection connection); 27 | 28 | void publishService(in IBinder token, in Intent intent, in IBinder service); 29 | 30 | void unbindFinished(in IBinder token, in Intent service, in boolean doRebind); 31 | 32 | IIntentSender getIntentSender(in int type, in String packageName, in IBinder token, in String resultWho, int requestCode, in Intent[] intents, in String[] resolvedTypes, in int flags, in Bundle options, in int userId); 33 | 34 | void cancelIntentSender(in IIntentSender sender); 35 | 36 | String getPackageForIntentSender(in IIntentSender sender); 37 | 38 | int getUidForIntentSender(in IIntentSender sender); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /AndroidStub/src/main/aidl/android/app/IApplicationThread.aidl: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | interface IApplicationThread { 4 | } 5 | -------------------------------------------------------------------------------- /AndroidStub/src/main/aidl/android/app/INotificationManager.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007, The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package android.app; 17 | import android.app.Notification; 18 | import android.content.ComponentName; 19 | import android.content.Intent; 20 | import android.net.Uri; 21 | import android.os.Bundle; 22 | 23 | interface INotificationManager 24 | { 25 | void cancelAllNotifications(String pkg, int userId); 26 | void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id, in Notification notification, inout int[] idReceived, int userId); 27 | void cancelNotificationWithTag(String pkg, String tag, int id, int userId); 28 | void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled); 29 | boolean areNotificationsEnabledForPackage(String pkg, int uid); 30 | boolean areNotificationsEnabled(String pkg); 31 | } 32 | -------------------------------------------------------------------------------- /AndroidStub/src/main/aidl/android/app/IServiceConnection.aidl: -------------------------------------------------------------------------------- 1 | /* //device/java/android/android/app/IServiceConnection.aidl 2 | ** 3 | ** Copyright 2007, The Android Open Source Project 4 | ** 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); 6 | ** you may not use this file except in compliance with the License. 7 | ** You may obtain a copy of the License at 8 | ** 9 | ** http://www.apache.org/licenses/LICENSE-2.0 10 | ** 11 | ** Unless required by applicable law or agreed to in writing, software 12 | ** distributed under the License is distributed on an "AS IS" BASIS, 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | ** See the License for the specific language governing permissions and 15 | ** limitations under the License. 16 | */ 17 | 18 | package android.app; 19 | 20 | import android.content.ComponentName; 21 | 22 | /** @hide */ 23 | oneway interface IServiceConnection { 24 | // void connected(in ComponentName name, IBinder service); 25 | 26 | /** Added in Android O */ 27 | void connected(in ComponentName name, IBinder service, boolean dead); 28 | } 29 | -------------------------------------------------------------------------------- /AndroidStub/src/main/aidl/android/content/IIntentReceiver.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package android.content; 18 | 19 | import android.content.Intent; 20 | import android.os.Bundle; 21 | 22 | /** 23 | * System private API for dispatching intent broadcasts. This is given to the 24 | * activity manager as part of registering for an intent broadcasts, and is 25 | * called when it receives intents. 26 | */ 27 | oneway interface IIntentReceiver { 28 | void performReceive(in Intent intent, int resultCode, String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser); 29 | } 30 | -------------------------------------------------------------------------------- /AndroidStub/src/main/aidl/android/content/IIntentSender.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package android.content; 18 | 19 | import android.content.IIntentReceiver; 20 | import android.content.Intent; 21 | import android.os.Bundle; 22 | 23 | oneway interface IIntentSender { 24 | 25 | void send(int code, in Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, in Bundle options); 26 | 27 | } -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/app/ActivityManagerNative.java: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | import android.content.Intent; 4 | import android.os.Binder; 5 | import android.os.IBinder; 6 | 7 | /** 8 | * @author johnsonlee 9 | */ 10 | public abstract class ActivityManagerNative extends Binder implements IActivityManager { 11 | 12 | public static IActivityManager getDefault() { 13 | throw new RuntimeException("Stub!"); 14 | } 15 | 16 | public static boolean isSystemReady() { 17 | throw new RuntimeException("Stub!"); 18 | } 19 | 20 | public static void broadcastStickyIntent(final Intent intent, final String permission, final int userId) { 21 | throw new RuntimeException("Stub!"); 22 | } 23 | 24 | static public IActivityManager asInterface(IBinder obj) { 25 | throw new RuntimeException("Stub!"); 26 | } 27 | 28 | public ActivityManagerNative() { 29 | throw new RuntimeException("Stub!"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/app/ActivityThread.java: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | import android.content.Intent; 4 | import android.content.pm.ActivityInfo; 5 | import android.os.Handler; 6 | import android.os.IBinder; 7 | import android.os.Looper; 8 | 9 | /** 10 | * @author johnsonlee 11 | */ 12 | public final class ActivityThread { 13 | 14 | public static ActivityThread currentActivityThread() { 15 | throw new RuntimeException("Stub!"); 16 | } 17 | 18 | public static boolean isSystem() { 19 | throw new RuntimeException("Stub!"); 20 | } 21 | 22 | public static String currentOpPackageName() { 23 | throw new RuntimeException("Stub!"); 24 | } 25 | 26 | public static String currentPackageName() { 27 | throw new RuntimeException("Stub!"); 28 | } 29 | 30 | public static String currentProcessName() { 31 | throw new RuntimeException("Stub!"); 32 | } 33 | 34 | public static Application currentApplication() { 35 | throw new RuntimeException("Stub!"); 36 | } 37 | 38 | public ApplicationThread getApplicationThread() { 39 | throw new RuntimeException("Stub!"); 40 | } 41 | 42 | public Instrumentation getInstrumentation() { 43 | throw new RuntimeException("Stub!"); 44 | } 45 | 46 | public Looper getLooper() { 47 | throw new RuntimeException("Stub!"); 48 | } 49 | 50 | public Application getApplication() { 51 | throw new RuntimeException("Stub!"); 52 | } 53 | 54 | public String getProcessName() { 55 | throw new RuntimeException("Stub!"); 56 | } 57 | 58 | public final ActivityInfo resolveActivityInfo(final Intent intent) { 59 | throw new RuntimeException("Stub!"); 60 | } 61 | 62 | public final Activity getActivity(final IBinder token) { 63 | throw new RuntimeException("Stub!"); 64 | } 65 | 66 | final Handler getHandler() { 67 | throw new RuntimeException("Stub!"); 68 | } 69 | 70 | private class ApplicationThread extends ApplicationThreadNative { 71 | 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/app/ApplicationThreadNative.java: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | import android.os.Binder; 4 | import android.os.IBinder; 5 | 6 | /** 7 | * @author johnsonlee 8 | */ 9 | public abstract class ApplicationThreadNative extends Binder implements IApplicationThread { 10 | 11 | @Override 12 | public IBinder asBinder() { 13 | throw new RuntimeException("Stub!"); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/app/Instrumentation.java: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.os.IBinder; 8 | import android.os.PersistableBundle; 9 | 10 | /** 11 | * Created by qiaopu on 2018/5/7. 12 | */ 13 | public class Instrumentation { 14 | 15 | public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { 16 | throw new RuntimeException("Stub!"); 17 | } 18 | 19 | public void callApplicationOnCreate(Application app) { 20 | throw new RuntimeException("Stub!"); 21 | } 22 | 23 | public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { 24 | throw new RuntimeException("Stub!"); 25 | } 26 | 27 | public void callActivityOnCreate(Activity activity, Bundle icicle) { 28 | throw new RuntimeException("Stub!"); 29 | } 30 | 31 | public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) { 32 | throw new RuntimeException("Stub!"); 33 | } 34 | 35 | public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode) { 36 | throw new RuntimeException("Stub!"); 37 | } 38 | 39 | public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { 40 | throw new RuntimeException("Stub!"); 41 | } 42 | 43 | public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Fragment target, Intent intent, int requestCode, Bundle options) { 44 | throw new RuntimeException("Stub!"); 45 | } 46 | 47 | public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) { 48 | throw new RuntimeException("Stub!"); 49 | } 50 | 51 | public Context getContext() { 52 | throw new RuntimeException("Stub!"); 53 | } 54 | 55 | public Context getTargetContext() { 56 | throw new RuntimeException("Stub!"); 57 | } 58 | 59 | public ComponentName getComponentName() { 60 | throw new RuntimeException("Stub!"); 61 | } 62 | 63 | public static final class ActivityResult { 64 | public ActivityResult(int resultCode, Intent resultData) { 65 | throw new RuntimeException("Stub!"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/app/LoadedApk.java: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.IIntentReceiver; 6 | import android.content.pm.ApplicationInfo; 7 | import android.content.res.AssetManager; 8 | import android.content.res.Resources; 9 | import android.os.Handler; 10 | 11 | import java.io.File; 12 | 13 | /** 14 | * Created by johnson on 24/8/16. 15 | */ 16 | public final class LoadedApk { 17 | 18 | public String getPackageName() { 19 | throw new RuntimeException("Stub!"); 20 | } 21 | 22 | public ApplicationInfo getApplicationInfo() { 23 | throw new RuntimeException("Stub!"); 24 | } 25 | 26 | public ClassLoader getClassLoader() { 27 | throw new RuntimeException("Stub!"); 28 | } 29 | 30 | public String getAppDir() { 31 | throw new RuntimeException("Stub!"); 32 | } 33 | 34 | public String getLibDir() { 35 | throw new RuntimeException("Stub!"); 36 | } 37 | 38 | public String getResDir() { 39 | throw new RuntimeException("Stub!"); 40 | } 41 | 42 | public String[] getSplitAppDirs() { 43 | throw new RuntimeException("Stub!"); 44 | } 45 | 46 | public String[] getSplitResDirs() { 47 | throw new RuntimeException("Stub!"); 48 | } 49 | 50 | public String[] getOverlayDirs() { 51 | throw new RuntimeException("Stub!"); 52 | } 53 | 54 | public String getDataDir() { 55 | throw new RuntimeException("Stub!"); 56 | } 57 | 58 | public File getDataDirFile() { 59 | throw new RuntimeException("Stub!"); 60 | } 61 | 62 | public AssetManager getAssets(final ActivityThread mainThread) { 63 | throw new RuntimeException("Stub!"); 64 | } 65 | 66 | public Resources getResources(final ActivityThread mainThread) { 67 | throw new RuntimeException("Stub!"); 68 | } 69 | 70 | public IIntentReceiver getReceiverDispatcher(final BroadcastReceiver r, final Context context, final Handler handler, final Instrumentation instrumentation, final boolean registered) { 71 | throw new RuntimeException("Stub!"); 72 | } 73 | 74 | public IIntentReceiver forgetReceiverDispatcher(final Context context, final BroadcastReceiver r) { 75 | throw new RuntimeException("Stub!"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/app/ResourcesManager.java: -------------------------------------------------------------------------------- 1 | package android.app; 2 | 3 | /** 4 | * Created by qiaopu on 2018/4/25. 5 | */ 6 | public class ResourcesManager { 7 | 8 | public static ResourcesManager getInstance() { 9 | throw new RuntimeException("Stub!"); 10 | } 11 | 12 | public void appendLibAssetForMainAssetPath(String assetPath, String libAsset) { 13 | throw new RuntimeException("Stub!"); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/ContentResolver.java: -------------------------------------------------------------------------------- 1 | package android.content; 2 | 3 | import android.net.Uri; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | 8 | /** 9 | * Created by qiaopu on 2018/5/7. 10 | */ 11 | public abstract class ContentResolver { 12 | 13 | public ContentResolver(Context context) { 14 | throw new RuntimeException("Stub!"); 15 | } 16 | 17 | public final @Nullable 18 | Bundle call(@NonNull Uri uri, @NonNull String method, 19 | @Nullable String arg, @Nullable Bundle extras) { 20 | throw new RuntimeException("Stub!"); 21 | } 22 | 23 | protected abstract IContentProvider acquireProvider(Context c, String name); 24 | 25 | protected IContentProvider acquireExistingProvider(Context c, String name) { 26 | throw new RuntimeException("Stub!"); 27 | } 28 | 29 | public abstract boolean releaseProvider(IContentProvider icp); 30 | 31 | protected abstract IContentProvider acquireUnstableProvider(Context c, String name); 32 | 33 | public abstract boolean releaseUnstableProvider(IContentProvider icp); 34 | 35 | public abstract void unstableProviderDied(IContentProvider icp); 36 | 37 | public void appNotRespondingViaProvider(IContentProvider icp) { 38 | throw new RuntimeException("Stub!"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/IContentProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package android.content; 18 | 19 | import android.os.IInterface; 20 | 21 | /** 22 | * The ipc interface to talk to a content provider. 23 | * @hide 24 | */ 25 | public interface IContentProvider extends IInterface { 26 | } 27 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/pm/ManifestDigest.java: -------------------------------------------------------------------------------- 1 | package android.content.pm; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import java.util.jar.Attributes; 7 | 8 | /** 9 | * @author johnsonlee 10 | */ 11 | public class ManifestDigest implements Parcelable { 12 | 13 | ManifestDigest(final byte[] digest) { 14 | throw new RuntimeException("Stub!"); 15 | } 16 | 17 | private ManifestDigest(final Parcel source) { 18 | throw new RuntimeException("Stub!"); 19 | } 20 | 21 | static ManifestDigest fromAttributes(final Attributes attributes) { 22 | throw new RuntimeException("Stub!"); 23 | } 24 | 25 | @Override 26 | public int describeContents() { 27 | throw new RuntimeException("Stub!"); 28 | } 29 | 30 | @Override 31 | public boolean equals(Object o) { 32 | throw new RuntimeException("Stub!"); 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | throw new RuntimeException("Stub!"); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | throw new RuntimeException("Stub!"); 43 | } 44 | 45 | @Override 46 | public void writeToParcel(final Parcel dest, final int flags) { 47 | throw new RuntimeException("Stub!"); 48 | } 49 | 50 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 51 | public ManifestDigest createFromParcel(Parcel source) { 52 | return new ManifestDigest(source); 53 | } 54 | 55 | public ManifestDigest[] newArray(int size) { 56 | return new ManifestDigest[size]; 57 | } 58 | }; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/pm/PackageUserState.java: -------------------------------------------------------------------------------- 1 | package android.content.pm; 2 | 3 | import android.util.ArraySet; 4 | 5 | /** 6 | * @author johnsonlee 7 | */ 8 | public class PackageUserState { 9 | 10 | public boolean stopped; 11 | public boolean notLaunched; 12 | public boolean installed; 13 | public boolean hidden; // Is the app restricted by owner / admin 14 | public int enabled; 15 | public boolean blockUninstall; 16 | 17 | public String lastDisableAppCaller; 18 | 19 | public ArraySet disabledComponents; 20 | public ArraySet enabledComponents; 21 | 22 | public int domainVerificationStatus; 23 | public int appLinkGeneration; 24 | 25 | public PackageUserState() { 26 | throw new RuntimeException("Stub!"); 27 | } 28 | 29 | public PackageUserState(final PackageUserState o) { 30 | throw new RuntimeException("Stub!"); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/pm/VerifierInfo.java: -------------------------------------------------------------------------------- 1 | package android.content.pm; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import java.security.PublicKey; 7 | 8 | /** 9 | * @author johnsonlee 10 | */ 11 | public class VerifierInfo implements Parcelable{ 12 | 13 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 14 | public VerifierInfo createFromParcel(final Parcel source) { 15 | return new VerifierInfo(source); 16 | } 17 | 18 | public VerifierInfo[] newArray(final int size) { 19 | return new VerifierInfo[size]; 20 | } 21 | }; 22 | 23 | public VerifierInfo(final String packageName, final PublicKey publicKey) { 24 | throw new RuntimeException("Stub!"); 25 | } 26 | 27 | private VerifierInfo(final Parcel source) { 28 | throw new RuntimeException("Stub!"); 29 | } 30 | 31 | @Override 32 | public int describeContents() { 33 | throw new RuntimeException("Stub!"); 34 | } 35 | 36 | @Override 37 | public void writeToParcel(final Parcel dest, final int flags) { 38 | throw new RuntimeException("Stub!"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/res/CompatibilityInfo.java: -------------------------------------------------------------------------------- 1 | package android.content.res; 2 | 3 | import android.content.pm.ApplicationInfo; 4 | import android.os.Parcel; 5 | import android.os.Parcelable; 6 | 7 | /** 8 | * Created by qiaopu on 2018/5/3. 9 | */ 10 | public class CompatibilityInfo implements Parcelable { 11 | 12 | public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, 13 | boolean forceCompat) { 14 | throw new RuntimeException("Stub!"); 15 | } 16 | 17 | @Override 18 | public int describeContents() { 19 | throw new RuntimeException("Stub!"); 20 | } 21 | 22 | @Override 23 | public void writeToParcel(Parcel dest, int flags) { 24 | throw new RuntimeException("Stub!"); 25 | } 26 | 27 | public static final Parcelable.Creator CREATOR 28 | = new Parcelable.Creator() { 29 | @Override 30 | public CompatibilityInfo createFromParcel(Parcel source) { 31 | throw new RuntimeException("Stub!"); 32 | } 33 | 34 | @Override 35 | public CompatibilityInfo[] newArray(int size) { 36 | throw new RuntimeException("Stub!"); 37 | } 38 | }; 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/res/Resources.java: -------------------------------------------------------------------------------- 1 | package android.content.res; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.util.DisplayMetrics; 5 | 6 | /** 7 | * Created by qiaopu on 2018/5/18. 8 | */ 9 | public class Resources { 10 | 11 | public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) { 12 | throw new RuntimeException("Stub!"); 13 | } 14 | 15 | public final AssetManager getAssets() { 16 | throw new RuntimeException("Stub!"); 17 | } 18 | 19 | public int getColor(int id) throws NotFoundException { 20 | throw new RuntimeException("Stub!"); 21 | } 22 | 23 | public Configuration getConfiguration() { 24 | throw new RuntimeException("Stub!"); 25 | } 26 | 27 | public DisplayMetrics getDisplayMetrics() { 28 | throw new RuntimeException("Stub!"); 29 | } 30 | 31 | public Drawable getDrawable(int id) throws NotFoundException { 32 | throw new RuntimeException("Stub!"); 33 | } 34 | 35 | public String getString(int id) throws NotFoundException { 36 | throw new RuntimeException("Stub!"); 37 | } 38 | 39 | public CharSequence getText(int id) throws NotFoundException { 40 | throw new RuntimeException("Stub!"); 41 | } 42 | 43 | public XmlResourceParser getXml(int id) throws NotFoundException { 44 | throw new RuntimeException("Stub!"); 45 | } 46 | 47 | public ResourcesImpl getImpl() { 48 | throw new RuntimeException("Stub!"); 49 | } 50 | 51 | public final Theme newTheme() { 52 | throw new RuntimeException("Stub!"); 53 | } 54 | 55 | public void updateConfiguration(Configuration config, DisplayMetrics metrics) { 56 | throw new RuntimeException("Stub!"); 57 | } 58 | 59 | public final class Theme { 60 | 61 | public void applyStyle(int resId, boolean force) { 62 | throw new RuntimeException("Stub!"); 63 | } 64 | 65 | public TypedArray obtainStyledAttributes(int[] attrs) { 66 | throw new RuntimeException("Stub!"); 67 | } 68 | 69 | public void setTo(Theme other) { 70 | throw new RuntimeException("Stub!"); 71 | } 72 | 73 | } 74 | 75 | public static class NotFoundException extends RuntimeException { 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/res/ResourcesImpl.java: -------------------------------------------------------------------------------- 1 | package android.content.res; 2 | 3 | /** 4 | * Created by qiaopu on 2018/5/18. 5 | */ 6 | public class ResourcesImpl { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/content/res/ResourcesKey.java: -------------------------------------------------------------------------------- 1 | package android.content.res; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | 6 | /** 7 | * Created by qiaopu on 2018/5/3. 8 | */ 9 | public final class ResourcesKey { 10 | @Nullable 11 | public final String mResDir; 12 | 13 | @Nullable 14 | public final String[] mSplitResDirs; 15 | 16 | @Nullable 17 | public final String[] mOverlayDirs; 18 | 19 | @Nullable 20 | public final String[] mLibDirs; 21 | 22 | public final int mDisplayId; 23 | 24 | @NonNull 25 | public final Configuration mOverrideConfiguration; 26 | 27 | @NonNull 28 | public final CompatibilityInfo mCompatInfo; 29 | 30 | public ResourcesKey(@Nullable String resDir, 31 | @Nullable String[] splitResDirs, 32 | @Nullable String[] overlayDirs, 33 | @Nullable String[] libDirs, 34 | int displayId, 35 | @Nullable Configuration overrideConfig, 36 | @Nullable CompatibilityInfo compatInfo) { 37 | throw new RuntimeException("Stub!"); 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/databinding/DataBinderMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package android.databinding; 17 | import android.view.View; 18 | /** 19 | * This class will be stripped from the jar and then replaced by the annotation processor 20 | * as part of the code generation step. This class's existence is just to ensure that 21 | * compile works and no reflection is needed to access the generated class. 22 | */ 23 | class DataBinderMapper { 24 | public ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View view, 25 | int layoutId) { 26 | return null; 27 | } 28 | ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View[] view, int layoutId) { 29 | return null; 30 | } 31 | public int getLayoutId(String tag) { return 0; } 32 | public String convertBrIdToString(int id) { 33 | return null; 34 | } 35 | public static int TARGET_MIN_SDK = 0; 36 | } -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/databinding/DataBindingComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package android.databinding; 17 | /** 18 | * This interface is generated during compilation to contain getters for all used instance 19 | * BindingAdapters. When a BindingAdapter is an instance method, an instance of the class 20 | * implementing the method must be instantiated. This interface will be generated with a getter 21 | * for each class with the name get* where * is simple class name of the declaring BindingAdapter 22 | * class/interface. Name collisions will be resolved by adding a numeric suffix to the getter. 23 | *

24 | * An instance of this class may also be passed into static or instance BindingAdapters as the 25 | * first parameter. 26 | *

27 | * If you are using Dagger 2, you should extend this interface and annotate the extended interface 28 | * as a Component. 29 | */ 30 | public interface DataBindingComponent { 31 | } -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/os/ServiceManager.java: -------------------------------------------------------------------------------- 1 | package android.os; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author johnsonlee 8 | */ 9 | public final class ServiceManager { 10 | 11 | private static HashMap sCache = new HashMap(); 12 | 13 | public static IBinder getService(final String name) { 14 | throw new RuntimeException("Stub!"); 15 | } 16 | 17 | public static void addService(final String name, final IBinder service) { 18 | throw new RuntimeException("Stub!"); 19 | } 20 | 21 | public static void addService(final String name, final IBinder service, final boolean allowIsolated) { 22 | throw new RuntimeException("Stub!"); 23 | } 24 | 25 | public static IBinder checkService(final String name) { 26 | throw new RuntimeException("Stub!"); 27 | } 28 | 29 | public static String[] listServices() throws RemoteException { 30 | throw new RuntimeException("Stub!"); 31 | } 32 | 33 | public static void initServiceCache(final Map cache) { 34 | throw new RuntimeException("Stub!"); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/os/SystemProperties.java: -------------------------------------------------------------------------------- 1 | package android.os; 2 | 3 | /** 4 | * @author johnsonlee 5 | */ 6 | public class SystemProperties { 7 | 8 | public static String get(final String key) { 9 | throw new RuntimeException("Stub!"); 10 | } 11 | 12 | public static String get(final String key, final String def) { 13 | throw new RuntimeException("Stub!"); 14 | } 15 | 16 | public static int getInt(final String key, final int def) { 17 | throw new RuntimeException("Stub!"); 18 | } 19 | 20 | public static long getLong(final String key, final long def) { 21 | throw new RuntimeException("Stub!"); 22 | } 23 | 24 | public static boolean getBoolean(final String key, final boolean def) { 25 | throw new RuntimeException("Stub!"); 26 | } 27 | 28 | public static void set(final String key, final String val) { 29 | throw new RuntimeException("Stub!"); 30 | } 31 | 32 | public static void addChangeCallback(final Runnable callback) { 33 | throw new RuntimeException("Stub!"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/android/util/Singleton.java: -------------------------------------------------------------------------------- 1 | package android.util; 2 | 3 | /** 4 | * @author johnsonlee 5 | */ 6 | public abstract class Singleton { 7 | public Singleton() { 8 | throw new RuntimeException("Stub!"); 9 | } 10 | 11 | protected abstract T create(); 12 | 13 | public T get() { 14 | throw new RuntimeException("Stub!"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AndroidStub/src/main/java/com/android/internal/R.java: -------------------------------------------------------------------------------- 1 | package com.android.internal; 2 | 3 | /** 4 | * @author johnsonlee 5 | */ 6 | public final class R { 7 | 8 | public static final class id { 9 | 10 | public static int action0 = 0; 11 | 12 | public static int actions = 0; 13 | 14 | public static int action_divider = 0; 15 | 16 | public static int big_picture = 0; 17 | 18 | public static int big_text = 0; 19 | 20 | public static int big_text2 = 0; 21 | 22 | public static int chronometer = 0; 23 | 24 | public static int icon = 0; 25 | 26 | public static int inbox_text0 = 0; 27 | 28 | public static int inbox_text1 = 0; 29 | 30 | public static int inbox_text2 = 0; 31 | 32 | public static int inbox_text3 = 0; 33 | 34 | public static int inbox_text4 = 0; 35 | 36 | public static int inbox_text5 = 0; 37 | 38 | public static int inbox_text6 = 0; 39 | 40 | public static int inbox_end_pad = 0; 41 | 42 | public static int info = 0; 43 | 44 | public static int line1 = 0; 45 | 46 | public static int line3 = 0; 47 | 48 | public static int overflow_divider = 0; 49 | 50 | public static int progress = 0; 51 | 52 | public static int title = 0; 53 | 54 | public static int text = 0; 55 | 56 | public static int text2 = 0; 57 | 58 | public static int time = 0; 59 | 60 | public static int right_icon = 0; 61 | 62 | public static int fillInIntent = 0; 63 | 64 | public static int status_bar_latest_event_content = 0; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guideline 2 | 3 | Thanks for considering to contribute this project. All issues and pull requests are highly appreciated. 4 | 5 | ## Pull Requests 6 | 7 | Before sending pull request to this project, please read and follow guidelines below. 8 | 9 | 1. Branch: We only accept pull request on `dev` branch. 10 | 2. Coding style: Follow the coding style used in VirtualAPK. 11 | 3. Commit message: Use English and be aware of your spell. 12 | 4. Test: Make sure to test your code. 13 | 14 | Add device mode, API version, related log, screenshots and other related information in your pull request if possible. 15 | 16 | NOTE: We assume all your contribution can be licensed under the [Apache License 2.0](https://github.com/didi/VirtualAPK/blob/master/LICENSE). 17 | 18 | ## Issues 19 | 20 | We love clearly described issues. :) 21 | 22 | Following information can help us to resolve the issue faster. 23 | 24 | * Device mode and hardware information. 25 | * API version. 26 | * Logs. 27 | * Screenshots. 28 | * Steps to reproduce the issue. 29 | -------------------------------------------------------------------------------- /CoreLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /CoreLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | import com.android.build.gradle.api.ApplicationVariant 2 | import com.android.build.gradle.api.LibraryVariant 3 | import com.google.common.base.Joiner 4 | 5 | apply plugin: 'com.android.library' 6 | 7 | android { 8 | compileSdkVersion VERSION_COMPILE_SDK 9 | buildToolsVersion VERSION_BUILD_TOOLS 10 | 11 | defaultConfig { 12 | minSdkVersion VERSION_MIN_SDK 13 | targetSdkVersion VERSION_TARGET_SDK 14 | versionCode 1 15 | versionName "1.0.0" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility SOURCE_COMPATIBILITY 25 | } 26 | lintOptions { 27 | abortOnError false 28 | } 29 | } 30 | 31 | repositories { 32 | mavenCentral() 33 | jcenter() 34 | } 35 | 36 | final String projectAndroidStub = ':AndroidStub' 37 | 38 | dependencies { 39 | compile fileTree(dir: 'libs', include: ['*.jar']) 40 | 41 | provided project(projectAndroidStub) 42 | 43 | testCompile 'junit:junit:4.12' 44 | } 45 | 46 | // Using Stub classes first when compiling. 47 | afterEvaluate { 48 | project.android.libraryVariants.each { LibraryVariant variant -> 49 | variant.javaCompile.doFirst { JavaCompile javaCompile -> 50 | String projectAndroidStubPath = project.project(projectAndroidStub).projectDir.canonicalPath 51 | // println "projectAndroidStubPath: ${projectAndroidStubPath}" 52 | File stubPath = javaCompile.classpath.find { 53 | it.canonicalPath.startsWith(projectAndroidStubPath) 54 | } 55 | if (stubPath == null) { 56 | throw new RuntimeException("reset bootclasspath error.") 57 | } 58 | javaCompile.options.setBootClasspath(Joiner.on(File.pathSeparator).join(stubPath, javaCompile.options.bootClasspath)) 59 | } 60 | } 61 | } 62 | 63 | apply from: 'upload.gradle' 64 | -------------------------------------------------------------------------------- /CoreLibrary/gradle.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CoreLibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/didi/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /CoreLibrary/src/androidTest/java/com/didi/virtualapk/core/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.core; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /CoreLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/android/content/ContentResolverWrapper.java: -------------------------------------------------------------------------------- 1 | package android.content; 2 | 3 | import android.annotation.TargetApi; 4 | import android.os.Build; 5 | 6 | /** 7 | * Wrapper of {@link ContentResolver} 8 | * Created by qiaopu on 2018/5/7. 9 | */ 10 | public abstract class ContentResolverWrapper extends ContentResolver { 11 | 12 | ContentResolver mBase; 13 | 14 | public ContentResolverWrapper(Context context) { 15 | super(context); 16 | mBase = context.getContentResolver(); 17 | } 18 | 19 | @Override 20 | protected IContentProvider acquireProvider(Context context, String auth) { 21 | return mBase.acquireProvider(context, auth); 22 | } 23 | 24 | @Override 25 | protected IContentProvider acquireExistingProvider(Context context, String auth) { 26 | return mBase.acquireExistingProvider(context, auth); 27 | } 28 | 29 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 30 | @Override 31 | protected IContentProvider acquireUnstableProvider(Context context, String auth) { 32 | return mBase.acquireUnstableProvider(context, auth); 33 | } 34 | 35 | @Override 36 | public boolean releaseProvider(IContentProvider icp) { 37 | return mBase.releaseProvider(icp); 38 | } 39 | 40 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 41 | @Override 42 | public boolean releaseUnstableProvider(IContentProvider icp) { 43 | return mBase.releaseUnstableProvider(icp); 44 | } 45 | 46 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 47 | @Override 48 | public void unstableProviderDied(IContentProvider icp) { 49 | mBase.unstableProviderDied(icp); 50 | } 51 | 52 | @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) 53 | @Override 54 | public void appNotRespondingViaProvider(IContentProvider icp) { 55 | // dark greylist in Android P 56 | // mBase.appNotRespondingViaProvider(icp); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/android/databinding/DataBinderMapperProxy.java: -------------------------------------------------------------------------------- 1 | package android.databinding; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.util.Log; 5 | import android.view.View; 6 | 7 | import com.didi.virtualapk.PluginManager; 8 | import com.didi.virtualapk.internal.Constants; 9 | import com.didi.virtualapk.internal.LoadedPlugin; 10 | 11 | import java.util.LinkedList; 12 | 13 | /** 14 | * Replace {@link DataBindingUtil#sMapper}. 15 | * Created by qiaopu on 2018/4/11. 16 | */ 17 | public class DataBinderMapperProxy extends DataBinderMapper implements PluginManager.Callback { 18 | public static final String TAG = Constants.TAG_PREFIX + "DataBinderMapperProxy"; 19 | 20 | private final LinkedList mMappers; 21 | private DataBinderMapper[] mCache; 22 | 23 | public DataBinderMapperProxy(@NonNull Object source) { 24 | mMappers = new LinkedList<>(); 25 | 26 | addMapper((DataBinderMapper) source); 27 | } 28 | 29 | @Override 30 | public ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View view, int layoutId) { 31 | ViewDataBinding viewDataBinding; 32 | 33 | for (DataBinderMapper mapper : getCache()) { 34 | viewDataBinding = mapper.getDataBinder(bindingComponent, view, layoutId); 35 | if (viewDataBinding != null) { 36 | // Log.d(TAG, "Found by mapper: " + mapper); 37 | return viewDataBinding; 38 | } 39 | } 40 | 41 | return null; 42 | } 43 | 44 | @Override 45 | ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View[] view, int layoutId) { 46 | ViewDataBinding viewDataBinding; 47 | 48 | for (DataBinderMapper mapper : getCache()) { 49 | viewDataBinding = mapper.getDataBinder(bindingComponent, view, layoutId); 50 | if (viewDataBinding != null) { 51 | // Log.d(TAG, "Found by mapper: " + mapper); 52 | return viewDataBinding; 53 | } 54 | } 55 | 56 | return null; 57 | } 58 | 59 | @Override 60 | public int getLayoutId(String tag) { 61 | int layoutId; 62 | 63 | for (DataBinderMapper mapper : getCache()) { 64 | layoutId = mapper.getLayoutId(tag); 65 | if (layoutId != 0) { 66 | // Log.d(TAG, "Found by mapper: " + mapper); 67 | return layoutId; 68 | } 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | @Override 75 | public String convertBrIdToString(int id) { 76 | String brId; 77 | 78 | for (DataBinderMapper mapper : getCache()) { 79 | brId = mapper.convertBrIdToString(id); 80 | if (brId != null) { 81 | // Log.d(TAG, "Found by mapper: " + mapper); 82 | return brId; 83 | } 84 | } 85 | 86 | return null; 87 | } 88 | 89 | @Override 90 | public void onAddedLoadedPlugin(LoadedPlugin plugin) { 91 | try { 92 | String clsName = "android.databinding.DataBinderMapper_" + plugin.getPackageName().replace('.', '_'); 93 | Log.d(TAG, "Try to find the class: " + clsName); 94 | Class cls = Class.forName(clsName, true, plugin.getClassLoader()); 95 | Object obj = cls.newInstance(); 96 | 97 | addMapper((DataBinderMapper) obj); 98 | 99 | } catch (Exception e) { 100 | Log.w(TAG, e); 101 | } 102 | } 103 | 104 | private void addMapper(DataBinderMapper mapper) { 105 | int size = 0; 106 | synchronized (mMappers) { 107 | mMappers.add(mapper); 108 | mCache = null; 109 | size = mMappers.size(); 110 | } 111 | 112 | Log.d(TAG, "Added mapper: " + mapper + ", size: " + size); 113 | } 114 | 115 | private DataBinderMapper[] getCache() { 116 | synchronized (mMappers) { 117 | if (mCache == null) { 118 | mCache = mMappers.toArray(new DataBinderMapper[mMappers.size()]); 119 | } 120 | return mCache; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/delegate/RemoteService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.didi.virtualapk.delegate; 18 | 19 | import android.content.ComponentName; 20 | import android.content.Intent; 21 | import android.os.IBinder; 22 | import android.util.Log; 23 | 24 | import com.didi.virtualapk.PluginManager; 25 | import com.didi.virtualapk.internal.Constants; 26 | import com.didi.virtualapk.internal.LoadedPlugin; 27 | 28 | import java.io.File; 29 | 30 | /** 31 | * @author johnsonlee 32 | */ 33 | public class RemoteService extends LocalService { 34 | 35 | private static final String TAG = Constants.TAG_PREFIX + "RemoteService"; 36 | 37 | @Override 38 | public IBinder onBind(Intent intent) { 39 | return null; 40 | } 41 | 42 | @Override 43 | public int onStartCommand(Intent intent, int flags, int startId) { 44 | if (intent == null) { 45 | return super.onStartCommand(intent, flags, startId); 46 | } 47 | 48 | Intent target = intent.getParcelableExtra(EXTRA_TARGET); 49 | if (target != null) { 50 | String pluginLocation = intent.getStringExtra(EXTRA_PLUGIN_LOCATION); 51 | ComponentName component = target.getComponent(); 52 | LoadedPlugin plugin = PluginManager.getInstance(this).getLoadedPlugin(component); 53 | if (plugin == null && pluginLocation != null) { 54 | try { 55 | PluginManager.getInstance(this).loadPlugin(new File(pluginLocation)); 56 | } catch (Exception e) { 57 | Log.w(TAG, e); 58 | } 59 | } 60 | } 61 | 62 | return super.onStartCommand(intent, flags, startId); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/delegate/StubActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.delegate; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.content.pm.ResolveInfo; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | 9 | /** 10 | * Created by qiaopu on 2018/6/13. 11 | */ 12 | public class StubActivity extends Activity { 13 | @Override 14 | protected void onCreate(@Nullable Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | 17 | // Go to the main activity 18 | Intent mainIntent = getPackageManager().getLaunchIntentForPackage(getPackageName()); 19 | 20 | if (mainIntent == null) { 21 | mainIntent = new Intent(Intent.ACTION_MAIN); 22 | mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 23 | mainIntent.setPackage(getPackageName()); 24 | 25 | ResolveInfo resolveInfo = getPackageManager().resolveActivity(mainIntent, 0); 26 | 27 | if (resolveInfo != null) { 28 | mainIntent.setClassName(this, resolveInfo.activityInfo.name); 29 | } 30 | } 31 | 32 | startActivity(mainIntent); 33 | 34 | finish(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/internal/ActivityLifecycleCallbacksProxy.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.internal; 2 | 3 | import android.app.Activity; 4 | import android.app.ActivityThread; 5 | import android.app.Application; 6 | import android.os.Bundle; 7 | 8 | import com.didi.virtualapk.utils.Reflector; 9 | 10 | import java.util.ArrayList; 11 | 12 | /** 13 | * Created by qiaopu on 2017/8/9. 14 | */ 15 | class ActivityLifecycleCallbacksProxy implements Application.ActivityLifecycleCallbacks { 16 | 17 | final ArrayList mActivityLifecycleCallbacks = 18 | Reflector.QuietReflector.with(ActivityThread.currentApplication()).field("mActivityLifecycleCallbacks").get(); 19 | 20 | Object[] collectActivityLifecycleCallbacks() { 21 | if (mActivityLifecycleCallbacks == null) { 22 | return null; 23 | } 24 | Object[] callbacks = null; 25 | synchronized (mActivityLifecycleCallbacks) { 26 | if (mActivityLifecycleCallbacks.size() > 0) { 27 | callbacks = mActivityLifecycleCallbacks.toArray(); 28 | } 29 | } 30 | return callbacks; 31 | } 32 | 33 | @Override 34 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 35 | Object[] callbacks = collectActivityLifecycleCallbacks(); 36 | if (callbacks != null) { 37 | for (int i = 0; i < callbacks.length; i++) { 38 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(activity, 39 | savedInstanceState); 40 | } 41 | } 42 | } 43 | 44 | @Override 45 | public void onActivityStarted(Activity activity) { 46 | Object[] callbacks = collectActivityLifecycleCallbacks(); 47 | if (callbacks != null) { 48 | for (int i = 0; i < callbacks.length; i++) { 49 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(activity); 50 | } 51 | } 52 | } 53 | 54 | @Override 55 | public void onActivityResumed(Activity activity) { 56 | Object[] callbacks = collectActivityLifecycleCallbacks(); 57 | if (callbacks != null) { 58 | for (int i = 0; i < callbacks.length; i++) { 59 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityResumed(activity); 60 | } 61 | } 62 | } 63 | 64 | @Override 65 | public void onActivityPaused(Activity activity) { 66 | Object[] callbacks = collectActivityLifecycleCallbacks(); 67 | if (callbacks != null) { 68 | for (int i = 0; i < callbacks.length; i++) { 69 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPaused(activity); 70 | } 71 | } 72 | } 73 | 74 | @Override 75 | public void onActivityStopped(Activity activity) { 76 | Object[] callbacks = collectActivityLifecycleCallbacks(); 77 | if (callbacks != null) { 78 | for (int i = 0; i < callbacks.length; i++) { 79 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStopped(activity); 80 | } 81 | } 82 | } 83 | 84 | @Override 85 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 86 | Object[] callbacks = collectActivityLifecycleCallbacks(); 87 | if (callbacks != null) { 88 | for (int i = 0; i < callbacks.length; i++) { 89 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivitySaveInstanceState(activity, 90 | outState); 91 | } 92 | } 93 | } 94 | 95 | @Override 96 | public void onActivityDestroyed(Activity activity) { 97 | Object[] callbacks = collectActivityLifecycleCallbacks(); 98 | if (callbacks != null) { 99 | for (int i = 0; i < callbacks.length; i++) { 100 | ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityDestroyed(activity); 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/internal/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.didi.virtualapk.internal; 18 | 19 | /** 20 | * Created by renyugang on 16/8/15. 21 | */ 22 | public class Constants { 23 | public static final String KEY_IS_PLUGIN = "isPlugin"; 24 | public static final String KEY_TARGET_PACKAGE = "target.package"; 25 | public static final String KEY_TARGET_ACTIVITY = "target.activity"; 26 | 27 | public static final String OPTIMIZE_DIR = "dex"; 28 | public static final String NATIVE_DIR = "valibs"; 29 | 30 | public static final boolean COMBINE_RESOURCES = true; 31 | public static final boolean COMBINE_CLASSLOADER = true; 32 | public static final boolean DEBUG = true; 33 | 34 | public static final String TAG = "VA"; 35 | public static final String TAG_PREFIX = TAG + "."; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/internal/PluginContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.didi.virtualapk.internal; 18 | 19 | import android.content.ContentResolver; 20 | import android.content.Context; 21 | import android.content.ContextWrapper; 22 | import android.content.Intent; 23 | import android.content.pm.ApplicationInfo; 24 | import android.content.pm.PackageManager; 25 | import android.content.res.AssetManager; 26 | import android.content.res.Resources; 27 | 28 | /** 29 | * Created by renyugang on 16/8/12. 30 | */ 31 | class PluginContext extends ContextWrapper { 32 | 33 | private final LoadedPlugin mPlugin; 34 | 35 | public PluginContext(LoadedPlugin plugin) { 36 | super(plugin.getPluginManager().getHostContext()); 37 | this.mPlugin = plugin; 38 | } 39 | 40 | public PluginContext(LoadedPlugin plugin, Context base) { 41 | super(base); 42 | this.mPlugin = plugin; 43 | } 44 | 45 | @Override 46 | public Context getApplicationContext() { 47 | return this.mPlugin.getApplication(); 48 | } 49 | 50 | // @Override 51 | // public ApplicationInfo getApplicationInfo() { 52 | // return this.mPlugin.getApplicationInfo(); 53 | // } 54 | 55 | private Context getHostContext() { 56 | return getBaseContext(); 57 | } 58 | 59 | @Override 60 | public ContentResolver getContentResolver() { 61 | return new PluginContentResolver(getHostContext()); 62 | } 63 | 64 | @Override 65 | public ClassLoader getClassLoader() { 66 | return this.mPlugin.getClassLoader(); 67 | } 68 | 69 | // @Override 70 | // public String getPackageName() { 71 | // return this.mPlugin.getPackageName(); 72 | // } 73 | 74 | // @Override 75 | // public String getPackageResourcePath() { 76 | // return this.mPlugin.getPackageResourcePath(); 77 | // } 78 | 79 | // @Override 80 | // public String getPackageCodePath() { 81 | // return this.mPlugin.getCodePath(); 82 | // } 83 | 84 | @Override 85 | public PackageManager getPackageManager() { 86 | return this.mPlugin.getPackageManager(); 87 | } 88 | 89 | @Override 90 | public Object getSystemService(String name) { 91 | // intercept CLIPBOARD_SERVICE,NOTIFICATION_SERVICE 92 | if (name.equals(Context.CLIPBOARD_SERVICE)) { 93 | return getHostContext().getSystemService(name); 94 | } else if (name.equals(Context.NOTIFICATION_SERVICE)) { 95 | return getHostContext().getSystemService(name); 96 | } 97 | 98 | return super.getSystemService(name); 99 | } 100 | 101 | @Override 102 | public Resources getResources() { 103 | return this.mPlugin.getResources(); 104 | } 105 | 106 | @Override 107 | public AssetManager getAssets() { 108 | return this.mPlugin.getAssets(); 109 | } 110 | 111 | @Override 112 | public Resources.Theme getTheme() { 113 | return this.mPlugin.getTheme(); 114 | } 115 | 116 | @Override 117 | public void startActivity(Intent intent) { 118 | ComponentsHandler componentsHandler = mPlugin.getPluginManager().getComponentsHandler(); 119 | componentsHandler.transformIntentToExplicitAsNeeded(intent); 120 | super.startActivity(intent); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/internal/utils/PackageParserCompat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.didi.virtualapk.internal.utils; 18 | 19 | import android.content.Context; 20 | import android.content.pm.PackageParser; 21 | import android.os.Build; 22 | 23 | import com.didi.virtualapk.utils.Reflector; 24 | 25 | import java.io.File; 26 | 27 | /** 28 | * @author johnsonlee 29 | */ 30 | public final class PackageParserCompat { 31 | 32 | public static final PackageParser.Package parsePackage(final Context context, final File apk, final int flags) { 33 | try { 34 | if (Build.VERSION.SDK_INT >= 28 35 | || (Build.VERSION.SDK_INT == 27 && Build.VERSION.PREVIEW_SDK_INT != 0)) { // Android P Preview 36 | return PackageParserPPreview.parsePackage(context, apk, flags); 37 | } else if (Build.VERSION.SDK_INT >= 24) { 38 | return PackageParserV24.parsePackage(context, apk, flags); 39 | } else if (Build.VERSION.SDK_INT >= 21) { 40 | return PackageParserLollipop.parsePackage(context, apk, flags); 41 | } else { 42 | return PackageParserLegacy.parsePackage(context, apk, flags); 43 | } 44 | 45 | } catch (Throwable e) { 46 | throw new RuntimeException("error", e); 47 | } 48 | } 49 | 50 | private static final class PackageParserPPreview { 51 | 52 | static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws Throwable { 53 | PackageParser parser = new PackageParser(); 54 | PackageParser.Package pkg = parser.parsePackage(apk, flags); 55 | Reflector.with(parser) 56 | .method("collectCertificates", PackageParser.Package.class, boolean.class) 57 | .call(pkg, false); 58 | return pkg; 59 | } 60 | } 61 | 62 | private static final class PackageParserV24 { 63 | 64 | static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws Throwable { 65 | PackageParser parser = new PackageParser(); 66 | PackageParser.Package pkg = parser.parsePackage(apk, flags); 67 | Reflector.with(parser) 68 | .method("collectCertificates", PackageParser.Package.class, int.class) 69 | .call(pkg, flags); 70 | return pkg; 71 | } 72 | } 73 | 74 | private static final class PackageParserLollipop { 75 | 76 | static final PackageParser.Package parsePackage(final Context context, final File apk, final int flags) throws Throwable { 77 | PackageParser parser = new PackageParser(); 78 | PackageParser.Package pkg = parser.parsePackage(apk, flags); 79 | parser.collectCertificates(pkg, flags); 80 | return pkg; 81 | } 82 | 83 | } 84 | 85 | private static final class PackageParserLegacy { 86 | 87 | static final PackageParser.Package parsePackage(Context context, File apk, int flags) throws Throwable { 88 | PackageParser parser = new PackageParser(apk.getAbsolutePath()); 89 | PackageParser.Package pkg = parser.parsePackage(apk, apk.getAbsolutePath(), context.getResources().getDisplayMetrics(), flags); 90 | Reflector.with(parser) 91 | .method("collectCertificates", PackageParser.Package.class, int.class) 92 | .call(pkg, flags); 93 | return pkg; 94 | } 95 | 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /CoreLibrary/src/main/java/com/didi/virtualapk/internal/utils/Settings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.didi.virtualapk.internal.utils; 18 | 19 | import android.content.Context; 20 | import android.content.SharedPreferences; 21 | 22 | /** 23 | * Created by renyugang on 16/8/23. 24 | */ 25 | public class Settings { 26 | 27 | private static final String FILE_NAME = "VirtualAPK_Settings"; 28 | 29 | public static void setSoVersion(Context context, String name, int version) { 30 | SharedPreferences preferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); 31 | SharedPreferences.Editor editor = preferences.edit(); 32 | editor.putInt(name, version); 33 | editor.commit(); 34 | } 35 | 36 | public static int getSoVersion(Context context, String name) { 37 | SharedPreferences preferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); 38 | return preferences.getInt(name, 0); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /CoreLibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CoreLibrary 3 | 4 | -------------------------------------------------------------------------------- /CoreLibrary/src/test/java/com/didi/virtualapk/core/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.core; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /CoreLibrary/upload.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.dcendents.android-maven' 2 | apply plugin: 'com.jfrog.bintray' 3 | 4 | def GROUP_ID = 'com.didi.virtualapk' 5 | def ARTIFACT_ID = 'core' 6 | 7 | 8 | def siteUrl = 'https://github.com/didi/VirtualAPK' // 项目的主页 9 | def gitUrl = 'https://github.com/didi/VirtualAPK' // Git仓库的url 10 | 11 | group = GROUP_ID 12 | archivesBaseName = 'core' 13 | 14 | version = "0.9.8" 15 | 16 | 17 | install { 18 | repositories.mavenInstaller { 19 | // This generates POM.xml with proper parameters 20 | pom { 21 | artifactId = ARTIFACT_ID 22 | 23 | project { 24 | packaging 'aar' 25 | // Add your description here 26 | name 'A powerful but lightweight plugin framework for Android' //项目描述 27 | url siteUrl 28 | // Set your license 29 | licenses { 30 | license { 31 | name 'Apache License 2.0' 32 | url 'http://www.apache.org/licenses/LICENSE-2.0' 33 | } 34 | } 35 | developers { 36 | developer { 37 | id 'singwhatiwanna' //填写的一些基本信息 38 | name 'DiDi' 39 | email 'singwhatiwanna@gmail.com' 40 | } 41 | } 42 | scm { 43 | connection gitUrl 44 | developerConnection gitUrl 45 | url siteUrl 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | task sourcesJar(type: Jar) { 53 | from android.sourceSets.main.java.srcDirs 54 | classifier = 'sources' 55 | } 56 | task javadoc(type: Javadoc) { 57 | source = android.sourceSets.main.java.srcDirs 58 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 59 | } 60 | task javadocJar(type: Jar, dependsOn: javadoc) { 61 | classifier = 'javadoc' 62 | from javadoc.destinationDir 63 | } 64 | artifacts { 65 | //archives javadocJar 66 | archives sourcesJar 67 | } 68 | 69 | Properties properties = new Properties() 70 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 71 | bintray { 72 | user = properties.getProperty("bintray.user") 73 | key = properties.getProperty("bintray.apikey") 74 | configurations = ['archives'] 75 | pkg { 76 | repo = "maven" 77 | name = "${GROUP_ID}:${ARTIFACT_ID}" //发布到JCenter上的项目名字 78 | websiteUrl = siteUrl 79 | vcsUrl = gitUrl 80 | licenses = ["Apache-2.0"] 81 | publish = true 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /PluginDemo/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion VERSION_COMPILE_SDK 5 | buildToolsVersion VERSION_BUILD_TOOLS 6 | 7 | defaultConfig { 8 | applicationId "com.didi.virtualapk.demo" 9 | minSdkVersion VERSION_MIN_SDK 10 | targetSdkVersion VERSION_TARGET_SDK 11 | versionName "1.0.0" 12 | versionCode 1 13 | } 14 | compileOptions { 15 | sourceCompatibility SOURCE_COMPATIBILITY 16 | } 17 | 18 | flavorDimensions "demo" 19 | productFlavors { 20 | beijing { 21 | dimension "demo" 22 | applicationId 'com.didi.virtualapk.demo' 23 | } 24 | shanghai { 25 | dimension "demo" 26 | applicationId 'com.didi.virtualapk.demo' 27 | } 28 | } 29 | 30 | signingConfigs { 31 | release { 32 | storeFile file("../../keystore/test.keystore") 33 | storePassword "test123456" 34 | keyAlias "test" 35 | keyPassword "test123456" 36 | } 37 | } 38 | 39 | buildTypes { 40 | debug { 41 | minifyEnabled false 42 | shrinkResources false 43 | } 44 | release { 45 | minifyEnabled true 46 | shrinkResources true 47 | signingConfig signingConfigs.release 48 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 49 | } 50 | } 51 | } 52 | 53 | dependencies { 54 | // the following aars are also compiled in host project, so they will be filterd when build plugin apk. 55 | // but, wo can still visit their Class and Resources. 56 | implementation 'com.android.support:appcompat-v7:23.4.0' 57 | // implementation 'com.didi.virtualapk:core:0.9.8' 58 | } 59 | 60 | apply plugin: 'com.didi.virtualapk.plugin' 61 | 62 | virtualApk { 63 | packageId = 0x6f // the package id of Resources. 64 | targetHost = '../../VirtualAPK/app' // the path of application module in host project. 65 | applyHostMapping = true //optional, default value: true. 66 | } -------------------------------------------------------------------------------- /PluginDemo/app/gradle.properties: -------------------------------------------------------------------------------- 1 | #android.enableD8=false 2 | android.useDexArchive=false -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/aidl/Book.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.aidl; 2 | 3 | parcelable Book; -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/aidl/IBookManager.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.aidl; 2 | 3 | import com.didi.virtualapk.demo.aidl.Book; 4 | import com.didi.virtualapk.demo.aidl.IOnNewBookArrivedListener; 5 | 6 | interface IBookManager { 7 | List getBookList(); 8 | void addBook(in Book book); 9 | void registerListener(IOnNewBookArrivedListener listener); 10 | void unregisterListener(IOnNewBookArrivedListener listener); 11 | } -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/aidl/IOnNewBookArrivedListener.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.aidl; 2 | 3 | import com.didi.virtualapk.demo.aidl.Book; 4 | 5 | interface IOnNewBookArrivedListener { 6 | void onNewBookArrived(in Book newBook); 7 | } 8 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/binderpool/IBinderPool.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | interface IBinderPool { 4 | 5 | /** 6 | * @param binderCode, the unique token of specific Binder
7 | * @return specific Binder who's token is binderCode. 8 | */ 9 | IBinder queryBinder(int binderCode); 10 | } -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/binderpool/ICompute.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | interface ICompute { 4 | int add(int a, int b); 5 | } -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/binderpool/ISecurityCenter.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | interface ISecurityCenter { 4 | String encrypt(String content); 5 | String decrypt(String password); 6 | } -------------------------------------------------------------------------------- /PluginDemo/app/src/main/aidl/com/didi/virtualapk/demo/manualbinder/Book.aidl: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.manualbinder; 2 | 3 | parcelable Book; -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectOutputStream; 7 | import java.io.Serializable; 8 | 9 | import com.didi.virtualapk.demo.R; 10 | import com.didi.virtualapk.demo.aidl.Book; 11 | import com.didi.virtualapk.demo.manager.UserManager; 12 | import com.didi.virtualapk.demo.model.User; 13 | import com.didi.virtualapk.demo.utils.MyConstants; 14 | import com.didi.virtualapk.demo.utils.MyUtils; 15 | 16 | import android.app.Activity; 17 | import android.content.Intent; 18 | import android.os.Bundle; 19 | import android.util.Log; 20 | import android.view.View; 21 | import android.view.View.OnClickListener; 22 | 23 | public class MainActivity extends Activity { 24 | 25 | private static final String TAG = "MainActivity"; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_main); 31 | UserManager.sUserId = 2; 32 | findViewById(R.id.button1).setOnClickListener(new OnClickListener() { 33 | 34 | @Override 35 | public void onClick(View v) { 36 | Intent intent = new Intent(); 37 | intent.setClass(MainActivity.this, SecondActivity.class); 38 | User user = new User(0, "jake", true); 39 | user.book = new Book(); 40 | intent.putExtra("extra_user", (Serializable) user); 41 | startActivity(intent); 42 | } 43 | }); 44 | } 45 | 46 | @Override 47 | protected void onResume() { 48 | Log.d(TAG, "UserManage.sUserId=" + UserManager.sUserId); 49 | persistToFile(); 50 | 51 | super.onResume(); 52 | } 53 | 54 | private void persistToFile() { 55 | new Thread(new Runnable() { 56 | 57 | @Override 58 | public void run() { 59 | User user = new User(1, "hello world", false); 60 | File dir = new File(MyConstants.CHAPTER_2_PATH); 61 | if (!dir.exists()) { 62 | dir.mkdirs(); 63 | } 64 | File cachedFile = new File(MyConstants.CACHE_FILE_PATH); 65 | ObjectOutputStream objectOutputStream = null; 66 | try { 67 | objectOutputStream = new ObjectOutputStream( 68 | new FileOutputStream(cachedFile)); 69 | objectOutputStream.writeObject(user); 70 | Log.d(TAG, "persist user:" + user); 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } finally { 74 | MyUtils.close(objectOutputStream); 75 | } 76 | } 77 | }).start(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo; 2 | 3 | import com.didi.virtualapk.demo.utils.MyUtils; 4 | 5 | import android.app.Application; 6 | import android.os.Process; 7 | import android.util.Log; 8 | 9 | public class MyApplication extends Application { 10 | 11 | private static final String TAG = "MyApplication"; 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | String processName = MyUtils.getProcessName(getApplicationContext(), 17 | Process.myPid()); 18 | Log.d(TAG, "application start, process name:" + processName); 19 | new Thread(new Runnable() { 20 | 21 | @Override 22 | public void run() { 23 | doWorkInBackground(); 24 | } 25 | }).start(); 26 | } 27 | 28 | private void doWorkInBackground() { 29 | // init binder pool 30 | //BinderPool.getInsance(getApplicationContext()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectInputStream; 7 | 8 | import com.didi.virtualapk.demo.R; 9 | import com.didi.virtualapk.demo.model.User; 10 | import com.didi.virtualapk.demo.utils.MyConstants; 11 | import com.didi.virtualapk.demo.utils.MyUtils; 12 | 13 | import android.app.Activity; 14 | import android.content.Intent; 15 | import android.os.Bundle; 16 | import android.util.Log; 17 | import android.view.View; 18 | import android.view.View.OnClickListener; 19 | 20 | public class SecondActivity extends Activity { 21 | private static final String TAG = "SecondActivity"; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_second); 27 | findViewById(R.id.button1).setOnClickListener(new OnClickListener() { 28 | 29 | @Override 30 | public void onClick(View v) { 31 | Intent intent = new Intent(); 32 | intent.setClass(SecondActivity.this, ThirdActivity.class); 33 | intent.putExtra("time", System.currentTimeMillis()); 34 | startActivity(intent); 35 | } 36 | }); 37 | Log.d(TAG, "onCreate"); 38 | } 39 | 40 | @Override 41 | protected void onNewIntent(Intent intent) { 42 | super.onNewIntent(intent); 43 | Log.d(TAG, "onNewIntent"); 44 | } 45 | 46 | @Override 47 | protected void onResume() { 48 | super.onResume(); 49 | //User user = (User) getIntent().getSerializableExtra("extra_user"); 50 | //Log.d(TAG, "user:" + user.toString()); 51 | // Log.d(TAG, "UserManage.sUserId=" + UserManager.sUserId); 52 | //recoverFromFile(); 53 | } 54 | 55 | private void recoverFromFile() { 56 | new Thread(new Runnable() { 57 | 58 | @Override 59 | public void run() { 60 | User user = null; 61 | File cachedFile = new File(MyConstants.CACHE_FILE_PATH); 62 | if (cachedFile.exists()) { 63 | ObjectInputStream objectInputStream = null; 64 | try { 65 | objectInputStream = new ObjectInputStream( 66 | new FileInputStream(cachedFile)); 67 | user = (User) objectInputStream.readObject(); 68 | Log.d(TAG, "recover user:" + user); 69 | } catch (IOException e) { 70 | e.printStackTrace(); 71 | } catch (ClassNotFoundException e) { 72 | e.printStackTrace(); 73 | } finally { 74 | MyUtils.close(objectInputStream); 75 | } 76 | } 77 | } 78 | }).start(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/ThirdActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo; 2 | 3 | import com.didi.virtualapk.demo.R; 4 | 5 | import android.app.Activity; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | import android.util.Log; 9 | import android.view.View; 10 | import android.view.View.OnClickListener; 11 | 12 | public class ThirdActivity extends Activity { 13 | private static final String TAG = "ThirdActivity"; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | // TODO Auto-generated method stub 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_third); 20 | findViewById(R.id.button1).setOnClickListener(new OnClickListener() { 21 | 22 | @Override 23 | public void onClick(View v) { 24 | Intent intent = new Intent(); 25 | intent.setClass(ThirdActivity.this, SecondActivity.class); 26 | intent.putExtra("time", System.currentTimeMillis()); 27 | startActivity(intent); 28 | } 29 | }); 30 | Log.d(TAG, "onCreate"); 31 | } 32 | 33 | @Override 34 | protected void onStart() { 35 | // TODO Auto-generated method stub 36 | super.onStart(); 37 | Log.d(TAG, "onStart"); 38 | } 39 | 40 | @Override 41 | protected void onResume() { 42 | // TODO Auto-generated method stub 43 | super.onResume(); 44 | Log.d(TAG, "onResume"); 45 | } 46 | 47 | @Override 48 | protected void onSaveInstanceState(Bundle outState) { 49 | super.onSaveInstanceState(outState); 50 | Log.d(TAG, "onSaveInstanceState"); 51 | } 52 | 53 | @Override 54 | protected void onRestoreInstanceState(Bundle savedInstanceState) { 55 | super.onRestoreInstanceState(savedInstanceState); 56 | Log.d(TAG, "onRestoreInstanceState"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/aidl/Book.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.aidl; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | public class Book implements Parcelable { 7 | 8 | public int bookId; 9 | public String bookName; 10 | 11 | public Book() { 12 | 13 | } 14 | 15 | public Book(int bookId, String bookName) { 16 | this.bookId = bookId; 17 | this.bookName = bookName; 18 | } 19 | 20 | public int describeContents() { 21 | return 0; 22 | } 23 | 24 | public void writeToParcel(Parcel out, int flags) { 25 | out.writeInt(bookId); 26 | out.writeString(bookName); 27 | } 28 | 29 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 30 | public Book createFromParcel(Parcel in) { 31 | return new Book(in); 32 | } 33 | 34 | public Book[] newArray(int size) { 35 | return new Book[size]; 36 | } 37 | }; 38 | 39 | private Book(Parcel in) { 40 | bookId = in.readInt(); 41 | bookName = in.readString(); 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return String.format("[bookId:%s, bookName:%s]", bookId, bookName); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/binderpool/BinderPoolActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | import com.didi.virtualapk.demo.R; 4 | import android.app.Activity; 5 | import android.os.Bundle; 6 | import android.os.IBinder; 7 | import android.os.RemoteException; 8 | import android.util.Log; 9 | 10 | public class BinderPoolActivity extends Activity { 11 | private static final String TAG = "BinderPoolActivity"; 12 | 13 | private ISecurityCenter mSecurityCenter; 14 | private ICompute mCompute; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_binder_pool); 20 | new Thread(new Runnable() { 21 | 22 | @Override 23 | public void run() { 24 | doWork(); 25 | } 26 | }).start(); 27 | } 28 | 29 | private void doWork() { 30 | BinderPool binderPool = BinderPool.getInsance(BinderPoolActivity.this); 31 | IBinder securityBinder = binderPool 32 | .queryBinder(BinderPool.BINDER_SECURITY_CENTER); 33 | ; 34 | mSecurityCenter = (ISecurityCenter) SecurityCenterImpl 35 | .asInterface(securityBinder); 36 | Log.d(TAG, "visit ISecurityCenter"); 37 | String msg = "helloworld-安卓"; 38 | System.out.println("content:" + msg); 39 | try { 40 | String password = mSecurityCenter.encrypt(msg); 41 | System.out.println("encrypt:" + password); 42 | System.out.println("decrypt:" + mSecurityCenter.decrypt(password)); 43 | } catch (RemoteException e) { 44 | e.printStackTrace(); 45 | } 46 | 47 | Log.d(TAG, "visit ICompute"); 48 | IBinder computeBinder = binderPool 49 | .queryBinder(BinderPool.BINDER_COMPUTE); 50 | ; 51 | mCompute = ComputeImpl.asInterface(computeBinder); 52 | try { 53 | System.out.println("3+5=" + mCompute.add(3, 5)); 54 | } catch (RemoteException e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/binderpool/BinderPoolService.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.Binder; 6 | import android.os.IBinder; 7 | import android.util.Log; 8 | 9 | public class BinderPoolService extends Service { 10 | 11 | private static final String TAG = "BinderPoolService"; 12 | 13 | private Binder mBinderPool = new BinderPool.BinderPoolImpl(); 14 | 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | } 19 | 20 | @Override 21 | public IBinder onBind(Intent intent) { 22 | Log.d(TAG, "onBind"); 23 | return mBinderPool; 24 | } 25 | 26 | @Override 27 | public void onDestroy() { 28 | super.onDestroy(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/binderpool/ComputeImpl.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | import android.os.RemoteException; 4 | 5 | public class ComputeImpl extends ICompute.Stub { 6 | 7 | @Override 8 | public int add(int a, int b) throws RemoteException { 9 | return a + b; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/binderpool/SecurityCenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.binderpool; 2 | 3 | import android.os.RemoteException; 4 | 5 | public class SecurityCenterImpl extends ISecurityCenter.Stub { 6 | 7 | private static final char SECRET_CODE = '^'; 8 | 9 | @Override 10 | public String encrypt(String content) throws RemoteException { 11 | char[] chars = content.toCharArray(); 12 | for (int i = 0; i < chars.length; i++) { 13 | chars[i] ^= SECRET_CODE; 14 | } 15 | return new String(chars); 16 | } 17 | 18 | @Override 19 | public String decrypt(String password) throws RemoteException { 20 | return encrypt(password); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/manager/BookManager.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.manager; 2 | 3 | import com.didi.virtualapk.demo.aidl.IBookManager; 4 | 5 | import android.os.IBinder; 6 | 7 | public class BookManager { 8 | 9 | private IBookManager mBookManager; 10 | 11 | private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { 12 | @Override 13 | public void binderDied() { 14 | if (mBookManager == null) 15 | return; 16 | mBookManager.asBinder().unlinkToDeath(mDeathRecipient, 0); 17 | mBookManager = null; 18 | // TODO:这里重新绑定远程Service 19 | } 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/manager/UserManager.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.manager; 2 | 3 | public class UserManager { 4 | 5 | public static int sUserId = 1; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/manualbinder/Book.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.manualbinder; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | public class Book implements Parcelable { 7 | 8 | public int bookId; 9 | public String bookName; 10 | 11 | public Book() { 12 | 13 | } 14 | 15 | public Book(int bookId, String bookName) { 16 | this.bookId = bookId; 17 | this.bookName = bookName; 18 | } 19 | 20 | public int describeContents() { 21 | return 0; 22 | } 23 | 24 | public void writeToParcel(Parcel out, int flags) { 25 | out.writeInt(bookId); 26 | out.writeString(bookName); 27 | } 28 | 29 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 30 | public Book createFromParcel(Parcel in) { 31 | return new Book(in); 32 | } 33 | 34 | public Book[] newArray(int size) { 35 | return new Book[size]; 36 | } 37 | }; 38 | 39 | private Book(Parcel in) { 40 | bookId = in.readInt(); 41 | bookName = in.readString(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/manualbinder/IBookManager.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.manualbinder; 2 | 3 | import java.util.List; 4 | 5 | import android.os.IBinder; 6 | import android.os.IInterface; 7 | import android.os.RemoteException; 8 | 9 | public interface IBookManager extends IInterface { 10 | 11 | static final String DESCRIPTOR = "com.ryg.chapter_2.manualbinder.IBookManager"; 12 | 13 | static final int TRANSACTION_getBookList = (IBinder.FIRST_CALL_TRANSACTION + 0); 14 | static final int TRANSACTION_addBook = (IBinder.FIRST_CALL_TRANSACTION + 1); 15 | 16 | public List getBookList() throws RemoteException; 17 | 18 | public void addBook(Book book) throws RemoteException; 19 | } 20 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/messenger/MessengerActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.messenger; 2 | 3 | import com.didi.virtualapk.demo.R; 4 | import com.didi.virtualapk.demo.R.layout; 5 | import com.didi.virtualapk.demo.utils.MyConstants; 6 | 7 | import android.app.Activity; 8 | import android.content.ComponentName; 9 | import android.content.Context; 10 | import android.content.Intent; 11 | import android.content.ServiceConnection; 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import android.os.IBinder; 15 | import android.os.Message; 16 | import android.os.Messenger; 17 | import android.os.RemoteException; 18 | import android.util.Log; 19 | 20 | public class MessengerActivity extends Activity { 21 | 22 | private static final String TAG = "MessengerActivity"; 23 | 24 | private Messenger mService; 25 | private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler()); 26 | 27 | private static class MessengerHandler extends Handler { 28 | @Override 29 | public void handleMessage(Message msg) { 30 | switch (msg.what) { 31 | case MyConstants.MSG_FROM_SERVICE: 32 | Log.i(TAG, "receive msg from Service:" + msg.getData().getString("reply")); 33 | break; 34 | default: 35 | super.handleMessage(msg); 36 | } 37 | } 38 | } 39 | 40 | private ServiceConnection mConnection = new ServiceConnection() { 41 | public void onServiceConnected(ComponentName className, IBinder service) { 42 | mService = new Messenger(service); 43 | Log.d(TAG, "bind service"); 44 | Message msg = Message.obtain(null, MyConstants.MSG_FROM_CLIENT); 45 | Bundle data = new Bundle(); 46 | data.putString("msg", "hello, this is client."); 47 | msg.setData(data); 48 | msg.replyTo = mGetReplyMessenger; 49 | try { 50 | mService.send(msg); 51 | } catch (RemoteException e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | 56 | public void onServiceDisconnected(ComponentName className) { 57 | } 58 | }; 59 | 60 | @Override 61 | protected void onCreate(Bundle savedInstanceState) { 62 | super.onCreate(savedInstanceState); 63 | setContentView(R.layout.activity_messenger); 64 | Intent intent = new Intent("com.ryg.MessengerService.launch"); 65 | bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 66 | } 67 | 68 | @Override 69 | protected void onDestroy() { 70 | unbindService(mConnection); 71 | super.onDestroy(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/messenger/MessengerService.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.messenger; 2 | 3 | import com.didi.virtualapk.demo.utils.MyConstants; 4 | 5 | import android.app.Service; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | import android.os.Handler; 9 | import android.os.IBinder; 10 | import android.os.Message; 11 | import android.os.Messenger; 12 | import android.os.RemoteException; 13 | import android.util.Log; 14 | 15 | public class MessengerService extends Service { 16 | 17 | private static final String TAG = "MessengerService"; 18 | 19 | private static class MessengerHandler extends Handler { 20 | @Override 21 | public void handleMessage(Message msg) { 22 | switch (msg.what) { 23 | case MyConstants.MSG_FROM_CLIENT: 24 | Log.i(TAG, "receive msg from Client:" + msg.getData().getString("msg")); 25 | Messenger client = msg.replyTo; 26 | Message relpyMessage = Message.obtain(null, MyConstants.MSG_FROM_SERVICE); 27 | Bundle bundle = new Bundle(); 28 | bundle.putString("reply", "嗯,你的消息我已经收到,稍后会回复你。"); 29 | relpyMessage.setData(bundle); 30 | try { 31 | client.send(relpyMessage); 32 | } catch (RemoteException e) { 33 | e.printStackTrace(); 34 | } 35 | break; 36 | default: 37 | super.handleMessage(msg); 38 | } 39 | } 40 | } 41 | 42 | private final Messenger mMessenger = new Messenger(new MessengerHandler()); 43 | 44 | @Override 45 | public IBinder onBind(Intent intent) { 46 | return mMessenger.getBinder(); 47 | } 48 | 49 | @Override 50 | public void onCreate() { 51 | super.onCreate(); 52 | } 53 | 54 | @Override 55 | public int onStartCommand(Intent intent, int flags, int startId) { 56 | return super.onStartCommand(intent, flags, startId); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/model/User.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.didi.virtualapk.demo.aidl.Book; 6 | 7 | import android.os.Parcel; 8 | import android.os.Parcelable; 9 | 10 | public class User implements Parcelable, Serializable { 11 | private static final long serialVersionUID = 519067123721295773L; 12 | 13 | public int userId; 14 | public String userName; 15 | public boolean isMale; 16 | 17 | public Book book; 18 | 19 | public User() { 20 | } 21 | 22 | public User(int userId, String userName, boolean isMale) { 23 | this.userId = userId; 24 | this.userName = userName; 25 | this.isMale = isMale; 26 | } 27 | 28 | public int describeContents() { 29 | return 0; 30 | } 31 | 32 | public void writeToParcel(Parcel out, int flags) { 33 | out.writeInt(userId); 34 | out.writeString(userName); 35 | out.writeInt(isMale ? 1 : 0); 36 | out.writeParcelable(book, 0); 37 | } 38 | 39 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 40 | public User createFromParcel(Parcel in) { 41 | return new User(in); 42 | } 43 | 44 | public User[] newArray(int size) { 45 | return new User[size]; 46 | } 47 | }; 48 | 49 | private User(Parcel in) { 50 | userId = in.readInt(); 51 | userName = in.readString(); 52 | isMale = in.readInt() == 1; 53 | book = in 54 | .readParcelable(Thread.currentThread().getContextClassLoader()); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return String.format( 60 | "User:{userId:%s, userName:%s, isMale:%s}, with child:{%s}", 61 | userId, userName, isMale, book); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/provider/DbOpenHelper.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.provider; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | public class DbOpenHelper extends SQLiteOpenHelper { 8 | 9 | private static final String DB_NAME = "book_provider.db"; 10 | public static final String BOOK_TABLE_NAME = "book"; 11 | public static final String USER_TALBE_NAME = "user"; 12 | 13 | private static final int DB_VERSION = 3; 14 | 15 | private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS " 16 | + BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT)"; 17 | 18 | private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS " 19 | + USER_TALBE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT," 20 | + "sex INT)"; 21 | 22 | public DbOpenHelper(Context context) { 23 | super(context, DB_NAME, null, DB_VERSION); 24 | } 25 | 26 | @Override 27 | public void onCreate(SQLiteDatabase db) { 28 | db.execSQL(CREATE_BOOK_TABLE); 29 | db.execSQL(CREATE_USER_TABLE); 30 | } 31 | 32 | @Override 33 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 34 | // TODO ignored 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/provider/ProviderActivity.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.provider; 2 | 3 | import com.didi.virtualapk.demo.R; 4 | import com.didi.virtualapk.demo.aidl.Book; 5 | import com.didi.virtualapk.demo.model.User; 6 | 7 | import android.app.Activity; 8 | import android.content.ContentValues; 9 | import android.database.Cursor; 10 | import android.net.Uri; 11 | import android.os.Bundle; 12 | import android.util.Log; 13 | 14 | public class ProviderActivity extends Activity { 15 | private static final String TAG = "ProviderActivity"; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_provider); 21 | // Uri uri = Uri.parse("content://com.ryg.chapter_2.book.provider"); 22 | // getContentResolver().query(uri, null, null, null, null); 23 | // getContentResolver().query(uri, null, null, null, null); 24 | // getContentResolver().query(uri, null, null, null, null); 25 | 26 | Uri bookUri = Uri.parse("content://com.ryg.chapter_2.book.provider/book"); 27 | ContentValues values = new ContentValues(); 28 | values.put("_id", 6); 29 | values.put("name", "程序设计的艺术"); 30 | getContentResolver().insert(bookUri, values); 31 | Cursor bookCursor = getContentResolver().query(bookUri, new String[]{"_id", "name"}, null, null, null); 32 | while (bookCursor.moveToNext()) { 33 | Book book = new Book(); 34 | book.bookId = bookCursor.getInt(0); 35 | book.bookName = bookCursor.getString(1); 36 | Log.d(TAG, "query book:" + book.toString()); 37 | } 38 | bookCursor.close(); 39 | 40 | Uri userUri = Uri.parse("content://com.ryg.chapter_2.book.provider/user"); 41 | Cursor userCursor = getContentResolver().query(userUri, new String[]{"_id", "name", "sex"}, null, null, null); 42 | while (userCursor.moveToNext()) { 43 | User user = new User(); 44 | user.userId = userCursor.getInt(0); 45 | user.userName = userCursor.getString(1); 46 | user.isMale = userCursor.getInt(2) == 1; 47 | Log.d(TAG, "query user:" + user.toString()); 48 | } 49 | userCursor.close(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/socket/TCPServerService.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.socket; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStreamWriter; 8 | import java.io.PrintWriter; 9 | import java.net.ServerSocket; 10 | import java.net.Socket; 11 | import java.util.Random; 12 | 13 | import com.didi.virtualapk.demo.utils.MyUtils; 14 | 15 | import android.app.Service; 16 | import android.content.Intent; 17 | import android.os.IBinder; 18 | 19 | public class TCPServerService extends Service { 20 | 21 | private boolean mIsServiceDestoryed = false; 22 | private String[] mDefinedMessages = new String[] { 23 | "你好啊,哈哈", 24 | "请问你叫什么名字呀?", 25 | "今天北京天气不错啊,shy", 26 | "你知道吗?我可是可以和多个人同时聊天的哦", 27 | "给你讲个笑话吧:据说爱笑的人运气不会太差,不知道真假。" 28 | }; 29 | 30 | @Override 31 | public void onCreate() { 32 | new Thread(new TcpServer()).start(); 33 | super.onCreate(); 34 | } 35 | 36 | @Override 37 | public IBinder onBind(Intent intent) { 38 | return null; 39 | } 40 | 41 | @Override 42 | public void onDestroy() { 43 | mIsServiceDestoryed = true; 44 | super.onDestroy(); 45 | } 46 | 47 | private class TcpServer implements Runnable { 48 | 49 | @SuppressWarnings("resource") 50 | @Override 51 | public void run() { 52 | ServerSocket serverSocket = null; 53 | try { 54 | serverSocket = new ServerSocket(8688); 55 | } catch (IOException e) { 56 | System.err.println("establish tcp server failed, port:8688"); 57 | e.printStackTrace(); 58 | return; 59 | } 60 | 61 | while (!mIsServiceDestoryed) { 62 | try { 63 | // 接受客户端请求 64 | final Socket client = serverSocket.accept(); 65 | System.out.println("accept"); 66 | new Thread() { 67 | @Override 68 | public void run() { 69 | try { 70 | responseClient(client); 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } 74 | }; 75 | }.start(); 76 | 77 | } catch (IOException e) { 78 | e.printStackTrace(); 79 | } 80 | } 81 | } 82 | } 83 | 84 | private void responseClient(Socket client) throws IOException { 85 | // 用于接收客户端消息 86 | BufferedReader in = new BufferedReader(new InputStreamReader( 87 | client.getInputStream())); 88 | // 用于向客户端发送消息 89 | PrintWriter out = new PrintWriter(new BufferedWriter( 90 | new OutputStreamWriter(client.getOutputStream())), true); 91 | out.println("欢迎来到聊天室!"); 92 | while (!mIsServiceDestoryed) { 93 | String str = in.readLine(); 94 | System.out.println("msg from client:" + str); 95 | if (str == null) { 96 | break; 97 | } 98 | int i = new Random().nextInt(mDefinedMessages.length); 99 | String msg = mDefinedMessages[i]; 100 | out.println(msg); 101 | System.out.println("send :" + msg); 102 | } 103 | System.out.println("client quit."); 104 | // 关闭流 105 | MyUtils.close(out); 106 | MyUtils.close(in); 107 | client.close(); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/utils/MyConstants.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.utils; 2 | 3 | import android.os.Environment; 4 | 5 | public class MyConstants { 6 | public static final String CHAPTER_2_PATH = Environment 7 | .getExternalStorageDirectory().getPath() 8 | + "/singwhatiwanna/chapter_2/"; 9 | 10 | public static final String CACHE_FILE_PATH = CHAPTER_2_PATH + "usercache"; 11 | 12 | public static final int MSG_FROM_CLIENT = 0; 13 | public static final int MSG_FROM_SERVICE = 1; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/java/com/didi/virtualapk/demo/utils/MyUtils.java: -------------------------------------------------------------------------------- 1 | package com.didi.virtualapk.demo.utils; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.util.List; 6 | 7 | import android.app.ActivityManager; 8 | import android.app.ActivityManager.RunningAppProcessInfo; 9 | import android.content.Context; 10 | 11 | public class MyUtils { 12 | 13 | public static String getProcessName(Context cxt, int pid) { 14 | ActivityManager am = (ActivityManager) cxt 15 | .getSystemService(Context.ACTIVITY_SERVICE); 16 | List runningApps = am.getRunningAppProcesses(); 17 | if (runningApps == null) { 18 | return null; 19 | } 20 | for (RunningAppProcessInfo procInfo : runningApps) { 21 | if (procInfo.pid == pid) { 22 | return procInfo.processName; 23 | } 24 | } 25 | return null; 26 | } 27 | 28 | public static void close(Closeable closeable) { 29 | try { 30 | if (closeable != null) { 31 | closeable.close(); 32 | } 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | public static void executeInThread(Runnable runnable) { 39 | new Thread(runnable).start(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/VirtualAPK/b1a778a06688f89f574ec8608f0764eadb9009b7/PluginDemo/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/VirtualAPK/b1a778a06688f89f574ec8608f0764eadb9009b7/PluginDemo/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/VirtualAPK/b1a778a06688f89f574ec8608f0764eadb9009b7/PluginDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/VirtualAPK/b1a778a06688f89f574ec8608f0764eadb9009b7/PluginDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/drawable/edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/layout/activity_binder_pool.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /PluginDemo/app/src/main/res/layout/activity_book_manager.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 |