├── .gitignore ├── CONTRIBUTING.MD ├── LICENSE ├── README.md ├── README.zh-CN.md ├── SPLIT_UPDATE_GUIDE.MD ├── SPLIT_UPDATE_GUIDE.zh.CN.md ├── app ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── multidexkeep.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iqiyi │ │ └── qigsaw │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── iqiyi │ │ │ └── qigsaw │ │ │ └── sample │ │ │ ├── MainActivity.java │ │ │ ├── QigsawApplication.java │ │ │ ├── QigsawInstaller.java │ │ │ ├── SampleObtainUserConfirmationDialog.java │ │ │ ├── SampleSplitAppComponentFactory.java │ │ │ ├── downloader │ │ │ └── SampleDownloader.java │ │ │ └── reporter │ │ │ ├── SampleLogger.java │ │ │ ├── SampleSplitInstallReporter.java │ │ │ ├── SampleSplitLoadReporter.java │ │ │ ├── SampleSplitUninstallReporter.java │ │ │ └── SampleSplitUpdateReporter.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_qigsaw_installer.xml │ │ └── activity_sample_obtain_user_confirmation.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── feature_names.xml │ │ ├── installer_status.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── iqiyi │ └── qigsaw │ └── ExampleUnitTest.java ├── assets ├── qigsaw.png └── qigsaw_qq_group_chat.jpeg ├── build.gradle ├── buildSrc ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── main │ ├── groovy │ └── com │ │ └── iqiyi │ │ └── qigsaw │ │ └── buildtool │ │ └── gradle │ │ ├── QigsawAppBasePlugin.groovy │ │ ├── QigsawDynamicFeaturePlugin.groovy │ │ ├── QigsawPlugin.groovy │ │ ├── compiling │ │ ├── DexReMergeHandler.groovy │ │ ├── FixedMainDexList.groovy │ │ └── QigsawConfigGenerator.groovy │ │ ├── extension │ │ ├── QigsawSplitExtension.groovy │ │ └── QigsawSplitExtensionHelper.groovy │ │ ├── internal │ │ ├── entity │ │ │ ├── SplitDetails.groovy │ │ │ └── SplitInfo.groovy │ │ └── tool │ │ │ ├── AGPCompat.groovy │ │ │ ├── ApkSigner.groovy │ │ │ ├── CommandUtils.groovy │ │ │ ├── FileUtils.groovy │ │ │ ├── ManifestReader.groovy │ │ │ ├── SplitLogger.groovy │ │ │ ├── TinkerHelper.groovy │ │ │ ├── TypeClassFileParser.groovy │ │ │ └── ZipUtils.groovy │ │ ├── task │ │ ├── CreateSplitDetailsFileTask.groovy │ │ ├── ExtractTargetFilesFromOldApk.groovy │ │ ├── GenerateQigsawConfig.groovy │ │ ├── ProcessOldOutputsBaseTask.groovy │ │ ├── ProcessSplitApkTask.groovy │ │ ├── QigsawInstallTask.groovy │ │ ├── QigsawProcessManifestTask.groovy │ │ ├── QigsawProguardConfigTask.groovy │ │ └── SplitBaseApkForABIsTask.groovy │ │ ├── transform │ │ ├── SimpleClassCreatorTransform.groovy │ │ ├── SplitActivityWeaver.groovy │ │ ├── SplitComponentTransform.groovy │ │ ├── SplitComponentWeaver.groovy │ │ ├── SplitLibraryLoaderTransform.groovy │ │ ├── SplitReceiverWeaver.groovy │ │ ├── SplitResourcesLoaderInjector.groovy │ │ ├── SplitResourcesLoaderTransform.groovy │ │ └── SplitServiceWeaver.groovy │ │ └── upload │ │ ├── SplitApkUploadException.groovy │ │ ├── SplitApkUploader.groovy │ │ └── SplitApkUploaderInstance.groovy │ └── resources │ └── META-INF │ └── gradle-plugins │ ├── com.iqiyi.qigsaw.application.properties │ └── com.iqiyi.qigsaw.dynamicfeature.properties ├── checkstyle.xml ├── docs ├── 2019GMTC-基于Android App Bundle的动态化方案探索.pdf └── 2019GMTC-基于Android App Bundle的动态化方案探索.zip ├── downloader ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iqiyi │ │ └── qigsaw │ │ └── sample │ │ └── downloader │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── iqiyi │ │ │ └── qigsaw │ │ │ └── sample │ │ │ └── downloader │ │ │ ├── DeleteDownloadedFilesTask.java │ │ │ ├── GroupDownloadContext.java │ │ │ ├── GroupDownloadTaskQueueListener.java │ │ │ ├── GroupTaskDownloadCallBack.java │ │ │ ├── GroupTaskDownloader.java │ │ │ └── OnBunchCancelListener.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── iqiyi │ └── qigsaw │ └── sample │ └── downloader │ └── ExampleUnitTest.java ├── features ├── assets │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── assets │ │ └── assets.txt ├── java │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── iqiyi │ │ │ └── qigsaw │ │ │ └── sample │ │ │ └── java │ │ │ ├── JavaContentProvider.java │ │ │ ├── JavaSampleActivity.java │ │ │ ├── JavaSampleApplication.java │ │ │ └── JavaSampleFragment.java │ │ └── res │ │ ├── layout │ │ └── activity_java_sample.xml │ │ └── values │ │ └── strings.xml └── native │ ├── build.gradle │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── iqiyi │ │ └── qigsaw │ │ └── sample │ │ └── ccode │ │ └── NativeSampleActivity.java │ ├── jni │ ├── CMakeLists.txt │ └── hello-jni.c │ └── res │ └── layout │ └── activity_native_sample.xml ├── gradle.properties ├── gradle ├── android-artifacts.gradle ├── checkStyle.gradle ├── gradle-bintray-upload.gradle ├── gradle-maven-upload.gradle ├── java-artifacts.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── keystore ├── debug.jks └── release.jks ├── qigsaw-android-sample ├── build.gradle ├── buildSrc │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── groovy │ │ └── com │ │ │ └── iqiyi │ │ │ └── qigsaw │ │ │ └── buildtool │ │ │ └── gradle │ │ │ └── sample │ │ │ ├── QigsawAppPlugin.groovy │ │ │ ├── extension │ │ │ └── SplitUploadExtension.groovy │ │ │ └── upload │ │ │ └── SampleSplitApkUploader.groovy │ │ └── resources │ │ └── META-INF │ │ └── gradle-plugins │ │ └── com.iqiyi.qigsaw.sample.application.properties ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── keystore │ ├── debug.jks │ └── release.jks └── settings.gradle ├── qigsaw-android ├── playcorelibrary │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── qigsaw │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── google │ │ │ └── android │ │ │ ├── binder │ │ │ ├── BinderWrapper.java │ │ │ ├── Empty.java │ │ │ ├── IInterfaceProxy.java │ │ │ └── ParcelHelper.java │ │ │ └── play │ │ │ └── core │ │ │ ├── listener │ │ │ ├── StateUpdateListenerRegister.java │ │ │ ├── StateUpdatedListener.java │ │ │ └── StateUpdatedReceiver.java │ │ │ ├── remote │ │ │ ├── BindServiceTask.java │ │ │ ├── DeathRecipientImpl.java │ │ │ ├── IRemote.java │ │ │ ├── OnBinderDiedListener.java │ │ │ ├── RemoteManager.java │ │ │ ├── RemoteServiceException.java │ │ │ ├── RemoteTask.java │ │ │ ├── ServiceConnectedTask.java │ │ │ ├── ServiceConnectionImpl.java │ │ │ ├── ServiceDisconnectedTask.java │ │ │ └── UnbindServiceTask.java │ │ │ ├── splitcompat │ │ │ ├── LoadedSplitFetcherImpl.java │ │ │ ├── SplitCompat.java │ │ │ ├── SplitCompatApplication.java │ │ │ ├── SplitLoadSessionTask.java │ │ │ ├── SplitSessionLoaderImpl.java │ │ │ └── util │ │ │ │ └── PlayCore.java │ │ │ ├── splitinstall │ │ │ ├── CancelInstallCallback.java │ │ │ ├── CancelInstallTask.java │ │ │ ├── ChangeSessionStatusWorker.java │ │ │ ├── DeferredInstallCallback.java │ │ │ ├── DeferredInstallTask.java │ │ │ ├── DeferredUninstallCallback.java │ │ │ ├── DeferredUninstallTask.java │ │ │ ├── GetSessionStateCallback.java │ │ │ ├── GetSessionStateTask.java │ │ │ ├── GetSessionStatesCallback.java │ │ │ ├── GetSessionStatesTask.java │ │ │ ├── LoadedSplitFetcher.java │ │ │ ├── LoadedSplitFetcherSingleton.java │ │ │ ├── OnBinderDiedListenerImpl.java │ │ │ ├── SplitInstallException.java │ │ │ ├── SplitInstallHelper.java │ │ │ ├── SplitInstallListenerRegistry.java │ │ │ ├── SplitInstallManager.java │ │ │ ├── SplitInstallManagerFactory.java │ │ │ ├── SplitInstallManagerImpl.java │ │ │ ├── SplitInstallRequest.java │ │ │ ├── SplitInstallService.java │ │ │ ├── SplitInstallServiceCallbackImpl.java │ │ │ ├── SplitInstallSessionState.java │ │ │ ├── SplitInstallStateUpdatedListener.java │ │ │ ├── SplitInstalledDisposer.java │ │ │ ├── SplitRemoteImpl.java │ │ │ ├── SplitSessionLoader.java │ │ │ ├── SplitSessionLoaderSingleton.java │ │ │ ├── SplitSessionStatusChanger.java │ │ │ ├── StartInstallCallback.java │ │ │ ├── StartInstallTask.java │ │ │ ├── model │ │ │ │ ├── SplitInstallErrorCode.java │ │ │ │ └── SplitInstallSessionStatus.java │ │ │ └── protocol │ │ │ │ ├── ISplitInstallServiceCallbackProxy.java │ │ │ │ ├── ISplitInstallServiceHolder.java │ │ │ │ ├── ISplitInstallServiceImpl.java │ │ │ │ ├── ISplitInstallServiceProxy.java │ │ │ │ └── SplitInstallServiceCallback.java │ │ │ └── tasks │ │ │ ├── InvocationListener.java │ │ │ ├── InvocationListenerManager.java │ │ │ ├── InvokeCompleteListener.java │ │ │ ├── InvokeFailureListener.java │ │ │ ├── InvokeSuccessListener.java │ │ │ ├── OnCompleteListener.java │ │ │ ├── OnFailureListener.java │ │ │ ├── OnSuccessListener.java │ │ │ ├── RuntimeExecutionException.java │ │ │ ├── Task.java │ │ │ ├── TaskCompleteRunnable.java │ │ │ ├── TaskExecutor.java │ │ │ ├── TaskExecutors.java │ │ │ ├── TaskFailureRunnable.java │ │ │ ├── TaskImpl.java │ │ │ ├── TaskSuccessRunnable.java │ │ │ ├── TaskWrapper.java │ │ │ └── Tasks.java │ │ └── test │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── qigsaw │ │ └── ExampleUnitTest.java ├── splitcommon │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── common │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── common │ │ │ ├── AbiUtil.java │ │ │ ├── CompatBundle.java │ │ │ ├── FileLockHelper.java │ │ │ ├── FileUtil.java │ │ │ ├── ICompatBundle.java │ │ │ ├── OEMCompat.java │ │ │ ├── ProcessUtil.java │ │ │ ├── SplitAABInfoProvider.java │ │ │ ├── SplitBaseInfoProvider.java │ │ │ ├── SplitConstants.java │ │ │ ├── SplitElfFile.java │ │ │ └── SplitLog.java │ │ └── test │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── common │ │ └── ExampleUnitTest.java ├── splitcore │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── iqiyi │ │ │ │ └── android │ │ │ │ └── qigsaw │ │ │ │ └── core │ │ │ │ ├── DefaultObtainUserConfirmationDialog.java │ │ │ │ ├── InjectActivityResource.java │ │ │ │ ├── ObtainUserConfirmationDialog.java │ │ │ │ ├── Qigsaw.java │ │ │ │ ├── SplitActivityLifecycleCallbacks.java │ │ │ │ └── SplitConfiguration.java │ │ └── res │ │ │ ├── layout │ │ │ └── activity_obtain_user_confirmation.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── ExampleUnitTest.java ├── splitdownloader │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── splitdownload │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── splitdownload │ │ │ ├── DownloadCallback.java │ │ │ ├── DownloadRequest.java │ │ │ └── Downloader.java │ │ └── test │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── splitdownload │ │ └── ExampleUnitTest.java ├── splitextension │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── extension │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── extension │ │ │ ├── AABExtension.java │ │ │ ├── AABExtensionException.java │ │ │ ├── AABExtensionManager.java │ │ │ ├── AABExtensionManagerImpl.java │ │ │ ├── ComponentInfoManager.java │ │ │ ├── ContentProviderProxy.java │ │ │ ├── SplitComponentInfoProvider.java │ │ │ └── fakecomponents │ │ │ ├── FakeActivity.java │ │ │ ├── FakeReceiver.java │ │ │ ├── FakeService.java │ │ │ └── OrientationCompat.java │ │ └── test │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── extension │ │ └── ExampleUnitTest.java ├── splitinstaller │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── aidl │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── splitinstall │ │ │ └── protocol │ │ │ ├── ISplitInstallService.aidl │ │ │ └── ISplitInstallServiceCallback.aidl │ │ └── java │ │ └── com │ │ ├── iqiyi │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── splitinstall │ │ │ ├── DeferredDownloadCallback.java │ │ │ ├── SignatureValidator.java │ │ │ ├── SplitApkInstaller.java │ │ │ ├── SplitCleanService.java │ │ │ ├── SplitDeferredInstallTask.java │ │ │ ├── SplitDownloadPreprocessor.java │ │ │ ├── SplitInstallInternalErrorCode.java │ │ │ ├── SplitInstallInternalSessionState.java │ │ │ ├── SplitInstallInternalSessionStatus.java │ │ │ ├── SplitInstallReporterManager.java │ │ │ ├── SplitInstallSessionManager.java │ │ │ ├── SplitInstallSessionManagerImpl.java │ │ │ ├── SplitInstallSupervisorImpl.java │ │ │ ├── SplitInstallTask.java │ │ │ ├── SplitInstaller.java │ │ │ ├── SplitInstallerExecutor.java │ │ │ ├── SplitInstallerImpl.java │ │ │ ├── SplitInstallerThread.java │ │ │ ├── SplitLibExtractor.java │ │ │ ├── SplitMultiDexExtractor.java │ │ │ ├── SplitPendingUninstallManager.java │ │ │ ├── SplitSessionInstaller.java │ │ │ ├── SplitSessionInstallerImpl.java │ │ │ ├── SplitStartInstallTask.java │ │ │ ├── SplitUninstallReporterManager.java │ │ │ ├── StartDownloadCallback.java │ │ │ └── remote │ │ │ ├── DefaultTask.java │ │ │ ├── OnCancelInstallTask.java │ │ │ ├── OnDeferredInstallTask.java │ │ │ ├── OnDeferredUninstallTask.java │ │ │ ├── OnGetSessionStateTask.java │ │ │ ├── OnGetSessionStatesTask.java │ │ │ ├── OnStartInstallTask.java │ │ │ ├── SplitDeleteRedundantVersionTask.java │ │ │ ├── SplitInstallService.java │ │ │ ├── SplitInstallSupervisor.java │ │ │ └── SplitStartUninstallTask.java │ │ └── split │ │ └── signature │ │ ├── A.java │ │ ├── B.java │ │ ├── C.java │ │ ├── D.java │ │ ├── G.java │ │ ├── X509CertificateEx.java │ │ └── X509CertificateWrapper.java ├── splitloader │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── splitload │ │ ├── ClassNotFoundInterceptor.java │ │ ├── DefaultClassNotFoundInterceptor.java │ │ ├── HiddenApiReflection.java │ │ ├── SkipSplitLoadTaskImpl.java │ │ ├── Split.java │ │ ├── SplitActivator.java │ │ ├── SplitApplicationLoaders.java │ │ ├── SplitCompatDexLoader.java │ │ ├── SplitCompatLibraryLoader.java │ │ ├── SplitCompatResourcesException.java │ │ ├── SplitCompatResourcesLoader.java │ │ ├── SplitContentProvider.java │ │ ├── SplitDelegateClassLoaderFactory.java │ │ ├── SplitDelegateClassloader.java │ │ ├── SplitDexClassLoader.java │ │ ├── SplitLibraryLoaderHelper.java │ │ ├── SplitLoad.java │ │ ├── SplitLoadException.java │ │ ├── SplitLoadHandler.java │ │ ├── SplitLoadManager.java │ │ ├── SplitLoadManagerImpl.java │ │ ├── SplitLoadManagerService.java │ │ ├── SplitLoadReporterManager.java │ │ ├── SplitLoadTask.java │ │ ├── SplitLoadTaskImpl.java │ │ ├── SplitLoadTaskImpl2.java │ │ ├── SplitLoader.java │ │ ├── SplitLoaderImpl.java │ │ ├── SplitLoaderImpl2.java │ │ ├── SplitLoaderWrapper.java │ │ ├── SplitUnKnownFileTypeDexLoader.java │ │ ├── compat │ │ ├── NativePathMapper.java │ │ ├── NativePathMapperImpl.java │ │ ├── PathMapperAbove21.java │ │ ├── PathMapperV21.java │ │ └── SplitResourcesLoader.java │ │ └── listener │ │ └── OnSplitLoadListener.java ├── splitreporter │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── splitreport │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── iqiyi │ │ │ └── android │ │ │ └── qigsaw │ │ │ └── core │ │ │ └── splitreport │ │ │ ├── DefaultSplitInstallReporter.java │ │ │ ├── DefaultSplitLoadReporter.java │ │ │ ├── DefaultSplitUninstallReporter.java │ │ │ ├── DefaultSplitUpdateReporter.java │ │ │ ├── SplitBriefInfo.java │ │ │ ├── SplitInstallError.java │ │ │ ├── SplitInstallReporter.java │ │ │ ├── SplitLoadError.java │ │ │ ├── SplitLoadReporter.java │ │ │ ├── SplitUninstallReporter.java │ │ │ ├── SplitUpdateErrorCode.java │ │ │ └── SplitUpdateReporter.java │ │ └── test │ │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── splitreport │ │ └── ExampleUnitTest.java └── splitrequester │ ├── build.gradle │ ├── gradle.properties │ ├── proguard-rules.pro │ └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── splitrequest │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── iqiyi │ │ └── android │ │ └── qigsaw │ │ └── core │ │ └── splitrequest │ │ └── splitinfo │ │ ├── SplitDetails.java │ │ ├── SplitInfo.java │ │ ├── SplitInfoListing.java │ │ ├── SplitInfoManager.java │ │ ├── SplitInfoManagerImpl.java │ │ ├── SplitInfoManagerService.java │ │ ├── SplitInfoVersionData.java │ │ ├── SplitInfoVersionDataStorage.java │ │ ├── SplitInfoVersionDataStorageImpl.java │ │ ├── SplitInfoVersionManager.java │ │ ├── SplitInfoVersionManagerImpl.java │ │ ├── SplitPathManager.java │ │ ├── SplitUpdateReporterManager.java │ │ └── SplitUpdateService.java │ └── test │ └── java │ └── com │ └── iqiyi │ └── android │ └── qigsaw │ └── core │ └── splitrequest │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | gen 2 | bin 3 | target 4 | .idea 5 | .settings 6 | *.iml 7 | .classpath 8 | .project 9 | out 10 | classes 11 | gen-external-apklibs 12 | .DS_Store 13 | .gradle 14 | local.properties 15 | build/ 16 | buildSrc/build 17 | *.apk 18 | *.hprof 19 | infer-out/ 20 | captures/ 21 | *.swp 22 | 23 | strings/src/main/generated/ 24 | .externalNativeBuild 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.MD: -------------------------------------------------------------------------------- 1 | # Contributing to Qigsaw 2 | 3 | Welcome to the Qigsaw project. Read on to learn more about our development process and how to propose bug fixes and improvements. 4 | 5 | ## Issues 6 | 7 | We use GitHub issues to track public bugs and feature requests. Before creating an issue, please note the following: 8 | 9 | 1. Please search existing issues before creating a new one. 10 | 2. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue. The more information the better. 11 | 12 | 13 | ## Branch Management 14 | 15 | There are 2 main branches: 16 | 17 | 1. `master` branch 18 | 19 | * It's the latest (pre-)release branch. We use `master` for tags. 20 | * **Please do NOT submit any PR on `master` branch.** 21 | 22 | 2. `dev` branch 23 | 24 | * It's our stable developing branch. 25 | * Once `dev` has passed iQIYI's internal tests, it will be merged to `master` branch for the next release. 26 | * **Please always submit PR on `dev` branch.** 27 | 28 | 29 | ## Pull Requests 30 | 31 | Please make sure the following is done when submitting a pull request: 32 | 33 | 1. Fork the repo and create your branch from `master`. 34 | 2. Add the copyright notice to the top of any new files you've added. 35 | 3. Check your Java code lints and checkstyles. 36 | 4. Try your best to test your code. 37 | 5. Squash all of your commits into one meaningful commit. 38 | 39 | ## Code Style Guide 40 | 41 | 1. 4 spaces for indentation rather than tabs. 42 | 2. Follow this [checkstyle configuration](./checkstyle.xml) for Java code. 43 | 44 | ## License 45 | 46 | By contributing to Qigsaw, you agree that your contributions will be licensed under its [MIT LICENSE](LICENSE). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 2 | 3 | Most source code in Qigsaw are MIT licensed. 4 | 5 | A copy of the MIT License is included in this file. 6 | 7 | Terms of the MIT License 8 | ======================== 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. -------------------------------------------------------------------------------- /SPLIT_UPDATE_GUIDE.zh.CN.md: -------------------------------------------------------------------------------- 1 | # Qigsaw插件更新步骤 2 | 3 | ### 创建插件更新所需分支 4 | 5 | 为你的代码创建插件更新所需的分支。 6 | 7 | ### 修改插件版本号 8 | 9 | 完成插件代码更新后,在*dynamicfeature/build.gradlew*文件中修改插件版本号(如果不修改插件版本号插件将无法更新)。 10 | 11 | ``` 12 | android { 13 | compileSdkVersion versions.compileSdk 14 | defaultConfig { 15 | minSdkVersion versions.minSdk 16 | targetSdkVersion versions.targetSdk 17 | versionCode 1 18 | //versionName "1.0.0" 19 | versionName "1.0.1" 20 | } 21 | } 22 | ``` 23 | 24 | ### 配置文件并修改Split-Info版本号 25 | 26 | 1. 配置mapping文件。 27 | 2. 配置old apk,存放路径与mapping文件目录一直。 28 | 3. 修改插件信息版本号。 29 | 30 | ``` 31 | qigsawSplit { 32 | 33 | /** 34 | * 可选项,默认为'null' 35 | 36 | * 需要更新插件时,必须将上一版本的apk配置到指定路径 37 | 38 | */ 39 | oldApk = "${qigsawPath}/app.apk" 40 | 41 | /** 42 | * 可选项,默认为'1.0.0' 43 | 44 | * 当需要更新插件时,必须修改splitInfoVersion的值 45 | 46 | */ 47 | //splitInfoVersion '1.0.0' 48 | splitInfoVersion '1.0.1' 49 | 50 | /** 51 | * 可选项,默认为'null' 52 | 53 | * 当需要更新插件时, 必须配置applyMapping的值. 54 | 55 | */ 56 | applyMapping = "${qigsawPath}/mapping.txt" 57 | 58 | /** 59 | * 可选项,默认为'false' 60 | 61 | * 是否将插件上传至CDN,true代表需要上传至CDN。 62 | * 插件是否上传,由两个因素决定:1.releaseSplitApk必须为true。2.dynamic-feature项目AndroidManifest.xml中onDemand为true 63 | 64 | */ 65 | releaseSplitApk true 66 | } 67 | ``` 68 | 69 | - mapping文件应用规则 70 | 71 | 插件首次更新,应用app首次发布生成的mapping文件。 72 | 73 | 插件二次更新,应用插件第一次更新生成的mapping文件。以此类推。 74 | 75 | - old apk应用规则 76 | 77 | 插件更新情况下,始终应用app首次发布生成的apk文件。 78 | 79 | - 关于不同渠道 80 | 81 | 某些应用不同渠道其mapping文件不一样,因此需要针对这些渠道分别打包发布。 82 | 83 | ### 上传插件信息文件 84 | 85 | 上传新生成的插件信息JSON文件至您的发布后台。 86 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jul 17 11:22:29 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /app/multidexkeep.pro: -------------------------------------------------------------------------------- 1 | #your dex.loader patterns here 2 | 3 | -keep class com.iqiyi.android.qigsaw.core.Qigsaw { 4 | (...); 5 | void install(...); 6 | void onAppGetResources(Resources); 7 | } 8 | 9 | -keep class * implements com.iqiyi.android.qigsaw.core.splitdownload.Downloader { 10 | (...); 11 | } 12 | 13 | # ${yourApplicationId}.QigsawConfig, QigsawVersion >= 1.2.2 14 | -keep class **.QigsawConfig { 15 | *; 16 | } 17 | 18 | # ${yourPackageNameInManifest}.BuildConfig QigsawVersion < 1.2.2 19 | -keep class com.iqiyi.qigsaw.sample.BuildConfig { 20 | *; 21 | } 22 | 23 | -keep class com.iqiyi.android.qigsaw.core.extension.ComponentInfo { 24 | *; 25 | } 26 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings 23 | -dontwarn org.conscrypt.* 24 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -------------------------------------------------------------------------------- /app/src/androidTest/java/com/iqiyi/qigsaw/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.qigsaw", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/iqiyi/qigsaw/sample/SampleSplitAppComponentFactory.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample; 2 | 3 | import android.app.AppComponentFactory; 4 | import android.content.pm.ApplicationInfo; 5 | import android.os.Build; 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.RequiresApi; 8 | 9 | import com.iqiyi.android.qigsaw.core.splitload.SplitDelegateClassLoaderFactory; 10 | 11 | @RequiresApi(api = Build.VERSION_CODES.Q) 12 | public class SampleSplitAppComponentFactory extends AppComponentFactory { 13 | 14 | private ClassLoader classLoader; 15 | 16 | @NonNull 17 | @Override 18 | public ClassLoader instantiateClassLoader(@NonNull ClassLoader cl, @NonNull ApplicationInfo aInfo) { 19 | ClassLoader preCl = super.instantiateClassLoader(cl, aInfo); 20 | if (classLoader == null) { 21 | classLoader = SplitDelegateClassLoaderFactory.instantiateClassLoader(preCl); 22 | } 23 | return classLoader; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/iqiyi/qigsaw/sample/reporter/SampleSplitLoadReporter.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.reporter; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | 6 | import com.iqiyi.android.qigsaw.core.splitreport.DefaultSplitLoadReporter; 7 | import com.iqiyi.android.qigsaw.core.splitreport.SplitBriefInfo; 8 | import com.iqiyi.android.qigsaw.core.splitreport.SplitLoadError; 9 | 10 | import java.util.List; 11 | 12 | public class SampleSplitLoadReporter extends DefaultSplitLoadReporter { 13 | 14 | public SampleSplitLoadReporter(Context context) { 15 | super(context); 16 | } 17 | 18 | @Override 19 | public void onLoadOK(String processName, @NonNull List loadOKSplits, long cost) { 20 | super.onLoadOK(processName, loadOKSplits, cost); 21 | } 22 | 23 | @Override 24 | public void onLoadFailed(String processName, @NonNull List loadOKSplits, @NonNull List loadErrorSplits, long cost) { 25 | super.onLoadFailed(processName, loadOKSplits, loadErrorSplits, cost); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/iqiyi/qigsaw/sample/reporter/SampleSplitUninstallReporter.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.reporter; 2 | 3 | import android.content.Context; 4 | 5 | import com.iqiyi.android.qigsaw.core.splitreport.DefaultSplitUninstallReporter; 6 | 7 | import java.util.List; 8 | 9 | public class SampleSplitUninstallReporter extends DefaultSplitUninstallReporter { 10 | 11 | public SampleSplitUninstallReporter(Context context) { 12 | super(context); 13 | } 14 | 15 | @Override 16 | public void onSplitUninstallOK(List uninstalledSplits, long cost) { 17 | super.onSplitUninstallOK(uninstalledSplits, cost); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/iqiyi/qigsaw/sample/reporter/SampleSplitUpdateReporter.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.reporter; 2 | 3 | import android.content.Context; 4 | 5 | import com.iqiyi.android.qigsaw.core.splitreport.DefaultSplitUpdateReporter; 6 | 7 | import java.util.List; 8 | 9 | public class SampleSplitUpdateReporter extends DefaultSplitUpdateReporter { 10 | 11 | public SampleSplitUpdateReporter(Context context) { 12 | super(context); 13 | } 14 | 15 | 16 | @Override 17 | public void onUpdateOK(String oldSplitInfoVersion, String newSplitInfoVersion, List updateSplits) { 18 | super.onUpdateOK(oldSplitInfoVersion, newSplitInfoVersion, updateSplits); 19 | } 20 | 21 | @Override 22 | public void onUpdateFailed(String oldSplitInfoVersion, String newSplitInfoVersion, int errorCode) { 23 | super.onUpdateFailed(oldSplitInfoVersion, newSplitInfoVersion, errorCode); 24 | } 25 | 26 | @Override 27 | public void onNewSplitInfoVersionLoaded(String newSplitInfoVersion) { 28 | super.onNewSplitInfoVersionLoaded(newSplitInfoVersion); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_qigsaw_installer.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 19 | 20 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | #FFFFFF 7 | #000000 8 | #808080 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/feature_names.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | java 19 | assets 20 | native 21 | -------------------------------------------------------------------------------- /app/src/main/res/values/installer_status.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | Module requested is unavailable 19 | Install request is invalid 20 | Please check your phone network status! 21 | Install is not permitted under current device circumstances 22 | Request is existing! 23 | Service is unavailable, please try again. 24 | Internal error 25 | 26 | Pending… 27 | 28 | Downloading… 29 | Download completely 30 | Installing… 31 | Install completely 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Qigsaw 3 | java 4 | assets 5 | native 6 | Start Kotlin Feature 7 | Start Java Feature 8 | Start Native Feature 9 | Show assets 10 | Loading 11 | Press a button to perform an action. 12 | Install all features now 13 | Load all features deferred 14 | Install deferred 15 | Uninstall deferred 16 | Request module uninstall 17 | Module Title 18 | 19 | Warm Prompt 20 | Using this feature will consume about %s M traffic data, Do you want to continue downloading? 21 | Confirm 22 | Cancel 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/iqiyi/qigsaw/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /assets/qigsaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/assets/qigsaw.png -------------------------------------------------------------------------------- /assets/qigsaw_qq_group_chat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/assets/qigsaw_qq_group_chat.jpeg -------------------------------------------------------------------------------- /buildSrc/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=gradle-plugin 2 | POM_NAME=Qigsaw Gradle Plugin 3 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /buildSrc/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/buildSrc/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /buildSrc/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jun 25 23:07:43 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/internal/tool/CommandUtils.groovy: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.buildtool.gradle.internal.tool 2 | 3 | /*source code from https://github.com/shwenzhang/AndResGuard*/ 4 | 5 | class CommandUtils { 6 | 7 | static String runCmd(String... cmd) throws IOException, InterruptedException { 8 | String output = null 9 | Process process = null 10 | try { 11 | process = new ProcessBuilder(cmd).start() 12 | output = readInputStream(process.getInputStream()) 13 | process.waitFor() 14 | if (process.exitValue() != 0) { 15 | System.err.println(String.format("%s Failed! Please check your signature file.\n", cmd[0])) 16 | throw new RuntimeException(readInputStream(process.getErrorStream())) 17 | } 18 | } finally { 19 | if (process != null) { 20 | process.destroy() 21 | } 22 | } 23 | return output 24 | } 25 | 26 | static String readInputStream(InputStream inputStream) throws IOException { 27 | ByteArrayOutputStream result = new ByteArrayOutputStream(); 28 | byte[] buffer = new byte[4096] 29 | int length 30 | while ((length = inputStream.read(buffer)) != -1) { 31 | result.write(buffer, 0, length) 32 | } 33 | return result.toString("UTF-8") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/transform/SplitComponentWeaver.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.qigsaw.buildtool.gradle.transform 26 | 27 | interface SplitComponentWeaver { 28 | 29 | String CLASS_WOVEN = "com/google/android/play/core/splitinstall/SplitInstallHelper" 30 | 31 | String METHOD_WOVEN = "loadResources" 32 | 33 | byte[] weave(InputStream inputStream) 34 | 35 | } 36 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/upload/SplitApkUploadException.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.qigsaw.buildtool.gradle.upload 26 | 27 | class SplitApkUploadException extends Exception { 28 | 29 | SplitApkUploadException(int errorCode, String msg) { 30 | super((new StringBuilder()).append("Split Upload Error Code: ").append(errorCode).append("\n").append("Split Upload Error message: ").append(msg).toString()) 31 | } 32 | 33 | SplitApkUploadException(String msg) { 34 | super(msg) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/upload/SplitApkUploader.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.qigsaw.buildtool.gradle.upload 26 | 27 | import org.gradle.api.Project 28 | 29 | interface SplitApkUploader { 30 | 31 | String uploadSync(Project appProject, File splitApk, String splitName) throws SplitApkUploadException 32 | 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/upload/SplitApkUploaderInstance.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.qigsaw.buildtool.gradle.upload 26 | 27 | import java.util.concurrent.atomic.AtomicReference 28 | 29 | class SplitApkUploaderInstance { 30 | 31 | private static final AtomicReference sUploaderRef = new AtomicReference<>() 32 | 33 | static SplitApkUploader get() { 34 | return sUploaderRef.get() 35 | } 36 | 37 | static void set(SplitApkUploader uploader) { 38 | sUploaderRef.compareAndSet(null, uploader) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /buildSrc/src/main/resources/META-INF/gradle-plugins/com.iqiyi.qigsaw.application.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.iqiyi.qigsaw.buildtool.gradle.QigsawAppBasePlugin -------------------------------------------------------------------------------- /buildSrc/src/main/resources/META-INF/gradle-plugins/com.iqiyi.qigsaw.dynamicfeature.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.iqiyi.qigsaw.buildtool.gradle.QigsawDynamicFeaturePlugin -------------------------------------------------------------------------------- /docs/2019GMTC-基于Android App Bundle的动态化方案探索.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/docs/2019GMTC-基于Android App Bundle的动态化方案探索.pdf -------------------------------------------------------------------------------- /docs/2019GMTC-基于Android App Bundle的动态化方案探索.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/docs/2019GMTC-基于Android App Bundle的动态化方案探索.zip -------------------------------------------------------------------------------- /downloader/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion versions.compileSdk 5 | defaultConfig { 6 | minSdkVersion versions.minSdk 7 | targetSdkVersion versions.targetSdk 8 | versionCode 1 9 | versionName "1.0" 10 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 11 | 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | 25 | //for downloader 26 | compileOnly 'net.jcip:jcip-annotations:1.0' 27 | compileOnly 'com.github.spotbugs:spotbugs-annotations:3.1.3' 28 | implementation 'com.google.code.findbugs:jsr305:3.0.2' 29 | // core 30 | implementation 'com.liulishuo.okdownload:okdownload:1.0.5' 31 | // provide sqlite to store breakpoints 32 | implementation 'com.liulishuo.okdownload:sqlite:1.0.5' 33 | // provide okhttp to connect to backend 34 | implementation 'com.liulishuo.okdownload:okhttp:1.0.5' 35 | implementation 'com.squareup.okhttp3:okhttp:3.10.0' 36 | 37 | testImplementation 'junit:junit:4.12' 38 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 39 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 40 | implementation 'androidx.annotation:annotation:1.0.0' 41 | } 42 | -------------------------------------------------------------------------------- /downloader/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /downloader/src/androidTest/java/com/iqiyi/qigsaw/sample/downloader/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.downloader; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.qigsaw.sample.downloader.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /downloader/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /downloader/src/main/java/com/iqiyi/qigsaw/sample/downloader/GroupDownloadTaskQueueListener.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.downloader; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import com.liulishuo.okdownload.DownloadTask; 7 | import com.liulishuo.okdownload.core.cause.EndCause; 8 | 9 | 10 | public interface GroupDownloadTaskQueueListener { 11 | 12 | void taskEnd(@NonNull GroupDownloadContext context, @NonNull DownloadTask task, 13 | @NonNull EndCause cause, @Nullable Exception realCause, int remainCount); 14 | 15 | void queueEnd(@NonNull GroupDownloadContext context); 16 | } 17 | -------------------------------------------------------------------------------- /downloader/src/main/java/com/iqiyi/qigsaw/sample/downloader/GroupTaskDownloadCallBack.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.downloader; 2 | 3 | public interface GroupTaskDownloadCallBack { 4 | 5 | void onProgress(long currentOffset); 6 | 7 | void onStarted(); 8 | 9 | void onCompleted(); 10 | 11 | void onCanceled(); 12 | 13 | void onError(int errorCode); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /downloader/src/main/java/com/iqiyi/qigsaw/sample/downloader/OnBunchCancelListener.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.downloader; 2 | 3 | public interface OnBunchCancelListener { 4 | 5 | void onSuccess(); 6 | 7 | void onFailure(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /downloader/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | downloader 3 | 4 | -------------------------------------------------------------------------------- /downloader/src/test/java/com/iqiyi/qigsaw/sample/downloader/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.downloader; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /features/assets/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 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 | apply plugin: 'com.android.dynamic-feature' 18 | apply plugin: 'com.iqiyi.qigsaw.dynamicfeature' 19 | 20 | android { 21 | 22 | compileSdkVersion versions.compileSdk 23 | defaultConfig { 24 | minSdkVersion versions.minSdk 25 | targetSdkVersion versions.targetSdk 26 | versionCode 1 27 | versionName "1.0" 28 | } 29 | 30 | signingConfigs { 31 | debug { 32 | storeFile new File(project.rootProject.projectDir.absolutePath + "/keystore/debug.jks") 33 | storePassword "qigsawtest" 34 | keyAlias "qigsawtest" 35 | keyPassword "qigsawtest" 36 | } 37 | release { 38 | storeFile new File(project.rootProject.projectDir.absolutePath + "/keystore/release.jks") 39 | storePassword "qigsawtest" 40 | keyAlias "qigsawtest" 41 | keyPassword "qigsawtest" 42 | } 43 | } 44 | 45 | } 46 | 47 | dependencies { 48 | 49 | implementation project(':app') 50 | } 51 | -------------------------------------------------------------------------------- /features/assets/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /features/assets/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /features/assets/src/main/assets/assets.txt: -------------------------------------------------------------------------------- 1 | This text originates from a dynamically loaded feature. 2 | The source can be found in features/assets/assets/assets.txt. -------------------------------------------------------------------------------- /features/java/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.dynamic-feature' 2 | apply plugin: 'com.iqiyi.qigsaw.dynamicfeature' 3 | 4 | android { 5 | compileSdkVersion versions.compileSdk 6 | defaultConfig { 7 | minSdkVersion versions.minSdk 8 | targetSdkVersion versions.targetSdk 9 | versionCode 1 10 | versionName "1.1" 11 | } 12 | 13 | signingConfigs { 14 | debug { 15 | storeFile new File(project.rootProject.projectDir.absolutePath + "/keystore/debug.jks") 16 | storePassword "qigsawtest" 17 | keyAlias "qigsawtest" 18 | keyPassword "qigsawtest" 19 | } 20 | release { 21 | storeFile new File(project.rootProject.projectDir.absolutePath + "/keystore/release.jks") 22 | storePassword "qigsawtest" 23 | keyAlias "qigsawtest" 24 | keyPassword "qigsawtest" 25 | } 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation project(':app') 32 | } 33 | -------------------------------------------------------------------------------- /features/java/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 14 | 15 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /features/java/src/main/java/com/iqiyi/qigsaw/sample/java/JavaContentProvider.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.java; 2 | 3 | import android.content.ContentProvider; 4 | import android.content.ContentValues; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | 10 | public class JavaContentProvider extends ContentProvider { 11 | @Override 12 | public boolean onCreate() { 13 | return false; 14 | } 15 | 16 | @Nullable 17 | @Override 18 | public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { 19 | return null; 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public String getType(@NonNull Uri uri) { 25 | return null; 26 | } 27 | 28 | @Nullable 29 | @Override 30 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { 36 | return 0; 37 | } 38 | 39 | @Override 40 | public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { 41 | return 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /features/java/src/main/java/com/iqiyi/qigsaw/sample/java/JavaSampleActivity.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.java; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | public class JavaSampleActivity extends Activity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_java_sample); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /features/java/src/main/java/com/iqiyi/qigsaw/sample/java/JavaSampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.java; 2 | 3 | import android.app.Application; 4 | 5 | public class JavaSampleApplication extends Application { 6 | 7 | @Override 8 | public void onCreate() { 9 | super.onCreate(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /features/java/src/main/java/com/iqiyi/qigsaw/sample/java/JavaSampleFragment.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.java; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | import androidx.fragment.app.Fragment; 11 | 12 | public class JavaSampleFragment extends Fragment { 13 | 14 | @Nullable 15 | @Override 16 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 17 | return super.onCreateView(inflater, container, savedInstanceState); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /features/java/src/main/res/layout/activity_java_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /features/java/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | This is a dynamic feature, written in \nJava\n which can be loaded on demand. 19 | 20 | -------------------------------------------------------------------------------- /features/native/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.dynamic-feature' 2 | apply plugin: 'com.iqiyi.qigsaw.dynamicfeature' 3 | 4 | android { 5 | compileSdkVersion versions.compileSdk 6 | 7 | defaultConfig { 8 | 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | externalNativeBuild { 14 | cmake { 15 | cppFlags "-std=c++11" 16 | } 17 | } 18 | ndk { 19 | abiFilters 'arm64-v8a', 'x86' 20 | } 21 | } 22 | 23 | signingConfigs { 24 | debug { 25 | storeFile new File(project.rootProject.projectDir.absolutePath + "/keystore/debug.jks") 26 | storePassword "qigsawtest" 27 | keyAlias "qigsawtest" 28 | keyPassword "qigsawtest" 29 | } 30 | release { 31 | storeFile new File(project.rootProject.projectDir.absolutePath + "/keystore/release.jks") 32 | storePassword "qigsawtest" 33 | keyAlias "qigsawtest" 34 | keyPassword "qigsawtest" 35 | } 36 | } 37 | 38 | 39 | externalNativeBuild { 40 | cmake { 41 | path "src/main/jni/CMakeLists.txt" 42 | } 43 | } 44 | 45 | sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jni/'] } } 46 | } 47 | 48 | dependencies { 49 | implementation fileTree(dir: 'libs', include: ['*.jar']) 50 | implementation project(':app') 51 | } 52 | -------------------------------------------------------------------------------- /features/native/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /features/native/src/main/java/com/iqiyi/qigsaw/sample/ccode/NativeSampleActivity.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.sample.ccode; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.widget.TextView; 6 | 7 | import com.google.android.play.core.splitinstall.SplitInstallHelper; 8 | 9 | public class NativeSampleActivity extends Activity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_native_sample); 15 | SplitInstallHelper.loadLibrary(this, "hello-jni"); 16 | ((TextView) (findViewById(R.id.hello_textview))).setText(stringFromJNI()); 17 | } 18 | 19 | public native String stringFromJNI(); 20 | } 21 | -------------------------------------------------------------------------------- /features/native/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | add_library(hello-jni SHARED 4 | hello-jni.c) 5 | 6 | # Include libraries needed for hello-jni lib 7 | target_link_libraries(hello-jni 8 | android 9 | log) 10 | -------------------------------------------------------------------------------- /features/native/src/main/jni/hello-jni.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kissonchen on 2018/11/22. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | /* This is a trivial JNI example where we use a native method 9 | * to return a new VM String. See the corresponding Kotlin source 10 | * file located at: 11 | * 12 | * app/src/main/java/com/example/kotlin/KotlinJni.kt 13 | */ 14 | JNIEXPORT jstring JNICALL 15 | Java_com_iqiyi_qigsaw_sample_ccode_NativeSampleActivity_stringFromJNI(JNIEnv *env, 16 | jobject thiz) { 17 | #if defined(__arm__) 18 | #if defined(__ARM_ARCH_7A__) 19 | #if defined(__ARM_NEON__) 20 | #if defined(__ARM_PCS_VFP) 21 | #define ABI "armeabi-v7a/NEON (hard-float)" 22 | #else 23 | #define ABI "armeabi-v7a/NEON" 24 | #endif 25 | #else 26 | #if defined(__ARM_PCS_VFP) 27 | #define ABI "armeabi-v7a (hard-float)" 28 | #else 29 | #define ABI "armeabi-v7a" 30 | #endif 31 | #endif 32 | #else 33 | #define ABI "armeabi" 34 | #endif 35 | #elif defined(__i386__) 36 | #define ABI "x86" 37 | #elif defined(__x86_64__) 38 | #define ABI "x86_64" 39 | #elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */ 40 | #define ABI "mips64" 41 | #elif defined(__mips__) 42 | #define ABI "mips" 43 | #elif defined(__aarch64__) 44 | #define ABI "arm64-v8a" 45 | #else 46 | #define ABI "unknown" 47 | #endif 48 | 49 | return (*env)->NewStringUTF(env, "Hello from JNI!\nCompiled with ABI " ABI "."); 50 | } -------------------------------------------------------------------------------- /features/native/src/main/res/layout/activity_native_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | JAVA_VERSION=1.7 15 | AGP_VERSION=3.4.2 16 | GROUP_ID=com.iqiyi.android.qigsaw 17 | VERSION_NAME=1.4.1-hotfix01 18 | BINTRAY_REPO=maven 19 | POM_DESCRIPTION=A dynamic modularization library which is based on Android App Bundles. 20 | POM_PACKAGING=pom 21 | POM_URL=https://github.com/iqiyi/Qigsaw 22 | POM_SCM_URL=https://github.com/iqiyi/Qigsaw.git 23 | POM_SCM_CONNECTION=https://github.com/iqiyi/Qigsaw.git 24 | POM_SCM_DEV_CONNECTION=https://github.com/iqiyi/Qigsaw.git 25 | POM_LICENCE_NAME=The MIT License 26 | POM_LICENCE_URL=https://opensource.org/licenses/MIT 27 | POM_LICENCE_DIST=repo 28 | POM_DEVELOPER_ID=kissonchan 29 | POM_DEVELOPER_NAME=iQIYI, Inc. 30 | POM_DEVELOPER_EMAIL=kisson_cjw@hotmail.com 31 | BINTRAY_LICENCE='MIT' 32 | BINTRAY_ORGANIZATION=qigsaw 33 | POM_ISSUE_URL='https://github.com/iqiyi/Qigsaw/issues' 34 | android.useAndroidX=true 35 | android.enableJetifier=true -------------------------------------------------------------------------------- /gradle/android-artifacts.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven-publish' 2 | 3 | android { 4 | compileOptions { 5 | sourceCompatibility JAVA_VERSION 6 | targetCompatibility JAVA_VERSION 7 | } 8 | } 9 | 10 | task androidJavadocs(type: Javadoc) { 11 | source = android.sourceSets.main.java.sourceFiles 12 | source += files('build/generated/aidl_source_output_dir/release/compileReleaseAidl/out') 13 | android.libraryVariants.all { variant -> 14 | if (variant.name == 'release') { 15 | try { 16 | owner.classpath += variant.getJavaCompileProvider().get().classpath 17 | } catch(Exception e) { 18 | owner.classpath += variant.getJavaCompile().classpath 19 | } 20 | } 21 | } 22 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 23 | exclude '**/BuildConfig.java' 24 | exclude '**/R.java' 25 | } 26 | 27 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 28 | classifier = 'javadoc' 29 | from androidJavadocs.destinationDir 30 | } 31 | 32 | task androidSourcesJar(type: Jar) { 33 | classifier = 'sources' 34 | from android.sourceSets.main.java.sourceFiles 35 | } 36 | 37 | artifacts { 38 | archives androidSourcesJar 39 | archives androidJavadocsJar 40 | } 41 | -------------------------------------------------------------------------------- /gradle/checkStyle.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'checkstyle' 2 | 3 | checkstyle { 4 | File checkStyleFile = rootProject.file('./checkstyle.xml') 5 | if (!checkStyleFile.exists()) { 6 | checkStyleFile = rootProject.file('../checkstyle.xml') 7 | } 8 | configFile checkStyleFile 9 | toolVersion '6.19' 10 | ignoreFailures false 11 | showViolations true 12 | } 13 | 14 | task('checkstyle', type: Checkstyle) { 15 | source 'src/main/groovy' 16 | include '**/*.java','**/*.groovy' 17 | classpath = files() 18 | } 19 | -------------------------------------------------------------------------------- /gradle/java-artifacts.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven-publish' 2 | 3 | sourceCompatibility = JAVA_VERSION 4 | targetCompatibility = JAVA_VERSION 5 | 6 | task sourcesJar(type: Jar) { 7 | from sourceSets.main.java.srcDirs 8 | classifier = 'sources' 9 | } 10 | 11 | task javadocJar(type: Jar, dependsOn: javadoc) { 12 | classifier = 'javadoc' 13 | from javadoc.destinationDir 14 | } 15 | 16 | artifacts { 17 | archives javadocJar 18 | archives sourcesJar 19 | } 20 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /keystore/debug.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/keystore/debug.jks -------------------------------------------------------------------------------- /keystore/release.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/keystore/release.jks -------------------------------------------------------------------------------- /qigsaw-android-sample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | 4 | buildscript { 5 | 6 | repositories { 7 | google() 8 | jcenter() 9 | } 10 | 11 | dependencies { 12 | classpath "com.android.tools.build:gradle:${AGP_VERSION}" 13 | classpath "com.iqiyi.android.qigsaw:gradle-plugin:${VERSION_NAME}" 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | } 24 | } 25 | 26 | 27 | ext { 28 | versions = [ 29 | 'compileSdk': 29, 30 | 'minSdk' : 14, 31 | 'targetSdk' : 28, 32 | 'support' : '27.1.1' 33 | ] 34 | sample = true 35 | } 36 | 37 | task clean(type: Delete) { 38 | delete rootProject.buildDir 39 | } -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=sample-gradle-plugin 2 | POM_NAME=Qigsaw Sample Gradle Plugin 3 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/qigsaw-android-sample/buildSrc/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jul 09 23:11:03 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/sample/QigsawAppPlugin.groovy: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.buildtool.gradle.sample 2 | 3 | import com.iqiyi.qigsaw.buildtool.gradle.QigsawAppBasePlugin 4 | import com.iqiyi.qigsaw.buildtool.gradle.sample.extension.SplitUploadExtension 5 | import com.iqiyi.qigsaw.buildtool.gradle.upload.SplitApkUploaderInstance 6 | import com.iqiyi.qigsaw.buildtool.gradle.sample.upload.SampleSplitApkUploader 7 | import org.gradle.api.Project 8 | 9 | class QigsawAppPlugin extends QigsawAppBasePlugin { 10 | 11 | @Override 12 | void apply(Project project) { 13 | super.apply(project) 14 | SplitApkUploaderInstance.set(new SampleSplitApkUploader()) 15 | project.extensions.create("splitUpload", SplitUploadExtension) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/sample/extension/SplitUploadExtension.groovy: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.buildtool.gradle.sample.extension 2 | 3 | import com.google.common.collect.Lists 4 | 5 | class SplitUploadExtension { 6 | 7 | /** 8 | * Whether upload apk to test env 9 | */ 10 | boolean useTestEnv = true 11 | 12 | /** 13 | * You can decide which split apks should be upload to test env. 14 | */ 15 | List testOnly = Lists.newArrayList() 16 | 17 | void setTestOnly(List values) { 18 | testOnly.addAll(values) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/src/main/groovy/com/iqiyi/qigsaw/buildtool/gradle/sample/upload/SampleSplitApkUploader.groovy: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw.buildtool.gradle.sample.upload 2 | 3 | import com.iqiyi.qigsaw.buildtool.gradle.upload.SplitApkUploadException 4 | import com.iqiyi.qigsaw.buildtool.gradle.upload.SplitApkUploader 5 | import org.gradle.api.Project 6 | 7 | class SampleSplitApkUploader implements SplitApkUploader { 8 | 9 | @Override 10 | String uploadSync(Project appProject, File splitApk, String splitName) throws SplitApkUploadException { 11 | List testOnly = appProject.extensions.splitUpload.testOnly 12 | boolean useTestEnv = appProject.extensions.splitUpload.useTestEnv 13 | if (useTestEnv) { 14 | return uploadSplitApk(splitApk, splitName, true) 15 | } else { 16 | return uploadSplitApk(splitApk, splitName, usingTestEnvAnyWay(testOnly, splitName)) 17 | } 18 | } 19 | 20 | 21 | static boolean usingTestEnvAnyWay(List testOnly, String splitName) { 22 | return testOnly != null && testOnly.contains(splitName) 23 | } 24 | 25 | /** 26 | * Implement this method to upload split apks to your own server. 27 | */ 28 | static String uploadSplitApk(File splitApk, String splitName, boolean useTestEnv) { 29 | println("Upload split " + splitName + " split apk file path: " + splitApk + " useTestEnv: " + useTestEnv) 30 | //todo:: 31 | return null 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /qigsaw-android-sample/buildSrc/src/main/resources/META-INF/gradle-plugins/com.iqiyi.qigsaw.sample.application.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.iqiyi.qigsaw.buildtool.gradle.sample.QigsawAppPlugin -------------------------------------------------------------------------------- /qigsaw-android-sample/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | JAVA_VERSION=1.7 15 | AGP_VERSION=3.4.2 16 | GROUP_ID=com.iqiyi.android.qigsaw 17 | VERSION_NAME=1.4.1-hotfix01 18 | BINTRAY_REPO=maven 19 | POM_DESCRIPTION=A dynamic modularization library which is based on Android App Bundles. 20 | POM_PACKAGING=pom 21 | POM_URL=https://github.com/iqiyi/Qigsaw 22 | POM_SCM_URL=https://github.com/iqiyi/Qigsaw.git 23 | POM_SCM_CONNECTION=https://github.com/iqiyi/Qigsaw.git 24 | POM_SCM_DEV_CONNECTION=https://github.com/iqiyi/Qigsaw.git 25 | POM_LICENCE_NAME=The MIT License 26 | POM_LICENCE_URL=https://opensource.org/licenses/MIT 27 | POM_LICENCE_DIST=repo 28 | POM_DEVELOPER_ID=kissonchan 29 | POM_DEVELOPER_NAME=iQIYI, Inc. 30 | POM_DEVELOPER_EMAIL=kisson_cjw@hotmail.com 31 | BINTRAY_LICENCE='MIT' 32 | BINTRAY_ORGANIZATION=qigsaw 33 | POM_ISSUE_URL='https://github.com/iqiyi/Qigsaw/issues' 34 | android.useAndroidX=true 35 | android.enableJetifier=true -------------------------------------------------------------------------------- /qigsaw-android-sample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/qigsaw-android-sample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /qigsaw-android-sample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Jun 23 15:20:54 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip 7 | -------------------------------------------------------------------------------- /qigsaw-android-sample/keystore/debug.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/qigsaw-android-sample/keystore/debug.jks -------------------------------------------------------------------------------- /qigsaw-android-sample/keystore/release.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iqiyi/Qigsaw/a8414bdef99409dc0940c42f0555e5afcdd8c52f/qigsaw-android-sample/keystore/release.jks -------------------------------------------------------------------------------- /qigsaw-android-sample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':downloader' 2 | include ':assets' 3 | include ':java' 4 | include ':native' 5 | 6 | project(':app').projectDir = new File("../app") 7 | project(':downloader').projectDir = new File("../downloader") 8 | 9 | project(':assets').projectDir = new File("../features/assets") 10 | project(':java').projectDir = new File("../features/java") 11 | project(':native').projectDir = new File("../features/native") 12 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation "androidx.annotation:annotation:1.0.0" 27 | implementation project(':splitloader') 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 31 | } 32 | apply from: rootProject.file('gradle/android-artifacts.gradle') 33 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 34 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 35 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=playcorelibrary 2 | POM_NAME=A Copycat of Play Core Library 3 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/androidTest/java/com/iqiyi/qigsaw/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.qigsaw.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/binder/BinderWrapper.java: -------------------------------------------------------------------------------- 1 | package com.google.android.binder; 2 | 3 | import android.os.Binder; 4 | import android.os.IBinder; 5 | import android.os.IInterface; 6 | import android.os.Parcel; 7 | import android.os.RemoteException; 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | import androidx.annotation.RestrictTo; 11 | 12 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 13 | 14 | @RestrictTo(LIBRARY_GROUP) 15 | public class BinderWrapper extends Binder implements IInterface { 16 | 17 | private static Empty empty = null; 18 | 19 | protected BinderWrapper(String descriptor) { 20 | this.attachInterface(this, descriptor); 21 | } 22 | 23 | @Override 24 | public IBinder asBinder() { 25 | return this; 26 | } 27 | 28 | @Override 29 | protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { 30 | boolean ret; 31 | if (code > LAST_CALL_TRANSACTION) { 32 | ret = super.onTransact(code, data, reply, flags); 33 | } else { 34 | data.enforceInterface(this.getInterfaceDescriptor()); 35 | ret = false; 36 | } 37 | return ret || this.dispatchTransact(code, data); 38 | } 39 | 40 | protected boolean dispatchTransact(int code, Parcel data) { 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/binder/Empty.java: -------------------------------------------------------------------------------- 1 | package com.google.android.binder; 2 | 3 | final class Empty { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/binder/IInterfaceProxy.java: -------------------------------------------------------------------------------- 1 | package com.google.android.binder; 2 | 3 | import android.os.IBinder; 4 | import android.os.IInterface; 5 | import android.os.Parcel; 6 | import android.os.RemoteException; 7 | import androidx.annotation.RestrictTo; 8 | 9 | import static android.os.IBinder.FLAG_ONEWAY; 10 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 11 | 12 | @RestrictTo(LIBRARY_GROUP) 13 | public class IInterfaceProxy implements IInterface { 14 | 15 | private final IBinder mRemote; 16 | 17 | private final String mDescriptor; 18 | 19 | protected IInterfaceProxy(IBinder remote, String descriptor) { 20 | this.mRemote = remote; 21 | this.mDescriptor = descriptor; 22 | } 23 | 24 | @Override 25 | public IBinder asBinder() { 26 | return mRemote; 27 | } 28 | 29 | protected final Parcel obtainData() { 30 | Parcel data; 31 | (data = Parcel.obtain()).writeInterfaceToken(this.mDescriptor); 32 | return data; 33 | } 34 | 35 | protected final void transact(int code, Parcel data) throws RemoteException { 36 | Parcel reply = Parcel.obtain(); 37 | try { 38 | this.mRemote.transact(code, data, reply, FLAG_ONEWAY); 39 | reply.readException(); 40 | } finally { 41 | reply.recycle(); 42 | data.recycle(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/binder/ParcelHelper.java: -------------------------------------------------------------------------------- 1 | package com.google.android.binder; 2 | 3 | import android.os.IInterface; 4 | import android.os.Parcel; 5 | import android.os.Parcelable; 6 | import androidx.annotation.RestrictTo; 7 | 8 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 9 | 10 | @RestrictTo(LIBRARY_GROUP) 11 | public class ParcelHelper { 12 | 13 | static { 14 | ParcelHelper.class.getClassLoader(); 15 | } 16 | 17 | public static T createFromParcel(Parcel data, Parcelable.Creator creator) { 18 | return data.readInt() == 0 ? null : creator.createFromParcel(data); 19 | } 20 | 21 | public static void writeToParcel(Parcel data, Parcelable arg) { 22 | if (arg == null) { 23 | data.writeInt(0); 24 | } else { 25 | data.writeInt(1); 26 | arg.writeToParcel(data, 0); 27 | } 28 | } 29 | 30 | public static void writeStrongBinder(Parcel data, IInterface iin) { 31 | if (iin == null) { 32 | data.writeStrongBinder(null); 33 | } else { 34 | data.writeStrongBinder(iin.asBinder()); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/listener/StateUpdatedListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.listener; 2 | 3 | public interface StateUpdatedListener { 4 | 5 | /** 6 | * Callback triggered whenever the state has changed. 7 | */ 8 | void onStateUpdate(State state); 9 | } 10 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/listener/StateUpdatedReceiver.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.listener; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import androidx.annotation.RestrictTo; 7 | 8 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 9 | 10 | @RestrictTo(LIBRARY_GROUP) 11 | public class StateUpdatedReceiver extends BroadcastReceiver { 12 | 13 | private final StateUpdateListenerRegister mRegister; 14 | 15 | StateUpdatedReceiver(StateUpdateListenerRegister listenerRegister) { 16 | this.mRegister = listenerRegister; 17 | } 18 | 19 | @Override 20 | public void onReceive(Context context, Intent intent) { 21 | mRegister.onReceived(intent); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/BindServiceTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | final class BindServiceTask extends RemoteTask { 4 | 5 | private final RemoteManager remoteManager; 6 | 7 | private final RemoteTask task; 8 | 9 | BindServiceTask(RemoteManager remoteManager, RemoteTask task) { 10 | this.remoteManager = remoteManager; 11 | this.task = task; 12 | } 13 | 14 | @Override 15 | protected void execute() { 16 | remoteManager.bindServiceInternal(task); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/DeathRecipientImpl.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import android.os.IBinder; 4 | 5 | final class DeathRecipientImpl implements IBinder.DeathRecipient { 6 | 7 | private final RemoteManager mRemoteManager; 8 | 9 | DeathRecipientImpl(RemoteManager remoteManager) { 10 | this.mRemoteManager = remoteManager; 11 | } 12 | 13 | public void binderDied() { 14 | this.mRemoteManager.reportBinderDeath(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/IRemote.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import android.os.IBinder; 4 | import androidx.annotation.RestrictTo; 5 | 6 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 7 | 8 | @RestrictTo(LIBRARY_GROUP) 9 | public interface IRemote { 10 | 11 | T asInterface(IBinder remote); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/OnBinderDiedListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 6 | 7 | @RestrictTo(LIBRARY_GROUP) 8 | public interface OnBinderDiedListener { 9 | 10 | void onBinderDied(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/RemoteServiceException.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 6 | 7 | @RestrictTo(LIBRARY_GROUP) 8 | public class RemoteServiceException extends RuntimeException { 9 | 10 | public RemoteServiceException() { 11 | super("Failed to bind to the service."); 12 | } 13 | 14 | public RemoteServiceException(String str) { 15 | super(str); 16 | } 17 | 18 | public RemoteServiceException(String str, Throwable th) { 19 | super(str, th); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/RemoteTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 8 | 9 | @RestrictTo(LIBRARY_GROUP) 10 | public abstract class RemoteTask implements Runnable { 11 | 12 | private final TaskWrapper task; 13 | 14 | RemoteTask() { 15 | this.task = null; 16 | } 17 | 18 | public RemoteTask(TaskWrapper task) { 19 | this.task = task; 20 | } 21 | 22 | @Override 23 | public final void run() { 24 | try { 25 | execute(); 26 | } catch (Exception e) { 27 | e.printStackTrace(); 28 | if (this.task != null) { 29 | this.task.setException(e); 30 | } 31 | } 32 | } 33 | 34 | final TaskWrapper getTask() { 35 | return this.task; 36 | } 37 | 38 | protected abstract void execute(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/ServiceConnectedTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import android.os.IBinder; 4 | import android.os.IInterface; 5 | 6 | import java.util.List; 7 | 8 | final class ServiceConnectedTask extends RemoteTask { 9 | 10 | private final ServiceConnectionImpl mServiceConnection; 11 | 12 | private final IBinder mService; 13 | 14 | ServiceConnectedTask(ServiceConnectionImpl serviceConnection, IBinder service) { 15 | this.mServiceConnection = serviceConnection; 16 | this.mService = service; 17 | } 18 | 19 | @Override 20 | protected void execute() { 21 | this.mServiceConnection.mRemoteManager.mIInterface = (IInterface) mServiceConnection.mRemoteManager.mRemote.asInterface(mService); 22 | this.mServiceConnection.mRemoteManager.linkToDeath(); 23 | this.mServiceConnection.mRemoteManager.mBindingService = false; 24 | List remoteTasks = mServiceConnection.mRemoteManager.mPendingTasks; 25 | for (Runnable run : remoteTasks) { 26 | run.run(); 27 | } 28 | mServiceConnection.mRemoteManager.mPendingTasks.clear(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/ServiceConnectionImpl.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | import android.content.ComponentName; 4 | import android.content.ServiceConnection; 5 | import android.os.IBinder; 6 | 7 | final class ServiceConnectionImpl implements ServiceConnection { 8 | 9 | final RemoteManager mRemoteManager; 10 | 11 | ServiceConnectionImpl(RemoteManager remoteManager) { 12 | this.mRemoteManager = remoteManager; 13 | } 14 | 15 | @Override 16 | public void onServiceConnected(ComponentName name, IBinder service) { 17 | mRemoteManager.mPlayCore.info("ServiceConnectionImpl.onServiceConnected(%s)", name); 18 | mRemoteManager.post(new ServiceConnectedTask(this, service)); 19 | } 20 | 21 | @Override 22 | public void onServiceDisconnected(ComponentName name) { 23 | mRemoteManager.mPlayCore.info("ServiceConnectionImpl.onServiceDisconnected(%s)", name); 24 | mRemoteManager.post(new ServiceDisconnectedTask(this)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/ServiceDisconnectedTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | final class ServiceDisconnectedTask extends RemoteTask { 4 | 5 | private final ServiceConnectionImpl mServiceConnection; 6 | 7 | ServiceDisconnectedTask(ServiceConnectionImpl serviceConnection) { 8 | this.mServiceConnection = serviceConnection; 9 | } 10 | 11 | @Override 12 | protected void execute() { 13 | mServiceConnection.mRemoteManager.unlinkToDeath(); 14 | mServiceConnection.mRemoteManager.mIInterface = null; 15 | mServiceConnection.mRemoteManager.mBindingService = false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/remote/UnbindServiceTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.remote; 2 | 3 | final class UnbindServiceTask extends RemoteTask { 4 | 5 | private final RemoteManager mRemoteManager; 6 | 7 | UnbindServiceTask(RemoteManager remoteManager) { 8 | this.mRemoteManager = remoteManager; 9 | } 10 | 11 | @Override 12 | protected void execute() { 13 | if (this.mRemoteManager.mIInterface != null) { 14 | this.mRemoteManager.mContext.unbindService(this.mRemoteManager.mServiceConnection); 15 | this.mRemoteManager.mBindingService = false; 16 | this.mRemoteManager.mIInterface = null; 17 | this.mRemoteManager.mServiceConnection = null; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitcompat/LoadedSplitFetcherImpl.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitcompat; 2 | 3 | import com.google.android.play.core.splitinstall.LoadedSplitFetcher; 4 | 5 | import java.util.Set; 6 | 7 | final class LoadedSplitFetcherImpl implements LoadedSplitFetcher { 8 | 9 | private final SplitCompat mSplitCompat; 10 | 11 | LoadedSplitFetcherImpl(SplitCompat splitCompat) { 12 | this.mSplitCompat = splitCompat; 13 | } 14 | 15 | @Override 16 | public Set loadedSplits() { 17 | return mSplitCompat.getLoadedSplits(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitcompat/SplitCompat.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitcompat; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.android.play.core.splitinstall.LoadedSplitFetcherSingleton; 6 | import com.google.android.play.core.splitinstall.SplitSessionLoaderSingleton; 7 | import com.google.android.play.core.tasks.TaskExecutors; 8 | import com.iqiyi.android.qigsaw.core.splitload.SplitLoadManager; 9 | import com.iqiyi.android.qigsaw.core.splitload.SplitLoadManagerService; 10 | 11 | import java.util.Set; 12 | import java.util.concurrent.atomic.AtomicReference; 13 | 14 | public class SplitCompat { 15 | 16 | private static final AtomicReference sSplitCompatReference = new AtomicReference<>(null); 17 | 18 | private SplitCompat() { 19 | 20 | } 21 | 22 | public static boolean install(Context context) { 23 | return installInternal(context); 24 | } 25 | 26 | @SuppressWarnings("unused") 27 | private static boolean installInternal(final Context context) { 28 | if (sSplitCompatReference.compareAndSet(null, new SplitCompat())) { 29 | final SplitCompat compat = sSplitCompatReference.get(); 30 | SplitSessionLoaderSingleton.set(new SplitSessionLoaderImpl(TaskExecutors.MAIN_THREAD)); 31 | LoadedSplitFetcherSingleton.set(new LoadedSplitFetcherImpl(compat)); 32 | } 33 | return true; 34 | } 35 | 36 | static boolean hasInstance() { 37 | return sSplitCompatReference.get() != null; 38 | } 39 | 40 | final Set getLoadedSplits() { 41 | SplitLoadManager loadManager = SplitLoadManagerService.getInstance(); 42 | return loadManager.getLoadedSplitNames(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitcompat/SplitCompatApplication.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitcompat; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | public abstract class SplitCompatApplication extends Application { 7 | 8 | @Override 9 | protected void attachBaseContext(Context base) { 10 | super.attachBaseContext(base); 11 | SplitCompat.install(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitcompat/SplitSessionLoaderImpl.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitcompat; 2 | 3 | import android.content.Intent; 4 | 5 | import com.google.android.play.core.splitinstall.SplitSessionLoader; 6 | import com.google.android.play.core.splitinstall.SplitSessionStatusChanger; 7 | 8 | import java.util.List; 9 | import java.util.concurrent.Executor; 10 | 11 | final class SplitSessionLoaderImpl implements SplitSessionLoader { 12 | 13 | private final Executor mExecutor; 14 | 15 | SplitSessionLoaderImpl(Executor executor) { 16 | this.mExecutor = executor; 17 | } 18 | 19 | @Override 20 | public void load(List splitFileIntents, SplitSessionStatusChanger changer) { 21 | if (!SplitCompat.hasInstance()) { 22 | throw new IllegalStateException("Ingestion should only be called in SplitCompat mode."); 23 | } else { 24 | this.mExecutor.execute(new SplitLoadSessionTask(splitFileIntents, changer)); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/CancelInstallCallback.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | final class CancelInstallCallback extends SplitInstallServiceCallbackImpl { 8 | 9 | CancelInstallCallback(SplitInstallService splitInstallService, TaskWrapper task) { 10 | super(splitInstallService, task); 11 | } 12 | 13 | @Override 14 | public void onCancelInstall(int sessionId, Bundle data) { 15 | super.onCancelInstall(sessionId, data); 16 | mTask.setResult(null); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/CancelInstallTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.RemoteException; 4 | 5 | import com.google.android.play.core.remote.RemoteTask; 6 | import com.google.android.play.core.tasks.TaskWrapper; 7 | 8 | final class CancelInstallTask extends RemoteTask { 9 | 10 | private final SplitInstallService mSplitInstallService; 11 | 12 | private final TaskWrapper mTask; 13 | 14 | private final int sessionId; 15 | 16 | CancelInstallTask(SplitInstallService installService, TaskWrapper task, int sessionId, TaskWrapper taskSame) { 17 | super(taskSame); 18 | this.mSplitInstallService = installService; 19 | this.mTask = task; 20 | this.sessionId = sessionId; 21 | } 22 | 23 | @Override 24 | protected void execute() { 25 | try { 26 | mSplitInstallService.mSplitRemoteManager.getIInterface().cancelInstall( 27 | this.mSplitInstallService.mPackageName, 28 | sessionId, 29 | SplitInstallService.wrapVersionCode(), 30 | new CancelInstallCallback(mSplitInstallService, mTask) 31 | ); 32 | } catch (RemoteException e) { 33 | SplitInstallService.playCore.error(e, "cancelInstall(%d)", this.sessionId); 34 | this.mTask.setException(new RuntimeException(e)); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/ChangeSessionStatusWorker.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | final class ChangeSessionStatusWorker implements Runnable { 4 | 5 | private final SplitSessionStatusChanger changer; 6 | 7 | private final int status; 8 | 9 | private final int errorCode; 10 | 11 | ChangeSessionStatusWorker(SplitSessionStatusChanger changer, int status) { 12 | this(changer, status, 0); 13 | } 14 | 15 | ChangeSessionStatusWorker(SplitSessionStatusChanger changer, int status, int errorCode) { 16 | this.changer = changer; 17 | this.status = status; 18 | this.errorCode = errorCode; 19 | } 20 | 21 | @Override 22 | public void run() { 23 | if (errorCode != 0) { 24 | changer.mRegistry.notifyListeners(changer.sessionState.a(status, errorCode)); 25 | } else { 26 | changer.mRegistry.notifyListeners(changer.sessionState.a(status)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/DeferredInstallCallback.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | final class DeferredInstallCallback extends SplitInstallServiceCallbackImpl { 8 | 9 | DeferredInstallCallback(SplitInstallService splitInstallService, TaskWrapper task) { 10 | super(splitInstallService, task); 11 | } 12 | 13 | @Override 14 | public void onDeferredInstall(Bundle data) { 15 | super.onDeferredInstall(data); 16 | mTask.setResult(null); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/DeferredInstallTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | 4 | import android.os.RemoteException; 5 | 6 | import com.google.android.play.core.remote.RemoteTask; 7 | import com.google.android.play.core.tasks.TaskWrapper; 8 | 9 | import java.util.List; 10 | 11 | final class DeferredInstallTask extends RemoteTask { 12 | 13 | private final SplitInstallService mSplitInstallService; 14 | 15 | private final TaskWrapper mTask; 16 | 17 | private final List moduleNames; 18 | 19 | DeferredInstallTask(SplitInstallService installService, TaskWrapper task, List moduleNames, TaskWrapper taskSame) { 20 | super(task); 21 | this.mSplitInstallService = installService; 22 | this.moduleNames = moduleNames; 23 | this.mTask = taskSame; 24 | } 25 | 26 | @Override 27 | protected void execute() { 28 | try { 29 | mSplitInstallService.mSplitRemoteManager.getIInterface().deferredInstall( 30 | this.mSplitInstallService.mPackageName, 31 | SplitInstallService.wrapModuleNames(moduleNames), 32 | SplitInstallService.wrapVersionCode(), 33 | new DeferredInstallCallback(mSplitInstallService, mTask) 34 | ); 35 | } catch (RemoteException e) { 36 | SplitInstallService.playCore.error(e, "deferredInstall(%s)", this.moduleNames); 37 | this.mTask.setException(new RuntimeException(e)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/DeferredUninstallCallback.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | final class DeferredUninstallCallback extends SplitInstallServiceCallbackImpl { 8 | 9 | DeferredUninstallCallback(SplitInstallService splitInstallService, TaskWrapper task) { 10 | super(splitInstallService, task); 11 | } 12 | 13 | @Override 14 | public void onDeferredUninstall(Bundle data) { 15 | super.onDeferredUninstall(data); 16 | mTask.setResult(null); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/DeferredUninstallTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.RemoteException; 4 | 5 | import com.google.android.play.core.remote.RemoteTask; 6 | import com.google.android.play.core.tasks.TaskWrapper; 7 | 8 | import java.util.List; 9 | 10 | final class DeferredUninstallTask extends RemoteTask { 11 | 12 | private final SplitInstallService mSplitInstallService; 13 | 14 | private final TaskWrapper mTask; 15 | 16 | private final List moduleNames; 17 | 18 | DeferredUninstallTask(SplitInstallService installService, TaskWrapper task, List moduleNames, TaskWrapper taskSame) { 19 | super(task); 20 | this.mSplitInstallService = installService; 21 | this.moduleNames = moduleNames; 22 | this.mTask = taskSame; 23 | } 24 | 25 | @Override 26 | protected void execute() { 27 | try { 28 | mSplitInstallService.mSplitRemoteManager.getIInterface().deferredUninstall( 29 | this.mSplitInstallService.mPackageName, 30 | SplitInstallService.wrapModuleNames(moduleNames), 31 | SplitInstallService.wrapVersionCode(), 32 | new DeferredUninstallCallback(mSplitInstallService, mTask) 33 | ); 34 | } catch (RemoteException e) { 35 | SplitInstallService.playCore.error(e, "deferredUninstall(%s)", this.moduleNames); 36 | this.mTask.setException(new RuntimeException(e)); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/GetSessionStateCallback.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | final class GetSessionStateCallback extends SplitInstallServiceCallbackImpl { 8 | 9 | GetSessionStateCallback(SplitInstallService splitInstallService, TaskWrapper task) { 10 | super(splitInstallService, task); 11 | } 12 | 13 | @Override 14 | public void onGetSession(int sessionId, Bundle data) { 15 | super.onGetSession(sessionId, data); 16 | mTask.setResult(SplitInstallSessionState.createFrom(data)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/GetSessionStateTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.RemoteException; 4 | 5 | import com.google.android.play.core.remote.RemoteTask; 6 | import com.google.android.play.core.tasks.TaskWrapper; 7 | 8 | final class GetSessionStateTask extends RemoteTask { 9 | 10 | private final SplitInstallService mSplitInstallService; 11 | 12 | private final TaskWrapper mTask; 13 | 14 | private final int sessionId; 15 | 16 | GetSessionStateTask(SplitInstallService installService, TaskWrapper task, int sessionId, TaskWrapper taskSame) { 17 | super(task); 18 | this.mSplitInstallService = installService; 19 | this.sessionId = sessionId; 20 | this.mTask = taskSame; 21 | } 22 | 23 | @Override 24 | protected void execute() { 25 | try { 26 | mSplitInstallService.mSplitRemoteManager.getIInterface().getSessionState( 27 | this.mSplitInstallService.mPackageName, 28 | sessionId, 29 | new GetSessionStateCallback(mSplitInstallService, mTask) 30 | ); 31 | } catch (RemoteException e) { 32 | SplitInstallService.playCore.error(e, "getSessionState(%d)", this.sessionId); 33 | this.mTask.setException(new RuntimeException(e)); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/GetSessionStatesCallback.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | final class GetSessionStatesCallback extends SplitInstallServiceCallbackImpl> { 11 | 12 | GetSessionStatesCallback(SplitInstallService splitInstallService, TaskWrapper> task) { 13 | super(splitInstallService, task); 14 | } 15 | 16 | @Override 17 | public void onGetSessionStates(List data) { 18 | super.onGetSessionStates(data); 19 | List sessionStates = new ArrayList<>(data.size()); 20 | for (Bundle bundle : data) { 21 | sessionStates.add(SplitInstallSessionState.createFrom(bundle)); 22 | } 23 | mTask.setResult(sessionStates); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/GetSessionStatesTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.RemoteException; 4 | 5 | import com.google.android.play.core.remote.RemoteTask; 6 | import com.google.android.play.core.tasks.TaskWrapper; 7 | 8 | import java.util.List; 9 | 10 | final class GetSessionStatesTask extends RemoteTask { 11 | 12 | private final SplitInstallService mSplitInstallService; 13 | 14 | private final TaskWrapper> mTask; 15 | 16 | GetSessionStatesTask(SplitInstallService installService, TaskWrapper task, TaskWrapper> taskSame) { 17 | super(task); 18 | this.mSplitInstallService = installService; 19 | this.mTask = taskSame; 20 | } 21 | 22 | @Override 23 | protected void execute() { 24 | try { 25 | mSplitInstallService.mSplitRemoteManager.getIInterface().getSessionStates( 26 | this.mSplitInstallService.mPackageName, 27 | new GetSessionStatesCallback(mSplitInstallService, mTask) 28 | ); 29 | } catch (RemoteException e) { 30 | SplitInstallService.playCore.error(e, "getSessionStates"); 31 | this.mTask.setException(new RuntimeException(e)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/LoadedSplitFetcher.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import java.util.Set; 6 | 7 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 8 | 9 | @RestrictTo(LIBRARY_GROUP) 10 | public interface LoadedSplitFetcher { 11 | 12 | Set loadedSplits(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/LoadedSplitFetcherSingleton.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 8 | 9 | @RestrictTo(LIBRARY_GROUP) 10 | public final class LoadedSplitFetcherSingleton { 11 | 12 | private static final AtomicReference sInstalledSplitsFetcherRef = new AtomicReference<>(null); 13 | 14 | static LoadedSplitFetcher get() { 15 | return sInstalledSplitsFetcherRef.get(); 16 | } 17 | 18 | public static void set(LoadedSplitFetcher fetcher) { 19 | sInstalledSplitsFetcherRef.compareAndSet(null, fetcher); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/OnBinderDiedListenerImpl.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import com.google.android.play.core.remote.OnBinderDiedListener; 4 | 5 | final class OnBinderDiedListenerImpl implements OnBinderDiedListener { 6 | 7 | private final SplitInstallService mSplitInstallService; 8 | 9 | OnBinderDiedListenerImpl(SplitInstallService splitInstallService) { 10 | this.mSplitInstallService = splitInstallService; 11 | } 12 | 13 | @Override 14 | public void onBinderDied() { 15 | mSplitInstallService.onBinderDied(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitInstallException.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | public class SplitInstallException extends RuntimeException { 4 | 5 | private final int errorCode; 6 | 7 | SplitInstallException(int errorCode) { 8 | super((new StringBuilder(32)).append("Split Install Error: ").append(errorCode).toString()); 9 | this.errorCode = errorCode; 10 | } 11 | 12 | public int getErrorCode() { 13 | return this.errorCode; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitInstallListenerRegistry.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.IntentFilter; 6 | import android.os.Handler; 7 | import android.os.Looper; 8 | 9 | import com.google.android.play.core.listener.StateUpdateListenerRegister; 10 | import com.google.android.play.core.splitcompat.util.PlayCore; 11 | 12 | final class SplitInstallListenerRegistry extends StateUpdateListenerRegister { 13 | 14 | final Handler mMainHandler; 15 | 16 | private final SplitSessionLoader mLoader; 17 | 18 | SplitInstallListenerRegistry(Context context) { 19 | this(context, SplitSessionLoaderSingleton.get()); 20 | } 21 | 22 | private SplitInstallListenerRegistry(Context context, SplitSessionLoader loader) { 23 | super(new PlayCore("SplitInstallListenerRegistry"), new IntentFilter("com.iqiyi.android.play.core.splitinstall.receiver.SplitInstallUpdateIntentService"), context); 24 | this.mMainHandler = new Handler(Looper.getMainLooper()); 25 | this.mLoader = loader; 26 | } 27 | 28 | @Override 29 | protected void onReceived(Intent intent) { 30 | SplitInstallSessionState sessionState = SplitInstallSessionState.createFrom(intent.getBundleExtra("session_state")); 31 | this.playCore.info("ListenerRegistryBroadcastReceiver.onReceive: %s", sessionState); 32 | if (sessionState.status() == 10 && mLoader != null) { 33 | mLoader.load(sessionState.splitFileIntents, new SplitSessionStatusChanger(this, sessionState)); 34 | } else { 35 | notifyListeners(sessionState); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitInstallManagerFactory.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.content.Context; 4 | 5 | public class SplitInstallManagerFactory { 6 | 7 | public SplitInstallManagerFactory() { 8 | 9 | } 10 | 11 | /** 12 | * Creates an instance of {@link SplitInstallManager}. 13 | */ 14 | public static SplitInstallManager create(Context context) { 15 | return new SplitInstallManagerImpl(new SplitInstallService(context), context); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitInstallRequest.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class SplitInstallRequest { 7 | 8 | private final List moduleNames; 9 | 10 | public static SplitInstallRequest.Builder newBuilder() { 11 | return new SplitInstallRequest.Builder(); 12 | } 13 | 14 | private SplitInstallRequest(Builder builder) { 15 | this.moduleNames = new ArrayList<>(builder.moduleNames); 16 | } 17 | 18 | /** 19 | * Get requested modules. 20 | */ 21 | public List getModuleNames() { 22 | return moduleNames; 23 | } 24 | 25 | public String toString() { 26 | String var1 = String.valueOf(this.moduleNames); 27 | return (new StringBuilder(34 + String.valueOf(var1).length())).append("SplitInstallRequest{modulesNames=").append(var1).append("}").toString(); 28 | } 29 | 30 | /** 31 | * A builder for a request to install some splits. 32 | */ 33 | public static class Builder { 34 | 35 | private final List moduleNames; 36 | 37 | private Builder() { 38 | this.moduleNames = new ArrayList<>(); 39 | } 40 | 41 | public Builder addModule(String moduleName) { 42 | this.moduleNames.add(moduleName); 43 | return this; 44 | } 45 | 46 | public SplitInstallRequest build() { 47 | return new SplitInstallRequest(this); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitInstallStateUpdatedListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | 4 | import com.google.android.play.core.listener.StateUpdatedListener; 5 | 6 | public interface SplitInstallStateUpdatedListener extends StateUpdatedListener { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitInstalledDisposer.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | 10 | final class SplitInstalledDisposer implements Runnable { 11 | 12 | private final SplitInstallManagerImpl splitInstallManager; 13 | 14 | private final SplitInstallRequest splitInstallRequest; 15 | 16 | SplitInstalledDisposer(SplitInstallManagerImpl splitInstallManager, 17 | SplitInstallRequest request) { 18 | this.splitInstallManager = splitInstallManager; 19 | this.splitInstallRequest = request; 20 | } 21 | 22 | @Override 23 | public void run() { 24 | this.splitInstallManager.getRegistry().notifyListeners( 25 | SplitInstallSessionState.createFrom(makeInstalledSessionState(this.splitInstallRequest.getModuleNames().toArray(new String[0]))) 26 | ); 27 | } 28 | 29 | private Bundle makeInstalledSessionState(String[] modulesNames) { 30 | Bundle bundle; 31 | (bundle = new Bundle()).putInt("session_id", 0); 32 | bundle.putInt("status", SplitInstallSessionStatus.INSTALLED); 33 | bundle.putInt("error_code", 0); 34 | bundle.putStringArrayList("module_names", new ArrayList<>(Arrays.asList(modulesNames))); 35 | bundle.putLong("total_bytes_to_download", 0L); 36 | bundle.putLong("bytes_downloaded", 0L); 37 | return bundle; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitRemoteImpl.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.IBinder; 4 | import androidx.annotation.RestrictTo; 5 | 6 | import com.google.android.play.core.remote.IRemote; 7 | import com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceHolder; 8 | import com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceProxy; 9 | 10 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 11 | 12 | @RestrictTo(LIBRARY_GROUP) 13 | public class SplitRemoteImpl implements IRemote { 14 | 15 | static final IRemote sInstance = new SplitRemoteImpl(); 16 | 17 | @Override 18 | public ISplitInstallServiceProxy asInterface(IBinder remote) { 19 | return ISplitInstallServiceHolder.queryLocalInterface(remote); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitSessionLoader.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.content.Intent; 4 | import androidx.annotation.RestrictTo; 5 | 6 | import java.util.List; 7 | 8 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 9 | 10 | @RestrictTo(LIBRARY_GROUP) 11 | public interface SplitSessionLoader { 12 | 13 | void load(List splitFileIntents, SplitSessionStatusChanger changer); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitSessionLoaderSingleton.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 8 | 9 | @RestrictTo(LIBRARY_GROUP) 10 | public final class SplitSessionLoaderSingleton { 11 | 12 | private static final AtomicReference sSplitLoaderHolder = new AtomicReference<>(); 13 | 14 | static SplitSessionLoader get() { 15 | return sSplitLoaderHolder.get(); 16 | } 17 | 18 | public static void set(SplitSessionLoader loader) { 19 | sSplitLoaderHolder.compareAndSet(null, loader); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/SplitSessionStatusChanger.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 6 | 7 | @RestrictTo(LIBRARY_GROUP) 8 | public class SplitSessionStatusChanger { 9 | 10 | final SplitInstallListenerRegistry mRegistry; 11 | 12 | final SplitInstallSessionState sessionState; 13 | 14 | SplitSessionStatusChanger(SplitInstallListenerRegistry registry, SplitInstallSessionState sessionState) { 15 | this.mRegistry = registry; 16 | this.sessionState = sessionState; 17 | } 18 | 19 | public void changeStatus(int status) { 20 | mRegistry.mMainHandler.post(new ChangeSessionStatusWorker(this, status)); 21 | } 22 | 23 | public void changeStatus(int status, int errorCode) { 24 | mRegistry.mMainHandler.post(new ChangeSessionStatusWorker(this, status, errorCode)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/StartInstallCallback.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.google.android.play.core.tasks.TaskWrapper; 6 | 7 | final class StartInstallCallback extends SplitInstallServiceCallbackImpl { 8 | 9 | StartInstallCallback(SplitInstallService splitInstallService, TaskWrapper task) { 10 | super(splitInstallService, task); 11 | } 12 | 13 | @Override 14 | public void onStartInstall(int sessionId, Bundle sessionStateBundle) { 15 | super.onStartInstall(sessionId, sessionStateBundle); 16 | mTask.setResult(sessionId); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/StartInstallTask.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall; 2 | 3 | import android.os.RemoteException; 4 | 5 | import com.google.android.play.core.remote.RemoteTask; 6 | import com.google.android.play.core.tasks.TaskWrapper; 7 | 8 | import java.util.List; 9 | 10 | final class StartInstallTask extends RemoteTask { 11 | 12 | private final SplitInstallService mSplitInstallService; 13 | 14 | private final TaskWrapper mTask; 15 | 16 | private final List moduleNames; 17 | 18 | StartInstallTask(SplitInstallService installService, TaskWrapper task, List moduleNames, TaskWrapper taskSame) { 19 | super(task); 20 | this.mSplitInstallService = installService; 21 | this.moduleNames = moduleNames; 22 | this.mTask = taskSame; 23 | } 24 | 25 | @Override 26 | protected void execute() { 27 | try { 28 | mSplitInstallService.mSplitRemoteManager.getIInterface().startInstall( 29 | this.mSplitInstallService.mPackageName, 30 | SplitInstallService.wrapModuleNames(moduleNames), 31 | SplitInstallService.wrapVersionCode(), 32 | new StartInstallCallback(mSplitInstallService, mTask) 33 | ); 34 | } catch (RemoteException e) { 35 | SplitInstallService.playCore.error(e, "startInstall(%s)", this.moduleNames); 36 | this.mTask.setException(new RuntimeException(e)); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/model/SplitInstallErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall.model; 2 | 3 | public @interface SplitInstallErrorCode { 4 | 5 | int NO_ERROR = 0; 6 | /** 7 | * Too many sessions are running for current app, existing sessions must be resolved first. 8 | */ 9 | int ACTIVE_SESSIONS_LIMIT_EXCEEDED = -1; 10 | /** 11 | * A requested module is not available (to this user/device, for the installed apk). 12 | */ 13 | int MODULE_UNAVAILABLE = -2; 14 | /** 15 | * Request is otherwise invalid. 16 | */ 17 | int INVALID_REQUEST = -3; 18 | /** 19 | * Requested session is not found. 20 | */ 21 | int SESSION_NOT_FOUND = -4; 22 | /** 23 | * Split Install API is not available. 24 | */ 25 | int API_NOT_AVAILABLE = -5; 26 | /** 27 | * Network error: unable to obtain split details 28 | */ 29 | int NETWORK_ERROR = -6; 30 | /** 31 | * Download not permitted under current device circumstances (e.g. in background) 32 | */ 33 | int ACCESS_DENIED = -7; 34 | /** 35 | * Requested session contains modules from an existing active session and also new modules. 36 | */ 37 | int INCOMPATIBLE_WITH_EXISTING_SESSION = -8; 38 | /** 39 | * Service handling split install has died. 40 | * This error code will be sent with session id = -1 and failed session status when the service handling split install has died. Upon receiving this error code the app should retry the request. 41 | */ 42 | int SERVICE_DIED = -9; 43 | /** 44 | * Unknown error processing split install. 45 | */ 46 | int INTERNAL_ERROR = -100; 47 | } 48 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/model/SplitInstallSessionStatus.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall.model; 2 | 3 | public @interface SplitInstallSessionStatus { 4 | int UNKNOWN = 0; 5 | /** 6 | * The download is pending and will be processed soon. 7 | */ 8 | int PENDING = 1; 9 | /** 10 | * The download requires user confirmation. 11 | */ 12 | int REQUIRES_USER_CONFIRMATION = 8; 13 | /** 14 | * The split download is in progress. 15 | */ 16 | int DOWNLOADING = 2; 17 | /** 18 | * The split is downloaded but not yet installed. 19 | */ 20 | int DOWNLOADED = 3; 21 | /** 22 | * The splits are being installed. 23 | */ 24 | int INSTALLING = 4; 25 | /** 26 | * Installation is complete; the splits are available to the client app. 27 | */ 28 | int INSTALLED = 5; 29 | /** 30 | * Split download or installation has failed. 31 | */ 32 | int FAILED = 6; 33 | /** 34 | * The split download is being cancelled. 35 | */ 36 | int CANCELING = 9; 37 | /** 38 | * The split download has been cancelled. 39 | */ 40 | int CANCELED = 7; 41 | } 42 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceCallbackProxy.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall.protocol; 2 | 3 | import android.os.Bundle; 4 | import android.os.IInterface; 5 | import androidx.annotation.RestrictTo; 6 | 7 | import java.util.List; 8 | 9 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 10 | 11 | @RestrictTo(LIBRARY_GROUP) 12 | public interface ISplitInstallServiceCallbackProxy extends IInterface { 13 | 14 | void onStartInstall(int sessionId, Bundle data); 15 | 16 | void onCompleteInstall(int sessionId); 17 | 18 | void onCancelInstall(int sessionId, Bundle data); 19 | 20 | void onGetSession(int sessionId, Bundle data); 21 | 22 | void onDeferredUninstall(Bundle data); 23 | 24 | void onDeferredInstall(Bundle data); 25 | 26 | void onGetSessionStates(List data); 27 | 28 | void onError(Bundle data); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceHolder.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall.protocol; 2 | 3 | import android.os.IBinder; 4 | import android.os.IInterface; 5 | import androidx.annotation.RestrictTo; 6 | 7 | import com.google.android.binder.BinderWrapper; 8 | 9 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 10 | 11 | @RestrictTo(LIBRARY_GROUP) 12 | public abstract class ISplitInstallServiceHolder extends BinderWrapper implements ISplitInstallServiceProxy { 13 | 14 | protected ISplitInstallServiceHolder(String descriptor) { 15 | super(descriptor); 16 | } 17 | 18 | public static ISplitInstallServiceProxy queryLocalInterface(IBinder remote) { 19 | if (remote == null) { 20 | return null; 21 | } else { 22 | IInterface iin; 23 | return ((iin = remote.queryLocalInterface("com.iqiyi.android.qigsaw.core.splitinstall.protocol.ISplitInstallService")) instanceof ISplitInstallServiceProxy ? (ISplitInstallServiceProxy) iin : new ISplitInstallServiceImpl(remote)); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceProxy.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.splitinstall.protocol; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.os.IInterface; 6 | import android.os.RemoteException; 7 | import androidx.annotation.RestrictTo; 8 | 9 | import java.util.List; 10 | 11 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 12 | 13 | @RestrictTo(LIBRARY_GROUP) 14 | public interface ISplitInstallServiceProxy extends IInterface { 15 | 16 | void startInstall(String packageName, List moduleNames, Bundle versionCode, ISplitInstallServiceCallbackProxy callback) throws RemoteException; 17 | 18 | void cancelInstall(String packageName, int sessionId, Bundle versionCode, ISplitInstallServiceCallbackProxy callback) throws RemoteException; 19 | 20 | void getSessionState(String packageName, int sessionId, ISplitInstallServiceCallbackProxy callback) throws RemoteException; 21 | 22 | void getSessionStates(String packageName, ISplitInstallServiceCallbackProxy callback) throws RemoteException; 23 | 24 | void deferredInstall(String packageName, List moduleNames, Bundle versionCode, ISplitInstallServiceCallbackProxy callback) throws RemoteException; 25 | 26 | void deferredUninstall(String packageName, List moduleNames, Bundle versionCode, ISplitInstallServiceCallbackProxy callback) throws RemoteException; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/InvocationListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | interface InvocationListener { 4 | 5 | void invoke(Task task); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/InvocationListenerManager.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Queue; 5 | 6 | final class InvocationListenerManager { 7 | 8 | private final Object lock = new Object(); 9 | 10 | private Queue> mInvocationListenerQueue; 11 | 12 | private boolean invoked; 13 | 14 | void addInvocationListener(InvocationListener invocationListener) { 15 | synchronized (lock) { 16 | if (mInvocationListenerQueue == null) { 17 | mInvocationListenerQueue = new ArrayDeque<>(); 18 | } 19 | mInvocationListenerQueue.add(invocationListener); 20 | } 21 | } 22 | 23 | void invokeListener(Task task) { 24 | synchronized (lock) { 25 | if (mInvocationListenerQueue == null || invoked) { 26 | return; 27 | } 28 | invoked = true; 29 | } 30 | while (true) { 31 | InvocationListener invocationListener; 32 | synchronized (lock) { 33 | invocationListener = mInvocationListenerQueue.poll(); 34 | if (invocationListener == null) { 35 | invoked = false; 36 | return; 37 | } 38 | } 39 | invocationListener.invoke(task); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/InvokeCompleteListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | class InvokeCompleteListener implements InvocationListener { 6 | 7 | private final Executor mExecutor; 8 | 9 | final Object lock = new Object(); 10 | 11 | final OnCompleteListener mListener; 12 | 13 | InvokeCompleteListener(Executor executor, OnCompleteListener listener) { 14 | this.mExecutor = executor; 15 | this.mListener = listener; 16 | } 17 | 18 | @Override 19 | public void invoke(Task task) { 20 | synchronized (lock) { 21 | if (mListener == null) { 22 | return; 23 | } 24 | } 25 | mExecutor.execute(new TaskCompleteRunnable(this, task)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/InvokeFailureListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | class InvokeFailureListener implements InvocationListener { 6 | 7 | private final Executor mExecutor; 8 | 9 | final Object lock = new Object(); 10 | 11 | final OnFailureListener mListener; 12 | 13 | InvokeFailureListener(Executor executor, OnFailureListener listener) { 14 | this.mExecutor = executor; 15 | this.mListener = listener; 16 | } 17 | 18 | @Override 19 | public void invoke(Task task) { 20 | if (!task.isSuccessful()) { 21 | synchronized (lock) { 22 | if (mListener == null) { 23 | return; 24 | } 25 | } 26 | mExecutor.execute(new TaskFailureRunnable(this, task)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/InvokeSuccessListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | final class InvokeSuccessListener implements InvocationListener { 6 | 7 | private final Executor mExecutor; 8 | 9 | final Object lock = new Object(); 10 | 11 | final OnSuccessListener mListener; 12 | 13 | InvokeSuccessListener(Executor executor, OnSuccessListener listener) { 14 | this.mExecutor = executor; 15 | this.mListener = listener; 16 | } 17 | 18 | @Override 19 | public void invoke(Task task) { 20 | if (task.isSuccessful()) { 21 | synchronized (lock) { 22 | if (mListener == null) { 23 | return; 24 | } 25 | } 26 | mExecutor.execute(new TaskSuccessRunnable(this, task)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/OnCompleteListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | public interface OnCompleteListener { 4 | 5 | /** 6 | * Called when the Task completes. 7 | */ 8 | void onComplete(Task task); 9 | } 10 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/OnFailureListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | public interface OnFailureListener { 4 | 5 | /** 6 | * Called when the Task fails with an exception. 7 | */ 8 | void onFailure(Exception e); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/OnSuccessListener.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | public interface OnSuccessListener { 4 | 5 | /** 6 | * Called when the Task completes successfully. 7 | */ 8 | void onSuccess(TResult result); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/RuntimeExecutionException.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | public class RuntimeExecutionException extends RuntimeException { 4 | 5 | RuntimeExecutionException(Throwable th) { 6 | super(th); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/TaskCompleteRunnable.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | final class TaskCompleteRunnable implements Runnable { 4 | 5 | private final InvokeCompleteListener mCompleteExecutor; 6 | 7 | private final Task mTask; 8 | 9 | TaskCompleteRunnable(InvokeCompleteListener executor, Task task) { 10 | this.mCompleteExecutor = executor; 11 | this.mTask = task; 12 | } 13 | 14 | @Override 15 | public void run() { 16 | synchronized (mCompleteExecutor.lock) { 17 | if (mCompleteExecutor.mListener != null) { 18 | mCompleteExecutor.mListener.onComplete(mTask); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/TaskExecutor.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.util.concurrent.Executor; 6 | 7 | public class TaskExecutor implements Executor { 8 | 9 | @Override 10 | public final void execute(@NonNull Runnable command) { 11 | command.run(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/TaskExecutors.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import androidx.annotation.NonNull; 6 | 7 | import java.util.concurrent.Executor; 8 | 9 | public class TaskExecutors { 10 | 11 | /** 12 | * An Executor that uses the main application thread. 13 | */ 14 | public static final Executor MAIN_THREAD = new TaskExecutors.MainThreadExecutor(); 15 | 16 | static final Executor sExecutor = new TaskExecutor(); 17 | 18 | static final class MainThreadExecutor implements Executor { 19 | 20 | private final Handler mainThreadHandler = new Handler(Looper.getMainLooper()); 21 | 22 | @Override 23 | public void execute(@NonNull Runnable command) { 24 | mainThreadHandler.post(command); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/TaskFailureRunnable.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | final class TaskFailureRunnable implements Runnable { 4 | 5 | private final InvokeFailureListener mFailureExecutor; 6 | 7 | private final Task mTask; 8 | 9 | TaskFailureRunnable(InvokeFailureListener executor, Task task) { 10 | this.mFailureExecutor = executor; 11 | this.mTask = task; 12 | } 13 | 14 | @Override 15 | public void run() { 16 | synchronized (mFailureExecutor.lock) { 17 | if (mFailureExecutor.mListener != null) { 18 | mFailureExecutor.mListener.onFailure(mTask.getException()); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/TaskSuccessRunnable.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | final class TaskSuccessRunnable implements Runnable { 4 | 5 | private final InvokeSuccessListener mSuccessExecutor; 6 | 7 | private final Task mTask; 8 | 9 | TaskSuccessRunnable(InvokeSuccessListener executor, Task task) { 10 | this.mSuccessExecutor = executor; 11 | this.mTask = task; 12 | } 13 | 14 | @Override 15 | public void run() { 16 | synchronized (mSuccessExecutor.lock) { 17 | if (mSuccessExecutor.mListener != null) { 18 | mSuccessExecutor.mListener.onSuccess(mTask.getResult()); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/main/java/com/google/android/play/core/tasks/TaskWrapper.java: -------------------------------------------------------------------------------- 1 | package com.google.android.play.core.tasks; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 6 | 7 | @RestrictTo(LIBRARY_GROUP) 8 | public class TaskWrapper { 9 | 10 | private final TaskImpl mTask = new TaskImpl<>(); 11 | 12 | public final Task getTask() { 13 | return mTask; 14 | } 15 | 16 | public final boolean setException(Exception exception) { 17 | return mTask.setException(exception); 18 | } 19 | 20 | public final boolean setResult(TResult result) { 21 | return mTask.setResult(result); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /qigsaw-android/playcorelibrary/src/test/java/com/iqiyi/qigsaw/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.qigsaw; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles 'proguard-rules.pro' 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation "androidx.annotation:annotation:1.0.0" 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 31 | } 32 | apply from: rootProject.file('gradle/android-artifacts.gradle') 33 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 34 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 35 | 36 | -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitcommon 2 | POM_NAME=Split Common Lib 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -keep class * extends com.iqiyi.android.qigsaw.core.common.ICompatBundle -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/src/androidTest/java/com/iqiyi/android/qigsaw/core/common/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.common; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.android.qigsaw.core.common.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/src/main/java/com/iqiyi/android/qigsaw/core/common/CompatBundle.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.common; 2 | 3 | import androidx.annotation.Nullable; 4 | 5 | import java.util.Iterator; 6 | import java.util.ServiceLoader; 7 | 8 | public class CompatBundle { 9 | @Nullable 10 | public static final ICompatBundle instance; 11 | 12 | static { 13 | ServiceLoader compats = ServiceLoader.load(ICompatBundle.class); 14 | Iterator iterator = compats.iterator(); 15 | instance = iterator.hasNext() ? iterator.next() : null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/src/main/java/com/iqiyi/android/qigsaw/core/common/ICompatBundle.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.common; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.Keep; 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | import java.io.File; 10 | import java.io.InputStream; 11 | 12 | @Keep 13 | public interface ICompatBundle { 14 | /** 15 | * for 'parseSplitContentsForDefaultVersion' 16 | */ 17 | @Nullable 18 | String readDefaultSplitVersionContent(@NonNull Context context, @NonNull String fileName); 19 | 20 | @NonNull 21 | String getMD5(@NonNull File file); 22 | 23 | @NonNull 24 | String getMD5(@NonNull InputStream inputStream); 25 | 26 | boolean injectActivityResource(); 27 | 28 | boolean disableComponentInfoManager(); 29 | 30 | Class qigsawConfigClass(); 31 | } 32 | -------------------------------------------------------------------------------- /qigsaw-android/splitcommon/src/test/java/com/iqiyi/android/qigsaw/core/common/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.common; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /qigsaw-android/splitcore/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | consumerProguardFiles 'proguard-rules.pro' 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation "androidx.annotation:annotation:1.0.0" 28 | implementation 'androidx.appcompat:appcompat:1.0.0' 29 | api project(':splitcommon') 30 | implementation project(':splitextension') 31 | implementation project(':splitrequester') 32 | implementation project(':splitinstaller') 33 | api project(':splitloader') 34 | api project(':splitdownloader') 35 | api project(':playcorelibrary') 36 | api project(':splitreporter') 37 | testImplementation 'junit:junit:4.12' 38 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 39 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 40 | } 41 | apply from: rootProject.file('gradle/android-artifacts.gradle') 42 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 43 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 44 | 45 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitcore 2 | POM_NAME=Split Core Lib 3 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /qigsaw-android/splitcore/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | #copy from multidexkeep.pro 24 | -keep class com.iqiyi.android.qigsaw.core.Qigsaw { 25 | (...); 26 | void install(...); 27 | void onAppGetResources(Resources); 28 | } 29 | 30 | # ${yourApplicationId}.QigsawConfig, QigsawVersion >= 1.2.2 31 | -keep class **.QigsawConfig { 32 | *; 33 | } 34 | 35 | -keep class com.iqiyi.android.qigsaw.core.extension.ComponentInfo { 36 | *; 37 | } 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/androidTest/java/com/iqiyi/android/qigsaw/core/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.android.qigsaw.core.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/main/res/values-en/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Warm Prompt 3 | Using this feature will consume about %s M traffic data, Do you want to continue downloading? 4 | Confirm 5 | Cancel 6 | 7 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #000000 5 | #808080 6 | 7 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 温馨提示 3 | 使用此功能将会消耗您约%sM流量数据,是否继续下载? 4 | 确认 5 | 取消 6 | 7 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /qigsaw-android/splitcore/src/test/java/com/iqiyi/android/qigsaw/core/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | consumerProguardFiles 'proguard-rules.pro' 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation "androidx.annotation:annotation:1.0.0" 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 31 | } 32 | apply from: rootProject.file('gradle/android-artifacts.gradle') 33 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 34 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 35 | -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitdownloader 2 | POM_NAME=Split Downloader Lib 3 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | #copy from multidexkeep.pro 24 | -keep class * implements com.iqiyi.android.qigsaw.core.splitdownload.Downloader { 25 | (...); 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/src/androidTest/java/com/iqiyi/android/qigsaw/core/splitdownload/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitdownload; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.android.qigsaw.core.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/src/main/java/com/iqiyi/android/qigsaw/core/splitdownload/DownloadCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitdownload; 26 | 27 | public interface DownloadCallback { 28 | 29 | void onStart(); 30 | 31 | void onCanceled(); 32 | 33 | void onCanceling(); 34 | 35 | void onProgress(long currentBytes); 36 | 37 | void onCompleted(); 38 | 39 | void onError(int errorCode); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /qigsaw-android/splitdownloader/src/test/java/com/iqiyi/android/qigsaw/core/splitdownload/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitdownload; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /qigsaw-android/splitextension/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation "androidx.annotation:annotation:1.0.0" 27 | implementation project(':splitcommon') 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 31 | } 32 | apply from: rootProject.file('gradle/android-artifacts.gradle') 33 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 34 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 35 | -------------------------------------------------------------------------------- /qigsaw-android/splitextension/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitextension 2 | POM_NAME=Split Extension Lib 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /qigsaw-android/splitextension/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /qigsaw-android/splitextension/src/androidTest/java/com/iqiyi/android/qigsaw/core/extension/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.extension; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.android.qigsaw.extension.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitextension/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /qigsaw-android/splitextension/src/main/java/com/iqiyi/android/qigsaw/core/extension/AABExtensionException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.extension; 26 | 27 | import androidx.annotation.RestrictTo; 28 | 29 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 30 | 31 | @RestrictTo(LIBRARY_GROUP) 32 | public class AABExtensionException extends Exception { 33 | 34 | AABExtensionException(String message) { 35 | super(message); 36 | } 37 | 38 | AABExtensionException(Throwable error) { 39 | super(error); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /qigsaw-android/splitextension/src/test/java/com/iqiyi/android/qigsaw/core/extension/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.extension; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation "androidx.annotation:annotation:1.0.0" 27 | testImplementation 'junit:junit:4.12' 28 | implementation project(':splitcommon') 29 | implementation project(':splitreporter') 30 | implementation project(':splitdownloader') 31 | implementation project(':splitrequester') 32 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 33 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 34 | } 35 | apply from: rootProject.file('gradle/android-artifacts.gradle') 36 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 37 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 38 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitinstaller 2 | POM_NAME=Split Install Lib 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/aidl/com/iqiyi/android/qigsaw/core/splitinstall/protocol/ISplitInstallService.aidl: -------------------------------------------------------------------------------- 1 | // ISplitInstallService.aidl 2 | package com.iqiyi.android.qigsaw.core.splitinstall.protocol; 3 | 4 | import com.iqiyi.android.qigsaw.core.splitinstall.protocol.ISplitInstallServiceCallback; 5 | // Declare any non-default types here with import statements 6 | 7 | interface ISplitInstallService { 8 | 9 | void startInstall(String packageName, in List moduleNames, in Bundle versionCode, ISplitInstallServiceCallback callback); 10 | 11 | void cancelInstall(String packageName, int sessionId, in Bundle versionCode, ISplitInstallServiceCallback callback); 12 | 13 | void getSessionState(String packageName, int sessionId, ISplitInstallServiceCallback callback); 14 | 15 | void getSessionStates(String packageName, ISplitInstallServiceCallback callback); 16 | 17 | void deferredInstall(String packageName, in List moduleNames, in Bundle versionCode, ISplitInstallServiceCallback callback); 18 | 19 | void deferredUninstall(String packageName, in List moduleNames, in Bundle versionCode, ISplitInstallServiceCallback callback); 20 | } 21 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/aidl/com/iqiyi/android/qigsaw/core/splitinstall/protocol/ISplitInstallServiceCallback.aidl: -------------------------------------------------------------------------------- 1 | // ISplitInstallServiceCallback.aidl 2 | package com.iqiyi.android.qigsaw.core.splitinstall.protocol; 3 | 4 | // Declare any non-default types here with import statements 5 | 6 | interface ISplitInstallServiceCallback { 7 | /** 8 | * Demonstrates some basic types that you can use as parameters 9 | * and return values in AIDL. 10 | */ 11 | void onStartInstall(int sessionId, in Bundle data); 12 | 13 | void onCompleteInstall(int sessionId); 14 | 15 | void onCancelInstall(int sessionId, in Bundle data); 16 | 17 | void onGetSession(int sessionId, in Bundle data); 18 | 19 | void onDeferredUninstall(in Bundle data); 20 | 21 | void onDeferredInstall(in Bundle data); 22 | 23 | void onGetSessionStates(in List data); 24 | 25 | void onError(in Bundle data); 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/iqiyi/android/qigsaw/core/splitinstall/SplitInstallerExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitinstall; 26 | 27 | import java.util.concurrent.Executor; 28 | import java.util.concurrent.Executors; 29 | 30 | final class SplitInstallerExecutor { 31 | 32 | private static final Executor sExecutor = Executors.newSingleThreadScheduledExecutor(new SplitInstallerThread()); 33 | 34 | static Executor getExecutor() { 35 | return sExecutor; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/iqiyi/android/qigsaw/core/splitinstall/SplitInstallerThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitinstall; 26 | 27 | import android.annotation.SuppressLint; 28 | 29 | import androidx.annotation.NonNull; 30 | 31 | import java.util.concurrent.ThreadFactory; 32 | 33 | final class SplitInstallerThread implements ThreadFactory { 34 | 35 | @SuppressLint("NewThreadDirectly") 36 | @Override 37 | public Thread newThread(@NonNull Runnable r) { 38 | return new Thread(r, "split_install_thread"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/iqiyi/android/qigsaw/core/splitinstall/SplitSessionInstaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitinstall; 26 | 27 | import com.iqiyi.android.qigsaw.core.splitrequest.splitinfo.SplitInfo; 28 | 29 | import java.util.List; 30 | 31 | /** 32 | * Used to install splits when download tasks are finished. 33 | */ 34 | interface SplitSessionInstaller { 35 | 36 | void install(int sessionId, List splitInfoList); 37 | } 38 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/iqiyi/android/qigsaw/core/splitinstall/SplitUninstallReporterManager.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitinstall; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | import androidx.annotation.RestrictTo; 6 | 7 | import com.iqiyi.android.qigsaw.core.splitreport.SplitUninstallReporter; 8 | 9 | import java.util.concurrent.atomic.AtomicReference; 10 | 11 | import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 12 | 13 | @RestrictTo(LIBRARY_GROUP) 14 | public class SplitUninstallReporterManager { 15 | 16 | private static final AtomicReference sUninstallReporterRef = new AtomicReference<>(); 17 | 18 | public static void install(@NonNull SplitUninstallReporter uninstallReporter) { 19 | sUninstallReporterRef.compareAndSet(null, uninstallReporter); 20 | } 21 | 22 | @Nullable 23 | public static SplitUninstallReporter getUninstallReporter() { 24 | return sUninstallReporterRef.get(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/split/signature/A.java: -------------------------------------------------------------------------------- 1 | package com.split.signature; 2 | 3 | 4 | import java.io.IOException; 5 | import java.security.MessageDigest; 6 | 7 | interface A { 8 | long a(); 9 | 10 | void a(MessageDigest[] var1, long var2, int var4) throws IOException; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/split/signature/B.java: -------------------------------------------------------------------------------- 1 | package com.split.signature; 2 | 3 | import java.io.IOException; 4 | import java.nio.MappedByteBuffer; 5 | import java.nio.channels.FileChannel; 6 | import java.nio.channels.FileChannel.MapMode; 7 | import java.security.MessageDigest; 8 | 9 | final class B implements A { 10 | private final FileChannel a; 11 | private final long b; 12 | private final long c; 13 | 14 | B(FileChannel var1, long var2, long var4) { 15 | this.a = var1; 16 | this.b = var2; 17 | this.c = var4; 18 | } 19 | 20 | public long a() { 21 | return this.c; 22 | } 23 | 24 | public void a(MessageDigest[] var1, long var2, int var4) throws IOException { 25 | long var5 = this.b + var2; 26 | MappedByteBuffer var7; 27 | (var7 = this.a.map(MapMode.READ_ONLY, var5, (long) var4)).load(); 28 | MessageDigest[] var8 = var1; 29 | int var9 = var1.length; 30 | 31 | for (int var10 = 0; var10 < var9; ++var10) { 32 | MessageDigest var11 = var8[var10]; 33 | var7.position(0); 34 | var11.update(var7); 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/split/signature/C.java: -------------------------------------------------------------------------------- 1 | package com.split.signature; 2 | 3 | 4 | import java.nio.ByteBuffer; 5 | 6 | final class C { 7 | final ByteBuffer a; 8 | final long b; 9 | final long c; 10 | final long d; 11 | final ByteBuffer e; 12 | 13 | C(ByteBuffer var1, long var2, long var4, long var6, ByteBuffer var8) { 14 | this.a = var1; 15 | this.b = var2; 16 | this.c = var4; 17 | this.d = var6; 18 | this.e = var8; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/split/signature/D.java: -------------------------------------------------------------------------------- 1 | package com.split.signature; 2 | 3 | public final class D extends Exception { 4 | public D(String var1) { 5 | super(var1); 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /qigsaw-android/splitinstaller/src/main/java/com/split/signature/X509CertificateEx.java: -------------------------------------------------------------------------------- 1 | package com.split.signature; 2 | 3 | import java.security.cert.X509Certificate; 4 | 5 | final class X509CertificateEx extends X509CertificateWrapper { 6 | private byte[] a; 7 | 8 | X509CertificateEx(X509Certificate var1, byte[] var2) { 9 | super(var1); 10 | this.a = var2; 11 | } 12 | 13 | public byte[] getEncoded() { 14 | return this.a; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation project(':splitcommon') 28 | implementation project(':splitrequester') 29 | implementation project(':splitextension') 30 | implementation project(':splitreporter') 31 | implementation "androidx.annotation:annotation:1.0.0" 32 | testImplementation 'junit:junit:4.12' 33 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 34 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 35 | } 36 | apply from: rootProject.file('gradle/android-artifacts.gradle') 37 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 38 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 39 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitloader 2 | POM_NAME=Split Load Lib 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/ClassNotFoundInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitload; 26 | 27 | import androidx.annotation.RestrictTo; 28 | 29 | @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 30 | public interface ClassNotFoundInterceptor { 31 | 32 | Class findClass(String name); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/SkipSplitLoadTaskImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitload; 26 | 27 | class SkipSplitLoadTaskImpl implements Runnable { 28 | 29 | @Override 30 | public final void run() { 31 | // empty 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/Split.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitload; 26 | 27 | import androidx.annotation.NonNull; 28 | 29 | final class Split { 30 | 31 | final String splitName; 32 | 33 | final String splitApkPath; 34 | 35 | Split(String splitName, String splitApkPath) { 36 | this.splitName = splitName; 37 | this.splitApkPath = splitApkPath; 38 | } 39 | 40 | @NonNull 41 | @Override 42 | public String toString() { 43 | return "{" + splitName + "," + splitApkPath + "}"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/SplitCompatResourcesException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitload; 26 | 27 | final class SplitCompatResourcesException extends Throwable { 28 | 29 | SplitCompatResourcesException(String message, Throwable cause) { 30 | super(message, cause); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/SplitDelegateClassLoaderFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitload; 26 | 27 | public class SplitDelegateClassLoaderFactory { 28 | 29 | public static ClassLoader instantiateClassLoader(ClassLoader cl) { 30 | return new SplitDelegateClassloader(cl); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/SplitLoadException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitload; 26 | 27 | final class SplitLoadException extends Exception { 28 | 29 | private final int errorCode; 30 | 31 | SplitLoadException(int errorCode, Throwable e) { 32 | super((new StringBuilder(32)).append("Split Load Error: ").append(errorCode).toString(), e); 33 | this.errorCode = errorCode; 34 | } 35 | 36 | int getErrorCode() { 37 | return this.errorCode; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/compat/NativePathMapper.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitload.compat; 2 | 3 | public interface NativePathMapper { 4 | String map(String splitName, String originPath); 5 | } 6 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/compat/NativePathMapperImpl.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitload.compat; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.text.TextUtils; 6 | 7 | import com.iqiyi.android.qigsaw.core.common.AbiUtil; 8 | 9 | 10 | public class NativePathMapperImpl implements NativePathMapper { 11 | 12 | private final NativePathMapper mapper; 13 | 14 | public NativePathMapperImpl(Context context) { 15 | if (needUseCommonSoDir(context)) { 16 | mapper = new PathMapperV21(context); 17 | } else { 18 | mapper = new PathMapperAbove21(context); 19 | } 20 | } 21 | 22 | @Override 23 | public String map(String splitName, String originPath) { 24 | if (TextUtils.isEmpty(splitName) || TextUtils.isEmpty(originPath)) { 25 | return originPath; 26 | } 27 | synchronized(Runtime.getRuntime()) { 28 | return mapper.map(splitName, originPath); 29 | } 30 | } 31 | 32 | private boolean needUseCommonSoDir(Context context) { 33 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP 34 | && Build.VERSION.SDK_INT < Build.VERSION_CODES.M 35 | && AbiUtil.isArm64(context); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/compat/PathMapperAbove21.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitload.compat; 2 | 3 | import android.content.Context; 4 | 5 | class PathMapperAbove21 implements NativePathMapper { 6 | 7 | private final Context context; 8 | 9 | PathMapperAbove21(Context context) { 10 | this.context = context; 11 | } 12 | 13 | @Override 14 | public String map(String splitName, String originPath) { 15 | return originPath; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /qigsaw-android/splitloader/src/main/java/com/iqiyi/android/qigsaw/core/splitload/compat/SplitResourcesLoader.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitload.compat; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | /** 9 | * fetch with ServiceLoader 10 | */ 11 | public interface SplitResourcesLoader { 12 | void loadResources(@NonNull Context context, @NonNull Resources resources) throws Throwable; 13 | 14 | void loadResources(@NonNull Context context, @NonNull Resources preResources, @NonNull String splitApkPath) throws Throwable; 15 | } 16 | -------------------------------------------------------------------------------- /qigsaw-android/splitreporter/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation "androidx.annotation:annotation:1.0.0" 27 | implementation project(':splitcommon') 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 31 | } 32 | 33 | apply from: rootProject.file('gradle/android-artifacts.gradle') 34 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 35 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 36 | -------------------------------------------------------------------------------- /qigsaw-android/splitreporter/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitreporter 2 | POM_NAME=Split Reporter Lib 3 | POM_PACKAGING=jar -------------------------------------------------------------------------------- /qigsaw-android/splitreporter/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /qigsaw-android/splitreporter/src/androidTest/java/com/iqiyi/android/qigsaw/core/splitreport/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitreport; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.android.qigsaw.core.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitreporter/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /qigsaw-android/splitreporter/src/test/java/com/iqiyi/android/qigsaw/core/splitreport/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitreport; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version VERSION_NAME 4 | group GROUP_ID 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion versions.minSdk 10 | targetSdkVersion versions.targetSdk 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation project(':splitcommon') 27 | implementation project(':splitreporter') 28 | implementation "androidx.annotation:annotation:1.0.0" 29 | testImplementation 'junit:junit:4.12' 30 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 32 | } 33 | 34 | apply from: rootProject.file('gradle/android-artifacts.gradle') 35 | apply from: rootProject.file('gradle/gradle-bintray-upload.gradle') 36 | apply from: rootProject.file('gradle/gradle-maven-upload.gradle') 37 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=splitrequester 2 | POM_NAME=Split Request Lib 3 | POM_PACKAGING=jar 4 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/src/androidTest/java/com/iqiyi/android/qigsaw/core/splitrequest/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitrequest; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.iqiyi.android.qigsaw.core.request.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/src/main/java/com/iqiyi/android/qigsaw/core/splitrequest/splitinfo/SplitInfoListing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitrequest.splitinfo; 26 | 27 | import java.util.LinkedHashMap; 28 | 29 | final class SplitInfoListing { 30 | 31 | private final LinkedHashMap splitInfoMap; 32 | 33 | 34 | SplitInfoListing(LinkedHashMap splitInfoMap) { 35 | this.splitInfoMap = splitInfoMap; 36 | } 37 | 38 | LinkedHashMap getSplitInfoMap() { 39 | return splitInfoMap; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/src/main/java/com/iqiyi/android/qigsaw/core/splitrequest/splitinfo/SplitInfoVersionData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2019-present, iQIYI, Inc. All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.iqiyi.android.qigsaw.core.splitrequest.splitinfo; 26 | 27 | final class SplitInfoVersionData { 28 | 29 | String oldVersion; 30 | 31 | String newVersion; 32 | 33 | SplitInfoVersionData(String oldVersion, String newVersion) { 34 | this.oldVersion = oldVersion; 35 | this.newVersion = newVersion; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /qigsaw-android/splitrequester/src/test/java/com/iqiyi/android/qigsaw/core/splitrequest/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.iqiyi.android.qigsaw.core.splitrequest; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app','downloader' 2 | include ':java', ':assets', ':native' 3 | include ':splitcore', ':playcorelibrary', ':splitcommon' 4 | include ':splitinstaller', ':splitdownloader', ':splitloader' 5 | include ':splitrequester', ':splitreporter', ':splitextension' 6 | 7 | project(':assets').projectDir = new File("./features/assets") 8 | project(':java').projectDir = new File("./features/java") 9 | project(':native').projectDir = new File("./features/native") 10 | 11 | project(':splitcore').projectDir = new File("./qigsaw-android/splitcore") 12 | project(':playcorelibrary').projectDir = new File("./qigsaw-android/playcorelibrary") 13 | project(':playcorelibrary').projectDir = new File("./qigsaw-android/playcorelibrary") 14 | project(':splitinstaller').projectDir = new File("./qigsaw-android/splitinstaller") 15 | project(':splitdownloader').projectDir = new File("./qigsaw-android/splitdownloader") 16 | project(':splitloader').projectDir = new File("./qigsaw-android/splitloader") 17 | project(':splitrequester').projectDir = new File("./qigsaw-android/splitrequester") 18 | project(':splitreporter').projectDir = new File("./qigsaw-android/splitreporter") 19 | project(':splitcommon').projectDir = new File("./qigsaw-android/splitcommon") 20 | project(':splitextension').projectDir = new File("./qigsaw-android/splitextension") 21 | --------------------------------------------------------------------------------