├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── encodings.xml ├── gradle.xml ├── markdown-navigator-enh.xml ├── markdown-navigator.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── JarSigner ├── .gitignore ├── .idea │ ├── .gitignore │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── build.gradle ├── consumer-rules.pro ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── janking │ │ └── jarsigner │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ ├── com.sun.jarsigner │ │ ├── ContentSigner.java │ │ └── ContentSignerParameters.java │ │ ├── compact │ │ └── java │ │ │ ├── lang │ │ │ ├── InternalError.java │ │ │ └── VirtualMachineError.java │ │ │ ├── security │ │ │ └── cert │ │ │ │ └── Extension.java │ │ │ └── util │ │ │ └── Base64.java │ │ ├── sun.security.tools.jarsigner │ │ ├── Main.java │ │ ├── Resources.java │ │ ├── Resources_zh_CN.java │ │ └── TimestampedSigner.java │ │ └── sun │ │ ├── misc │ │ ├── CharacterEncoder.java │ │ ├── HexDumpEncoder.java │ │ ├── IOUtils.java │ │ ├── JavaIOAccess.java │ │ ├── SharedSecrets.java │ │ ├── Unsafe.java │ │ └── VM.java │ │ ├── net │ │ └── www │ │ │ └── ParseUtil.java │ │ ├── nio │ │ └── cs │ │ │ └── ThreadLocalCoders.java │ │ ├── reflect │ │ ├── CallerSensitive.java │ │ └── Reflection.java │ │ ├── security │ │ ├── action │ │ │ ├── GetBooleanAction.java │ │ │ └── GetPropertyAction.java │ │ ├── jca │ │ │ ├── ProviderConfig.java │ │ │ ├── ProviderList.java │ │ │ ├── Providers.java │ │ │ └── ServiceId.java │ │ ├── pkcs │ │ │ ├── ContentInfo.java │ │ │ ├── PKCS7_1.java │ │ │ ├── PKCS9Attribute.java │ │ │ ├── PKCS9Attributes.java │ │ │ ├── ParsingException.java │ │ │ ├── SignerInfo.java │ │ │ └── SigningCertificateInfo.java │ │ ├── provider │ │ │ ├── X509Factory.java │ │ │ └── certpath │ │ │ │ ├── X509CertPath.java │ │ │ │ └── X509CertificatePair.java │ │ ├── timestamp │ │ │ ├── HttpTimestamper.java │ │ │ ├── TSRequest.java │ │ │ ├── TSResponse.java │ │ │ ├── TimestampToken.java │ │ │ └── Timestamper.java │ │ ├── tools │ │ │ ├── KeyStoreUtil.java │ │ │ └── PathList.java │ │ ├── util │ │ │ ├── BitArray.java │ │ │ ├── ByteArrayLexOrder.java │ │ │ ├── ByteArrayTagOrder.java │ │ │ ├── Cache.java │ │ │ ├── CompactSignatureFileVerifier.java │ │ │ ├── Debug.java │ │ │ ├── DerEncoder.java │ │ │ ├── DerIndefLenConverter.java │ │ │ ├── DerInputBuffer.java │ │ │ ├── DerInputStream.java │ │ │ ├── DerOutputStream.java │ │ │ ├── DerValue.java │ │ │ ├── ManifestDigester.java │ │ │ ├── ObjectIdentifier.java │ │ │ ├── Password.java │ │ │ └── PropertyExpander.java │ │ └── x509 │ │ │ ├── AVA.java │ │ │ ├── AccessDescription.java │ │ │ ├── AlgorithmId.java │ │ │ ├── AttributeNameEnumeration.java │ │ │ ├── AuthorityInfoAccessExtension.java │ │ │ ├── AuthorityKeyIdentifierExtension.java │ │ │ ├── BasicConstraintsExtension.java │ │ │ ├── CRLDistributionPointsExtension.java │ │ │ ├── CRLExtensions.java │ │ │ ├── CRLNumberExtension.java │ │ │ ├── CRLReasonCodeExtension.java │ │ │ ├── CertAttrSet.java │ │ │ ├── CertificateAlgorithmId.java │ │ │ ├── CertificateExtensions.java │ │ │ ├── CertificateIssuerExtension.java │ │ │ ├── CertificatePoliciesExtension.java │ │ │ ├── CertificatePolicyId.java │ │ │ ├── CertificatePolicyMap.java │ │ │ ├── CertificateSerialNumber.java │ │ │ ├── CertificateValidity.java │ │ │ ├── CertificateVersion.java │ │ │ ├── CertificateX509Key.java │ │ │ ├── DNSName.java │ │ │ ├── DeltaCRLIndicatorExtension.java │ │ │ ├── DistributionPoint.java │ │ │ ├── DistributionPointName.java │ │ │ ├── EDIPartyName.java │ │ │ ├── ExtendedKeyUsageExtension.java │ │ │ ├── Extension.java │ │ │ ├── FreshestCRLExtension.java │ │ │ ├── GeneralName.java │ │ │ ├── GeneralNameInterface.java │ │ │ ├── GeneralNames.java │ │ │ ├── GeneralSubtree.java │ │ │ ├── GeneralSubtrees.java │ │ │ ├── IPAddressName.java │ │ │ ├── InhibitAnyPolicyExtension.java │ │ │ ├── InvalidityDateExtension.java │ │ │ ├── IssuerAlternativeNameExtension.java │ │ │ ├── IssuingDistributionPointExtension.java │ │ │ ├── KeyIdentifier.java │ │ │ ├── KeyUsageExtension.java │ │ │ ├── NameConstraintsExtension.java │ │ │ ├── NetscapeCertTypeExtension.java │ │ │ ├── OCSPNoCheckExtension.java │ │ │ ├── OIDMap.java │ │ │ ├── OIDName.java │ │ │ ├── OtherName.java │ │ │ ├── PKIXExtensions.java │ │ │ ├── PolicyConstraintsExtension.java │ │ │ ├── PolicyInformation.java │ │ │ ├── PolicyMappingsExtension.java │ │ │ ├── PrivateKeyUsageExtension.java │ │ │ ├── RDN.java │ │ │ ├── RFC822Name.java │ │ │ ├── ReasonFlags.java │ │ │ ├── SerialNumber.java │ │ │ ├── SubjectAlternativeNameExtension.java │ │ │ ├── SubjectInfoAccessExtension.java │ │ │ ├── SubjectKeyIdentifierExtension.java │ │ │ ├── URIName.java │ │ │ ├── UniqueIdentity.java │ │ │ ├── X400Address.java │ │ │ ├── X500Name.java │ │ │ ├── X509AttributeName.java │ │ │ ├── X509CRLEntryImpl.java │ │ │ ├── X509CRLImpl.java │ │ │ ├── X509CertImpl.java │ │ │ ├── X509CertInfo.java │ │ │ └── X509Key.java │ │ └── util │ │ └── calendar │ │ ├── AbstractCalendar.java │ │ ├── BaseCalendar.java │ │ ├── CalendarDate.java │ │ ├── CalendarSystem.java │ │ ├── CalendarUtils.java │ │ ├── Era.java │ │ ├── Gregorian.java │ │ ├── ImmutableGregorianDate.java │ │ ├── LocalGregorianCalendar.java │ │ ├── ZoneInfo.java │ │ └── ZoneInfoFile.java │ └── test │ └── java │ └── cn │ └── janking │ └── jarsigner │ └── ExampleUnitTest.java ├── README.assets ├── Screenshot_20200407-135626.jpg ├── Screenshot_20200407-135639.jpg ├── Screenshot_20200413-155923.jpg └── Screenshot_20200413-155925.jpg ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── signing.gradle └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── janking │ │ └── webDroid │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── key │ │ │ └── webdroid.jks │ │ └── template │ │ │ ├── AndroidManifest.xml │ │ │ ├── config.json │ │ │ ├── ic_demo_app.png │ │ │ ├── ic_music.png │ │ │ ├── ic_news.png │ │ │ ├── ic_picture.png │ │ │ └── ic_search.png │ ├── java │ │ └── cn │ │ │ └── janking │ │ │ └── webDroid │ │ │ ├── MyApplication.kt │ │ │ ├── activity │ │ │ ├── BaseActivity.kt │ │ │ ├── CreatorActivity.kt │ │ │ └── WebDroidActivity.kt │ │ │ ├── adapter │ │ │ ├── BasicPagerAdapter.kt │ │ │ ├── ItemTouchHelperCallback.kt │ │ │ ├── OnMoveAndSwipedListener.kt │ │ │ └── TabListRVAdapter.kt │ │ │ ├── constant │ │ │ ├── PathConstants.kt │ │ │ ├── PermissionConstants.java │ │ │ └── WebConstants.kt │ │ │ ├── event │ │ │ └── event.kt │ │ │ ├── helper │ │ │ ├── DialogHelper.kt │ │ │ └── PermissionHelper.kt │ │ │ ├── layout │ │ │ ├── EditAppLayout.kt │ │ │ ├── EditLayout.kt │ │ │ └── EditTabLayout.kt │ │ │ ├── model │ │ │ └── Config.kt │ │ │ ├── util │ │ │ ├── ActivityUtils.java │ │ │ ├── AdaptScreenUtils.java │ │ │ ├── AppUtils.java │ │ │ ├── BuildUtils.kt │ │ │ ├── ColorUtils.java │ │ │ ├── ConsoleUtils.kt │ │ │ ├── DialogUtils.kt │ │ │ ├── FileUtils.kt │ │ │ ├── LogUtils.java │ │ │ ├── OpenUtils.kt │ │ │ ├── PermissionUtils.java │ │ │ ├── RomUtils.java │ │ │ ├── SPUtils.java │ │ │ ├── ScreenUtils.java │ │ │ ├── ShellUtils.java │ │ │ ├── SpanUtils.java │ │ │ ├── ThreadUtils.java │ │ │ ├── ThrowableUtils.java │ │ │ ├── UriUtils.java │ │ │ ├── Utils.java │ │ │ ├── WebUtils.kt │ │ │ └── ZipUtils.java │ │ │ └── web │ │ │ ├── FilePathChooserCallback.kt │ │ │ ├── WebBox.kt │ │ │ ├── WebConfig.kt │ │ │ ├── WebFragment.kt │ │ │ ├── WebVideoPlayer.kt │ │ │ ├── extend │ │ │ ├── WebChromeClientExtend.kt │ │ │ ├── WebDownloadExtend.kt │ │ │ ├── WebViewClientExtend.kt │ │ │ ├── WebViewLongClickExtend.kt │ │ │ └── WebViewSettingExtend.kt │ │ │ ├── lifecycle │ │ │ ├── WebLifeCycle.java │ │ │ └── WebLifeCycleImpl.kt │ │ │ └── view │ │ │ ├── LollipopFixedWebView.kt │ │ │ └── NestedScrollWebView.kt │ └── res │ │ ├── anim │ │ └── anim_recycler_item_show.xml │ │ ├── drawable │ │ ├── ic_add_primary.xml │ │ ├── ic_close_white_24dp.xml │ │ ├── ic_info_outline_black_24dp.xml │ │ ├── ic_launcher.png │ │ ├── ic_launcher_default.png │ │ ├── ic_search.png │ │ ├── ic_settings_black_24dp.xml │ │ ├── ic_tab_0.png │ │ ├── ic_tab_1.png │ │ ├── ic_tab_2.png │ │ ├── ic_tab_3.png │ │ ├── ic_tab_4.png │ │ ├── ic_tab_default.png │ │ ├── image_avatar_default.png │ │ └── img_author_avatar.jpg │ │ ├── layout │ │ ├── activity_creator.xml │ │ ├── activity_webdroid.xml │ │ ├── item_tab_list.xml │ │ ├── layout_edit_app.xml │ │ ├── layout_edit_tab.xml │ │ ├── layout_image_dialog_fullscreen.xml │ │ ├── layout_nav.xml │ │ ├── layout_nav_header.xml │ │ ├── layout_text_dialog_fullscreen.xml │ │ └── layout_webview.xml │ │ ├── menu │ │ ├── drawer_main.xml │ │ ├── menu_bottom.xml │ │ ├── menu_creator.xml │ │ └── menu_webdroid.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── util_code_provider_paths.xml │ └── test │ └── java │ └── com │ └── janking │ └── webDroid │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── janking.jks ├── settings.gradle └── xmlparser ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src ├── androidTest └── java │ └── luyao │ └── parser │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml └── java │ ├── cn │ └── janking │ │ └── AXMLTool │ │ ├── XmlProcessor.java │ │ └── util │ │ ├── ByteUtils.java │ │ └── ManifestUtils.java │ └── luyao │ └── parser │ └── parser │ ├── utils │ ├── BytesReader.java │ ├── Reader.java │ ├── TransformUtils.java │ └── Utils.java │ └── xml │ ├── XmlParser.java │ └── bean │ ├── Attribute.java │ ├── NameSpace.java │ ├── Xml.java │ └── chunk │ ├── Chunk.java │ ├── EndNameSpaceChunk.java │ ├── EndTagChunk.java │ ├── StartNameSpaceChunk.java │ └── StartTagChunk.java └── test └── java └── luyao └── parser └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | xmlns:android 17 | 18 | ^$ 19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | xmlns:.* 28 | 29 | ^$ 30 | 31 | 32 | BY_NAME 33 | 34 |
35 |
36 | 37 | 38 | 39 | .*:id 40 | 41 | http://schemas.android.com/apk/res/android 42 | 43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 | .*:name 51 | 52 | http://schemas.android.com/apk/res/android 53 | 54 | 55 | 56 |
57 |
58 | 59 | 60 | 61 | name 62 | 63 | ^$ 64 | 65 | 66 | 67 |
68 |
69 | 70 | 71 | 72 | style 73 | 74 | ^$ 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 | .* 84 | 85 | ^$ 86 | 87 | 88 | BY_NAME 89 | 90 |
91 |
92 | 93 | 94 | 95 | .* 96 | 97 | http://schemas.android.com/apk/res/android 98 | 99 | 100 | ANDROID_ATTRIBUTE_ORDER 101 | 102 |
103 |
104 | 105 | 106 | 107 | .* 108 | 109 | .* 110 | 111 | 112 | BY_NAME 113 | 114 |
115 |
116 |
117 |
118 | 119 | 121 |
122 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JarSigner/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /JarSigner/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /JarSigner/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /JarSigner/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | -------------------------------------------------------------------------------- /JarSigner/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /JarSigner/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JarSigner/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JarSigner/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 21 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles 'consumer-rules.pro' 15 | 16 | compileOptions { 17 | targetCompatibility 1.8 18 | sourceCompatibility 1.8 19 | } 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | 34 | implementation 'androidx.appcompat:appcompat:1.1.0' 35 | testImplementation 'junit:junit:4.12' 36 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 37 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 38 | } 39 | -------------------------------------------------------------------------------- /JarSigner/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/JarSigner/consumer-rules.pro -------------------------------------------------------------------------------- /JarSigner/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/JarSigner/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /JarSigner/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 12 22:14:15 CST 2020 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.6.4-all.zip 7 | -------------------------------------------------------------------------------- /JarSigner/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /JarSigner/local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Thu Mar 12 22:14:04 CST 2020 8 | sdk.dir=C\:\\Users\\janki\\AppData\\Local\\Android\\Sdk 9 | -------------------------------------------------------------------------------- /JarSigner/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 | -------------------------------------------------------------------------------- /JarSigner/src/androidTest/java/cn/janking/jarsigner/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.janking.jarsigner; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("cn.janking.jarsigner.test", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /JarSigner/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/com.sun.jarsigner/ContentSigner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package com.sun.jarsigner; 27 | 28 | import java.io.IOException; 29 | import java.security.NoSuchAlgorithmException; 30 | import java.security.cert.CertificateException; 31 | 32 | /** 33 | * This class defines a content signing service. 34 | * Implementations must be instantiable using a zero-argument constructor. 35 | * 36 | * @since 1.5 37 | * @author Vincent Ryan 38 | */ 39 | 40 | public abstract class ContentSigner { 41 | 42 | /** 43 | * Generates a PKCS #7 signed data message. 44 | * This method is used when the signature has already been generated. 45 | * The signature, the signer's details, and optionally a signature 46 | * timestamp and the content that was signed, are all packaged into a 47 | * signed data message. 48 | * 49 | * @param parameters The non-null input parameters. 50 | * @param omitContent true if the content should be omitted from the 51 | * signed data message. Otherwise the content is included. 52 | * @param applyTimestamp true if the signature should be timestamped. 53 | * Otherwise timestamping is not performed. 54 | * @return A PKCS #7 signed data message. 55 | * @throws NoSuchAlgorithmException The exception is thrown if the signature 56 | * algorithm is unrecognised. 57 | * @throws CertificateException The exception is thrown if an error occurs 58 | * while processing the signer's certificate or the TSA's 59 | * certificate. 60 | * @throws IOException The exception is thrown if an error occurs while 61 | * generating the signature timestamp or while generating the signed 62 | * data message. 63 | * @throws NullPointerException The exception is thrown if parameters is 64 | * null. 65 | */ 66 | public abstract byte[] generateSignedData( 67 | ContentSignerParameters parameters, boolean omitContent, 68 | boolean applyTimestamp) 69 | throws NoSuchAlgorithmException, CertificateException, IOException; 70 | } 71 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/com.sun.jarsigner/ContentSignerParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package com.sun.jarsigner; 27 | 28 | import java.net.URI; 29 | import java.security.cert.X509Certificate; 30 | import java.util.zip.ZipFile; 31 | 32 | /** 33 | * This interface encapsulates the parameters for a ContentSigner object. 34 | * 35 | * @since 1.5 36 | * @author Vincent Ryan 37 | */ 38 | public interface ContentSignerParameters { 39 | 40 | /** 41 | * Retrieves the command-line arguments passed to the jarsigner tool. 42 | * 43 | * @return The command-line arguments. May be null. 44 | */ 45 | public String[] getCommandLine(); 46 | 47 | /** 48 | * Retrieves the identifier for a Timestamping Authority (TSA). 49 | * 50 | * @return The TSA identifier. May be null. 51 | */ 52 | public URI getTimestampingAuthority(); 53 | 54 | /** 55 | * Retrieves the certificate for a Timestamping Authority (TSA). 56 | * 57 | * @return The TSA certificate. May be null. 58 | */ 59 | public X509Certificate getTimestampingAuthorityCertificate(); 60 | 61 | /** 62 | * Retrieves the TSAPolicyID for a Timestamping Authority (TSA). 63 | * 64 | * @return The TSAPolicyID. May be null. 65 | */ 66 | public default String getTSAPolicyID() { 67 | return null; 68 | } 69 | 70 | /** 71 | * Retrieves the JAR file's signature. 72 | * 73 | * @return The non-null array of signature bytes. 74 | */ 75 | public byte[] getSignature(); 76 | 77 | /** 78 | * Retrieves the name of the signature algorithm. 79 | * 80 | * @return The non-null string name of the signature algorithm. 81 | */ 82 | public String getSignatureAlgorithm(); 83 | 84 | /** 85 | * Retrieves the signer's X.509 certificate chain. 86 | * 87 | * @return The non-null array of X.509 public-key certificates. 88 | */ 89 | public X509Certificate[] getSignerCertificateChain(); 90 | 91 | /** 92 | * Retrieves the content that was signed. 93 | * The content is the JAR file's signature file. 94 | * 95 | * @return The content bytes. May be null. 96 | */ 97 | public byte[] getContent(); 98 | 99 | /** 100 | * Retrieves the original source ZIP file before it was signed. 101 | * 102 | * @return The original ZIP file. May be null. 103 | */ 104 | public ZipFile getSource(); 105 | } 106 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/compact/java/lang/InternalError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package compact.java.lang; 27 | 28 | /** 29 | * Thrown to indicate some unexpected internal error has occurred in 30 | * the Java Virtual Machine. 31 | * 32 | * @author unascribed 33 | * @since JDK1.0 34 | */ 35 | public class InternalError extends VirtualMachineError { 36 | private static final long serialVersionUID = -9062593416125562365L; 37 | 38 | /** 39 | * Constructs an InternalError with no detail message. 40 | */ 41 | public InternalError() { 42 | super(); 43 | } 44 | 45 | /** 46 | * Constructs an InternalError with the specified 47 | * detail message. 48 | * 49 | * @param message the detail message. 50 | */ 51 | public InternalError(String message) { 52 | super(message); 53 | } 54 | 55 | 56 | /** 57 | * Constructs an {@code InternalError} with the specified detail 58 | * message and cause.

Note that the detail message associated 59 | * with {@code cause} is not automatically incorporated in 60 | * this error's detail message. 61 | * 62 | * @param message the detail message (which is saved for later retrieval 63 | * by the {@link #getMessage()} method). 64 | * @param cause the cause (which is saved for later retrieval by the 65 | * {@link #getCause()} method). (A {@code null} value is 66 | * permitted, and indicates that the cause is nonexistent or 67 | * unknown.) 68 | * @since 1.8 69 | */ 70 | public InternalError(String message, Throwable cause) { 71 | super(message, cause); 72 | } 73 | 74 | /** 75 | * Constructs an {@code InternalError} with the specified cause 76 | * and a detail message of {@code (cause==null ? null : 77 | * cause.toString())} (which typically contains the class and 78 | * detail message of {@code cause}). 79 | * 80 | * @param cause the cause (which is saved for later retrieval by the 81 | * {@link #getCause()} method). (A {@code null} value is 82 | * permitted, and indicates that the cause is nonexistent or 83 | * unknown.) 84 | * @since 1.8 85 | */ 86 | public InternalError(Throwable cause) { 87 | super(cause); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/compact/java/lang/VirtualMachineError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package compact.java.lang; 27 | 28 | /** 29 | * Thrown to indicate that the Java Virtual Machine is broken or has 30 | * run out of resources necessary for it to continue operating. 31 | * 32 | * 33 | * @author Frank Yellin 34 | * @since JDK1.0 35 | */ 36 | abstract public class VirtualMachineError extends Error { 37 | private static final long serialVersionUID = 4161983926571568670L; 38 | 39 | /** 40 | * Constructs a VirtualMachineError with no detail message. 41 | */ 42 | public VirtualMachineError() { 43 | super(); 44 | } 45 | 46 | /** 47 | * Constructs a VirtualMachineError with the specified 48 | * detail message. 49 | * 50 | * @param message the detail message. 51 | */ 52 | public VirtualMachineError(String message) { 53 | super(message); 54 | } 55 | 56 | /** 57 | * Constructs a {@code VirtualMachineError} with the specified 58 | * detail message and cause.

Note that the detail message 59 | * associated with {@code cause} is not automatically 60 | * incorporated in this error's detail message. 61 | * 62 | * @param message the detail message (which is saved for later retrieval 63 | * by the {@link #getMessage()} method). 64 | * @param cause the cause (which is saved for later retrieval by the 65 | * {@link #getCause()} method). (A {@code null} value is 66 | * permitted, and indicates that the cause is nonexistent or 67 | * unknown.) 68 | * @since 1.8 69 | */ 70 | public VirtualMachineError(String message, Throwable cause) { 71 | super(message, cause); 72 | } 73 | 74 | /** 75 | * Constructs an a {@code VirtualMachineError} with the specified 76 | * cause and a detail message of {@code (cause==null ? null : 77 | * cause.toString())} (which typically contains the class and 78 | * detail message of {@code cause}). 79 | * 80 | * @param cause the cause (which is saved for later retrieval by the 81 | * {@link #getCause()} method). (A {@code null} value is 82 | * permitted, and indicates that the cause is nonexistent or 83 | * unknown.) 84 | * @since 1.8 85 | */ 86 | public VirtualMachineError(Throwable cause) { 87 | super(cause); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/compact/java/security/cert/Extension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package compact.java.security.cert; 27 | 28 | import java.io.IOException; 29 | import java.io.OutputStream; 30 | 31 | /** 32 | * This interface represents an X.509 extension. 33 | * 34 | *

35 | * Extensions provide a means of associating additional attributes with users 36 | * or public keys and for managing a certification hierarchy. The extension 37 | * format also allows communities to define private extensions to carry 38 | * information unique to those communities. 39 | * 40 | *

41 | * Each extension contains an object identifier, a criticality setting 42 | * indicating whether it is a critical or a non-critical extension, and 43 | * and an ASN.1 DER-encoded value. Its ASN.1 definition is: 44 | * 45 | *

 46 |  *
 47 |  *     Extension ::= SEQUENCE {
 48 |  *         extnId        OBJECT IDENTIFIER,
 49 |  *         critical      BOOLEAN DEFAULT FALSE,
 50 |  *         extnValue     OCTET STRING
 51 |  *                 -- contains a DER encoding of a value
 52 |  *                 -- of the type registered for use with
 53 |  *                 -- the extnId object identifier value
 54 |  *     }
 55 |  *
 56 |  * 
57 | * 58 | *

59 | * This interface is designed to provide access to a single extension, 60 | * unlike {@link java.security.cert.X509Extension} which is more suitable 61 | * for accessing a set of extensions. 62 | * 63 | * @since 1.7 64 | */ 65 | public interface Extension { 66 | 67 | /** 68 | * Gets the extensions's object identifier. 69 | * 70 | * @return the object identifier as a String 71 | */ 72 | String getId(); 73 | 74 | /** 75 | * Gets the extension's criticality setting. 76 | * 77 | * @return true if this is a critical extension. 78 | */ 79 | boolean isCritical(); 80 | 81 | /** 82 | * Gets the extensions's DER-encoded value. Note, this is the bytes 83 | * that are encoded as an OCTET STRING. It does not include the OCTET 84 | * STRING tag and length. 85 | * 86 | * @return a copy of the extension's value, or {@code null} if no 87 | * extension value is present. 88 | */ 89 | byte[] getValue(); 90 | 91 | /** 92 | * Generates the extension's DER encoding and writes it to the output 93 | * stream. 94 | * 95 | * @param out the output stream 96 | * @exception IOException on encoding or output error. 97 | * @exception NullPointerException if {@code out} is {@code null}. 98 | */ 99 | void encode(OutputStream out) throws IOException; 100 | } 101 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/misc/IOUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | /** 27 | * IOUtils: A collection of IO-related public static methods. 28 | */ 29 | 30 | package sun.misc; 31 | 32 | import java.io.EOFException; 33 | import java.io.IOException; 34 | import java.io.InputStream; 35 | import java.util.Arrays; 36 | 37 | public class IOUtils { 38 | 39 | /** 40 | * Read up to length of bytes from in 41 | * until EOF is detected. 42 | * @param in input stream, must not be null 43 | * @param length number of bytes to read, -1 or Integer.MAX_VALUE means 44 | * read as much as possible 45 | * @param readAll if true, an EOFException will be thrown if not enough 46 | * bytes are read. Ignored when length is -1 or Integer.MAX_VALUE 47 | * @return bytes read 48 | * @throws IOException Any IO error or a premature EOF is detected 49 | */ 50 | public static byte[] readFully(InputStream is, int length, boolean readAll) 51 | throws IOException { 52 | byte[] output = {}; 53 | if (length == -1) length = Integer.MAX_VALUE; 54 | int pos = 0; 55 | while (pos < length) { 56 | int bytesToRead; 57 | if (pos >= output.length) { // Only expand when there's no room 58 | bytesToRead = Math.min(length - pos, output.length + 1024); 59 | if (output.length < pos + bytesToRead) { 60 | output = Arrays.copyOf(output, pos + bytesToRead); 61 | } 62 | } else { 63 | bytesToRead = output.length - pos; 64 | } 65 | int cc = is.read(output, pos, bytesToRead); 66 | if (cc < 0) { 67 | if (readAll && length != Integer.MAX_VALUE) { 68 | throw new EOFException("Detect premature EOF"); 69 | } else { 70 | if (output.length != pos) { 71 | output = Arrays.copyOf(output, pos); 72 | } 73 | break; 74 | } 75 | } 76 | pos += cc; 77 | } 78 | return output; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/misc/JavaIOAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.misc; 27 | import java.io.Console; 28 | import java.nio.charset.Charset; 29 | 30 | public interface JavaIOAccess { 31 | public Console console(); 32 | public Charset charset(); 33 | } 34 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/misc/SharedSecrets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.misc; 27 | 28 | import java.io.Console; 29 | 30 | /** A repository of "shared secrets", which are a mechanism for 31 | calling implementation-private methods in another package without 32 | using reflection. A package-private class implements a public 33 | interface and provides the ability to call package-private methods 34 | within that package; the object implementing that interface is 35 | provided through a third package to which access is restricted. 36 | This framework avoids the primary disadvantage of using reflection 37 | for this purpose, namely the loss of compile-time checking. */ 38 | 39 | public class SharedSecrets { 40 | private static final Unsafe unsafe = Unsafe.getUnsafe(); 41 | private static JavaIOAccess javaIOAccess; 42 | 43 | 44 | public static JavaIOAccess getJavaIOAccess() { 45 | if (javaIOAccess == null) { 46 | unsafe.ensureClassInitialized(Console.class); 47 | } 48 | return javaIOAccess; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/reflect/CallerSensitive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.reflect; 27 | 28 | import java.lang.annotation.Retention; 29 | import java.lang.annotation.RetentionPolicy; 30 | import java.lang.annotation.Target; 31 | 32 | import static java.lang.annotation.ElementType.METHOD; 33 | 34 | /** 35 | * A method annotated @CallerSensitive is sensitive to its calling class, 36 | * via {@link sun.reflect.Reflection#getCallerClass Reflection.getCallerClass}, 37 | * or via some equivalent. 38 | * 39 | * @author John R. Rose 40 | */ 41 | @Retention(RetentionPolicy.RUNTIME) 42 | @Target({METHOD}) 43 | public @interface CallerSensitive { 44 | } 45 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/action/GetBooleanAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.action; 27 | 28 | /** 29 | * A convenience class for retrieving the boolean value of a system property 30 | * as a privileged action. 31 | * 32 | *

An instance of this class can be used as the argument of 33 | * AccessController.doPrivileged. 34 | * 35 | *

The following code retrieves the boolean value of the system 36 | * property named "prop" as a privileged action:

37 | * 38 | *

39 |  * boolean b = java.security.AccessController.doPrivileged
40 |  *              (new GetBooleanAction("prop")).booleanValue();
41 |  * 
42 | * 43 | * @author Roland Schemers 44 | * @see java.security.PrivilegedAction 45 | * @see java.security.AccessController 46 | * @since 1.2 47 | */ 48 | 49 | public class GetBooleanAction 50 | implements java.security.PrivilegedAction { 51 | private String theProp; 52 | 53 | /** 54 | * Constructor that takes the name of the system property whose boolean 55 | * value needs to be determined. 56 | * 57 | * @param theProp the name of the system property. 58 | */ 59 | public GetBooleanAction(String theProp) { 60 | this.theProp = theProp; 61 | } 62 | 63 | /** 64 | * Determines the boolean value of the system property whose name was 65 | * specified in the constructor. 66 | * 67 | * @return the Boolean value of the system property. 68 | */ 69 | public Boolean run() { 70 | return Boolean.getBoolean(theProp); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/action/GetPropertyAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.action; 27 | 28 | /** 29 | * A convenience class for retrieving the string value of a system 30 | * property as a privileged action. 31 | * 32 | *

An instance of this class can be used as the argument of 33 | * AccessController.doPrivileged. 34 | * 35 | *

The following code retrieves the value of the system 36 | * property named "prop" as a privileged action:

37 | * 38 | *

39 |  * String s = java.security.AccessController.doPrivileged
40 |  *                      (new GetPropertyAction("prop"));
41 |  * 
42 | * 43 | * @author Roland Schemers 44 | * @see java.security.PrivilegedAction 45 | * @see java.security.AccessController 46 | * @since 1.2 47 | */ 48 | 49 | public class GetPropertyAction 50 | implements java.security.PrivilegedAction { 51 | private String theProp; 52 | private String defaultVal; 53 | 54 | /** 55 | * Constructor that takes the name of the system property whose 56 | * string value needs to be determined. 57 | * 58 | * @param theProp the name of the system property. 59 | */ 60 | public GetPropertyAction(String theProp) { 61 | this.theProp = theProp; 62 | } 63 | 64 | /** 65 | * Constructor that takes the name of the system property and the default 66 | * value of that property. 67 | * 68 | * @param theProp the name of the system property. 69 | * @param defaulVal the default value. 70 | */ 71 | public GetPropertyAction(String theProp, String defaultVal) { 72 | this.theProp = theProp; 73 | this.defaultVal = defaultVal; 74 | } 75 | 76 | /** 77 | * Determines the string value of the system property whose 78 | * name was specified in the constructor. 79 | * 80 | * @return the string value of the system property, 81 | * or the default value if there is no property with that key. 82 | */ 83 | public String run() { 84 | String value = System.getProperty(theProp); 85 | return (value == null) ? defaultVal : value; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/jca/ServiceId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.jca; 27 | 28 | /** 29 | * Simple class encapsulating a service type and algorithm for lookup. 30 | * Put in a separate file rather than nested to allow import via ...jca.*. 31 | * 32 | * @author Andreas Sterbenz 33 | * @since 1.5 34 | */ 35 | public final class ServiceId { 36 | 37 | public final String type; 38 | public final String algorithm; 39 | 40 | public ServiceId(String type, String algorithm) { 41 | this.type = type; 42 | this.algorithm = algorithm; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/pkcs/ParsingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | /** 27 | * Generic PKCS Parsing exception. 28 | * 29 | * @author Benjamin Renaud 30 | */ 31 | 32 | package sun.security.pkcs; 33 | 34 | import java.io.IOException; 35 | 36 | public class ParsingException extends IOException { 37 | 38 | private static final long serialVersionUID = -6316569918966181883L; 39 | 40 | public ParsingException() { 41 | super(); 42 | } 43 | 44 | public ParsingException(String s) { 45 | super(s); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/timestamp/Timestamper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.timestamp; 27 | 28 | import java.io.IOException; 29 | 30 | /** 31 | * A timestamping service which conforms to the Time-Stamp Protocol (TSP) 32 | * defined in: 33 | * RFC 3161. 34 | * Individual timestampers may communicate with a Timestamping Authority (TSA) 35 | * over different transport machanisms. TSP permits at least the following 36 | * transports: HTTP, Internet mail, file-based and socket-based. 37 | * 38 | * @author Vincent Ryan 39 | * @see HttpTimestamper 40 | */ 41 | public interface Timestamper { 42 | 43 | /* 44 | * Connects to the TSA and requests a timestamp. 45 | * 46 | * @param tsQuery The timestamp query. 47 | * @return The result of the timestamp query. 48 | * @throws IOException The exception is thrown if a problem occurs while 49 | * communicating with the TSA. 50 | */ 51 | public TSResponse generateTimestamp(TSRequest tsQuery) throws IOException; 52 | } 53 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/util/ByteArrayLexOrder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | 27 | package sun.security.util; 28 | 29 | import java.util.Comparator; 30 | 31 | /** 32 | * Compare two byte arrays in lexicographical order. 33 | * 34 | * @author D. N. Hoover 35 | */ 36 | public class ByteArrayLexOrder implements Comparator { 37 | 38 | /** 39 | * Perform lexicographical comparison of two byte arrays, 40 | * regarding each byte as unsigned. That is, compare array entries 41 | * in order until they differ--the array with the smaller entry 42 | * is "smaller". If array entries are 43 | * equal till one array ends, then the longer array is "bigger". 44 | * 45 | * @param bytes1 first byte array to compare. 46 | * @param bytes2 second byte array to compare. 47 | * @return negative number if bytes1 < bytes2, 0 if bytes1 == bytes2, 48 | * positive number if bytes1 > bytes2. 49 | * 50 | * @exception ClassCastException 51 | * if either argument is not a byte array. 52 | */ 53 | public final int compare( byte[] bytes1, byte[] bytes2) { 54 | int diff; 55 | for (int i = 0; i < bytes1.length && i < bytes2.length; i++) { 56 | diff = (bytes1[i] & 0xFF) - (bytes2[i] & 0xFF); 57 | if (diff != 0) { 58 | return diff; 59 | } 60 | } 61 | // if array entries are equal till the first ends, then the 62 | // longer is "bigger" 63 | return bytes1.length - bytes2.length; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/util/ByteArrayTagOrder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | 27 | /** 28 | * ByteArrayTagOrder: a class for comparing two DER encodings by the 29 | * order of their tags. 30 | * 31 | * @author D. N. Hoover 32 | */ 33 | 34 | package sun.security.util; 35 | 36 | import java.util.Comparator; 37 | 38 | public class ByteArrayTagOrder implements Comparator { 39 | 40 | /** 41 | * Compare two byte arrays, by the order of their tags, 42 | * as defined in ITU-T X.680, sec. 6.4. (First compare 43 | * tag classes, then tag numbers, ignoring the constructivity bit.) 44 | * 45 | * @param bytes1 first byte array to compare. 46 | * @param bytes2 second byte array to compare. 47 | * @return negative number if bytes1 < bytes2, 0 if bytes1 == bytes2, 48 | * positive number if bytes1 > bytes2. 49 | * 50 | * @exception ClassCastException 51 | * if either argument is not a byte array. 52 | */ 53 | 54 | public final int compare(byte[] bytes1, byte[] bytes2) { 55 | // tag order is same as byte order ignoring any difference in 56 | // the constructivity bit (0x02) 57 | return (bytes1[0] | 0x20) - (bytes2[0] | 0x20); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/util/DerEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.util; 27 | 28 | import java.io.IOException; 29 | import java.io.OutputStream; 30 | 31 | /** 32 | * Interface to an object that knows how to write its own DER 33 | * encoding to an output stream. 34 | * 35 | * @author D. N. Hoover 36 | */ 37 | public interface DerEncoder { 38 | 39 | /** 40 | * DER encode this object and write the results to a stream. 41 | * 42 | * @param out the stream on which the DER encoding is written. 43 | */ 44 | public void derEncode(OutputStream out) 45 | throws IOException; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/x509/AttributeNameEnumeration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.x509; 27 | 28 | import java.util.Vector; 29 | 30 | /** 31 | *

This class provides the Enumeration implementation used 32 | * by all the X509 certificate attributes to return the attribute 33 | * names contained within them. 34 | * 35 | * @author Amit Kapoor 36 | * @author Hemma Prafullchandra 37 | */ 38 | public class AttributeNameEnumeration extends Vector { 39 | 40 | private static final long serialVersionUID = -6067440240757099134L; 41 | 42 | /** 43 | * The default constructor for this class. 44 | */ 45 | public AttributeNameEnumeration() { 46 | super(4,2); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/x509/CertificatePolicyId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.x509; 27 | 28 | import java.io.IOException; 29 | 30 | import sun.security.util.DerOutputStream; 31 | import sun.security.util.DerValue; 32 | import sun.security.util.ObjectIdentifier; 33 | 34 | 35 | /** 36 | * Represent the CertificatePolicyId ASN.1 object. 37 | * 38 | * @author Amit Kapoor 39 | * @author Hemma Prafullchandra 40 | */ 41 | public class CertificatePolicyId { 42 | private ObjectIdentifier id; 43 | 44 | /** 45 | * Create a CertificatePolicyId with the ObjectIdentifier. 46 | * 47 | * @param id the ObjectIdentifier for the policy id. 48 | */ 49 | public CertificatePolicyId(ObjectIdentifier id) { 50 | this.id = id; 51 | } 52 | 53 | /** 54 | * Create the object from its Der encoded value. 55 | * 56 | * @param val the DER encoded value for the same. 57 | */ 58 | public CertificatePolicyId(DerValue val) throws IOException { 59 | this.id = val.getOID(); 60 | } 61 | 62 | /** 63 | * Return the value of the CertificatePolicyId as an ObjectIdentifier. 64 | */ 65 | public ObjectIdentifier getIdentifier() { 66 | return (id); 67 | } 68 | 69 | /** 70 | * Returns a printable representation of the CertificatePolicyId. 71 | */ 72 | public String toString() { 73 | String s = "CertificatePolicyId: [" 74 | + id.toString() 75 | + "]\n"; 76 | 77 | return (s); 78 | } 79 | 80 | /** 81 | * Write the CertificatePolicyId to the DerOutputStream. 82 | * 83 | * @param out the DerOutputStream to write the object to. 84 | * @exception IOException on errors. 85 | */ 86 | public void encode(DerOutputStream out) throws IOException { 87 | out.putOID(id); 88 | } 89 | 90 | /** 91 | * Compares this CertificatePolicyId with another, for 92 | * equality. Uses ObjectIdentifier.equals() as test for 93 | * equality. 94 | * 95 | * @return true iff the ids are identical. 96 | */ 97 | public boolean equals(Object other) { 98 | if (other instanceof CertificatePolicyId) 99 | return id.equals((Object) 100 | ((CertificatePolicyId) other).getIdentifier()); 101 | else 102 | return false; 103 | } 104 | 105 | /** 106 | * Returns a hash code value for this object. 107 | * 108 | * @return a hash code value 109 | */ 110 | public int hashCode() { 111 | return id.hashCode(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/x509/CertificatePolicyMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.x509; 27 | 28 | import java.io.IOException; 29 | 30 | import sun.security.util.DerOutputStream; 31 | import sun.security.util.DerValue; 32 | 33 | /** 34 | * Represent the CertificatePolicyMap ASN.1 object. 35 | * 36 | * @author Amit Kapoor 37 | * @author Hemma Prafullchandra 38 | */ 39 | public class CertificatePolicyMap { 40 | private CertificatePolicyId issuerDomain; 41 | private CertificatePolicyId subjectDomain; 42 | 43 | /** 44 | * Create a CertificatePolicyMap with the passed CertificatePolicyId's. 45 | * 46 | * @param issuer the CertificatePolicyId for the issuer CA. 47 | * @param subject the CertificatePolicyId for the subject CA. 48 | */ 49 | public CertificatePolicyMap(CertificatePolicyId issuer, 50 | CertificatePolicyId subject) { 51 | this.issuerDomain = issuer; 52 | this.subjectDomain = subject; 53 | } 54 | 55 | /** 56 | * Create the CertificatePolicyMap from the DER encoded value. 57 | * 58 | * @param val the DER encoded value of the same. 59 | */ 60 | public CertificatePolicyMap(DerValue val) throws IOException { 61 | if (val.tag != DerValue.tag_Sequence) { 62 | throw new IOException("Invalid encoding for CertificatePolicyMap"); 63 | } 64 | issuerDomain = new CertificatePolicyId(val.data.getDerValue()); 65 | subjectDomain = new CertificatePolicyId(val.data.getDerValue()); 66 | } 67 | 68 | /** 69 | * Return the issuer CA part of the policy map. 70 | */ 71 | public CertificatePolicyId getIssuerIdentifier() { 72 | return (issuerDomain); 73 | } 74 | 75 | /** 76 | * Return the subject CA part of the policy map. 77 | */ 78 | public CertificatePolicyId getSubjectIdentifier() { 79 | return (subjectDomain); 80 | } 81 | 82 | /** 83 | * Returns a printable representation of the CertificatePolicyId. 84 | */ 85 | public String toString() { 86 | String s = "CertificatePolicyMap: [\n" 87 | + "IssuerDomain:" + issuerDomain.toString() 88 | + "SubjectDomain:" + subjectDomain.toString() 89 | + "]\n"; 90 | 91 | return (s); 92 | } 93 | 94 | /** 95 | * Write the CertificatePolicyMap to the DerOutputStream. 96 | * 97 | * @param out the DerOutputStream to write the object to. 98 | * @exception IOException on errors. 99 | */ 100 | public void encode(DerOutputStream out) throws IOException { 101 | DerOutputStream tmp = new DerOutputStream(); 102 | 103 | issuerDomain.encode(tmp); 104 | subjectDomain.encode(tmp); 105 | out.write(DerValue.tag_Sequence,tmp); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/x509/FreshestCRLExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.x509; 27 | 28 | import java.io.IOException; 29 | import java.io.OutputStream; 30 | import java.util.List; 31 | 32 | /** 33 | * Represents the Freshest CRL Extension. 34 | * 35 | *

36 | * The extension identifies how delta CRL information for a 37 | * complete CRL is obtained. 38 | * 39 | *

40 | * The extension is defined in Section 5.2.6 of 41 | * Internet X.509 PKI Certific 42 | ate and Certificate Revocation List (CRL) Profile. 43 | * 44 | *

45 | * Its ASN.1 definition is as follows: 46 | *

47 |  *     id-ce-freshestCRL OBJECT IDENTIFIER ::=  { id-ce 46 }
48 |  *
49 |  *     FreshestCRL ::= CRLDistributionPoints
50 |  * 
51 | * 52 | * @since 1.6 53 | */ 54 | public class FreshestCRLExtension extends CRLDistributionPointsExtension { 55 | 56 | /** 57 | * Attribute name. 58 | */ 59 | public static final String NAME = "FreshestCRL"; 60 | 61 | /** 62 | * Creates a freshest CRL extension. 63 | * The criticality is set to false. 64 | * 65 | * @param distributionPoints the list of delta CRL distribution points. 66 | */ 67 | public FreshestCRLExtension(List distributionPoints) 68 | throws IOException { 69 | 70 | super(PKIXExtensions.FreshestCRL_Id, false, distributionPoints, NAME); 71 | } 72 | 73 | /** 74 | * Creates the extension from the passed DER encoded value of the same. 75 | * 76 | * @param critical true if the extension is to be treated as critical. 77 | * @param value an array of DER encoded bytes of the actual value. 78 | * @exception IOException on decoding error. 79 | */ 80 | public FreshestCRLExtension(Boolean critical, Object value) 81 | throws IOException { 82 | super(PKIXExtensions.FreshestCRL_Id, critical.booleanValue(), value, 83 | NAME); 84 | } 85 | 86 | /** 87 | * Writes the extension to the DerOutputStream. 88 | * 89 | * @param out the DerOutputStream to write the extension to. 90 | * @exception IOException on encoding errors. 91 | */ 92 | public void encode(OutputStream out) throws IOException { 93 | super.encode(out, PKIXExtensions.FreshestCRL_Id, false); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/security/x509/X509AttributeName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.security.x509; 27 | 28 | /** 29 | * This class is used to parse attribute names like "x509.info.extensions". 30 | * 31 | * @author Amit Kapoor 32 | * @author Hemma Prafullchandra 33 | */ 34 | public class X509AttributeName { 35 | // Public members 36 | private static final char SEPARATOR = '.'; 37 | 38 | // Private data members 39 | private String prefix = null; 40 | private String suffix = null; 41 | 42 | /** 43 | * Default constructor for the class. Name is of the form 44 | * "x509.info.extensions". 45 | * 46 | * @param name the attribute name. 47 | */ 48 | public X509AttributeName(String name) { 49 | int i = name.indexOf(SEPARATOR); 50 | if (i == (-1)) { 51 | prefix = name; 52 | } else { 53 | prefix = name.substring(0, i); 54 | suffix = name.substring(i + 1); 55 | } 56 | } 57 | 58 | /** 59 | * Return the prefix of the name. 60 | */ 61 | public String getPrefix() { 62 | return (prefix); 63 | } 64 | 65 | /** 66 | * Return the suffix of the name. 67 | */ 68 | public String getSuffix() { 69 | return (suffix); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /JarSigner/src/main/java/sun/util/calendar/Gregorian.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package sun.util.calendar; 27 | 28 | import java.util.TimeZone; 29 | 30 | /** 31 | * Gregorian calendar implementation. 32 | * 33 | * @author Masayoshi Okutsu 34 | * @since 1.5 35 | */ 36 | 37 | public class Gregorian extends BaseCalendar { 38 | 39 | static class Date extends BaseCalendar.Date { 40 | protected Date() { 41 | super(); 42 | } 43 | 44 | protected Date(TimeZone zone) { 45 | super(zone); 46 | } 47 | 48 | public int getNormalizedYear() { 49 | return getYear(); 50 | } 51 | 52 | public void setNormalizedYear(int normalizedYear) { 53 | setYear(normalizedYear); 54 | } 55 | } 56 | 57 | Gregorian() { 58 | } 59 | 60 | public String getName() { 61 | return "gregorian"; 62 | } 63 | 64 | public Date getCalendarDate() { 65 | return getCalendarDate(System.currentTimeMillis(), newCalendarDate()); 66 | } 67 | 68 | public Date getCalendarDate(long millis) { 69 | return getCalendarDate(millis, newCalendarDate()); 70 | } 71 | 72 | public Date getCalendarDate(long millis, CalendarDate date) { 73 | return (Date) super.getCalendarDate(millis, date); 74 | } 75 | 76 | public Date getCalendarDate(long millis, TimeZone zone) { 77 | return getCalendarDate(millis, newCalendarDate(zone)); 78 | } 79 | 80 | public Date newCalendarDate() { 81 | return new Date(); 82 | } 83 | 84 | public Date newCalendarDate(TimeZone zone) { 85 | return new Date(zone); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /JarSigner/src/test/java/cn/janking/jarsigner/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.janking.jarsigner; 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 | } -------------------------------------------------------------------------------- /README.assets/Screenshot_20200407-135626.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/README.assets/Screenshot_20200407-135626.jpg -------------------------------------------------------------------------------- /README.assets/Screenshot_20200407-135639.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/README.assets/Screenshot_20200407-135639.jpg -------------------------------------------------------------------------------- /README.assets/Screenshot_20200413-155923.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/README.assets/Screenshot_20200413-155923.jpg -------------------------------------------------------------------------------- /README.assets/Screenshot_20200413-155925.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/README.assets/Screenshot_20200413-155925.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## WebDroid 2 | 一个简单的Android端混合应用(Hybrid App)生成器,能够把网页打包成APK 3 | 4 | ### 效果图 5 | 6 | 7 | 8 | ### 注意 9 | 10 | * 下载[RELEASE安装包](https://github.com/JankingWon/WebDroid/releases)直接安装或导入工程使用 11 | * **本应用**支持 Android7.0 至 Android9.0 使用 12 | * **生成的应用**支持 Android5.0 至 Android10.0使用 13 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | def signingFilePath = 'signing.gradle' 8 | def performSigning = file(signingFilePath).exists() 9 | if (performSigning) { 10 | apply from: signingFilePath 11 | } 12 | 13 | android { 14 | compileSdkVersion 28 15 | buildToolsVersion "28.0.3" 16 | defaultConfig { 17 | minSdkVersion 21 18 | targetSdkVersion 28 19 | versionCode 1 20 | versionName "1.0" 21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 22 | } 23 | if (performSigning) { 24 | signingConfigs { 25 | release { 26 | storeFile file(project.signing.storeFilePath) 27 | storePassword project.signing.storePassword 28 | keyAlias project.signing.keyAlias 29 | keyPassword project.signing.keyPassword 30 | v1SigningEnabled true 31 | v2SigningEnabled true 32 | } 33 | } 34 | } 35 | buildTypes { 36 | release { 37 | minifyEnabled false 38 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 39 | if (performSigning) { 40 | signingConfig signingConfigs.release 41 | } 42 | } 43 | } 44 | compileOptions { 45 | targetCompatibility 1.8 46 | sourceCompatibility 1.8 47 | } 48 | 49 | } 50 | 51 | tasks.withType(JavaCompile) { 52 | options.encoding = "UTF-8" 53 | } 54 | 55 | dependencies { 56 | implementation project(path: ':xmlparser') 57 | implementation project(path: ':jarsigner') 58 | //MaterialDesign 59 | implementation 'com.google.android.material:material:1.2.0-alpha05' 60 | //EventBus 61 | implementation 'org.greenrobot:eventbus:3.2.0' 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | // compact 64 | implementation 'androidx.appcompat:appcompat:1.1.0' 65 | implementation 'androidx.core:core-ktx:1.2.0' 66 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 67 | //Gson 68 | implementation 'com.google.code.gson:gson:2.8.6' 69 | //Glide 70 | implementation 'com.github.bumptech.glide:glide:4.11.0' 71 | //Downloader 72 | implementation 'com.download.library:Downloader:4.1.3' 73 | annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' 74 | testImplementation 'junit:junit:4.12' 75 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 76 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 77 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/signing.gradle: -------------------------------------------------------------------------------- 1 | ext.signing = [ 2 | storeFilePath : '../janking.jks', 3 | storePassword : '123456', 4 | keyAlias : 'janking', 5 | keyPassword :'123456', 6 | ] -------------------------------------------------------------------------------- /app/src/androidTest/java/com/janking/webDroid/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("cn.janking.webDroid", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 48 | 49 | 55 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/assets/key/webdroid.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/key/webdroid.jks -------------------------------------------------------------------------------- /app/src/main/assets/template/AndroidManifest.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/template/AndroidManifest.xml -------------------------------------------------------------------------------- /app/src/main/assets/template/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "aboutText": "这是使用WebDroid创建出来的App\n欢迎使用!", 3 | "allowOpenApp": 2, 4 | "appIcon": "ic_demo_app.png", 5 | "appName": "Test", 6 | "appPackage": "cn.janking.test", 7 | "tabIcons": [ 8 | "ic_search.png", 9 | "ic_news.png", 10 | "ic_music.png", 11 | "ic_picture.png" 12 | ], 13 | "tabStyle": 1, 14 | "tabTitles": [ 15 | "搜索", 16 | "新闻", 17 | "音乐", 18 | "图片" 19 | ], 20 | "tabUrls": [ 21 | "https://cn.bing.com/", 22 | "https://m.chinanews.com/", 23 | "https://music.mtnhao.com/#/music/playlist", 24 | "https://www.colorhub.me/" 25 | ], 26 | "versionCode": 1, 27 | "versionName": "0.0.1" 28 | } -------------------------------------------------------------------------------- /app/src/main/assets/template/ic_demo_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/template/ic_demo_app.png -------------------------------------------------------------------------------- /app/src/main/assets/template/ic_music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/template/ic_music.png -------------------------------------------------------------------------------- /app/src/main/assets/template/ic_news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/template/ic_news.png -------------------------------------------------------------------------------- /app/src/main/assets/template/ic_picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/template/ic_picture.png -------------------------------------------------------------------------------- /app/src/main/assets/template/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/assets/template/ic_search.png -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/MyApplication.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import cn.janking.webDroid.activity.CreatorActivity 6 | import cn.janking.webDroid.constant.PathConstants 7 | import cn.janking.webDroid.event.InitFinishEvent 8 | 9 | import cn.janking.webDroid.model.Config 10 | import cn.janking.webDroid.util.* 11 | import org.greenrobot.eventbus.EventBus 12 | import java.io.File 13 | import java.io.FileFilter 14 | 15 | /** 16 | * 自定义应用 17 | */ 18 | class MyApplication : Application() { 19 | 20 | 21 | override fun attachBaseContext(base: Context) { 22 | super.attachBaseContext(base) 23 | Utils.init(this) 24 | if (isPreview()) { 25 | init() 26 | } else { 27 | //读取配置 28 | Config.instance.preview = false 29 | Config.readFromString(FileUtils.getFileContent(base.assets.open(PathConstants.CONFIG_FILE))) 30 | } 31 | } 32 | 33 | /** 34 | * 判断当前APP是WebDroidCreator还是WebDroidAPP 35 | */ 36 | private fun isPreview(): Boolean { 37 | val intent = packageManager.getLaunchIntentForPackage(this.packageName); 38 | val launchComponentName = intent?.component; 39 | return launchComponentName?.className == CreatorActivity::class.java.name 40 | } 41 | 42 | /** 43 | * 初始化 44 | */ 45 | private fun init() { 46 | if (SPUtils.getInstance().getBoolean(getString(R.string.key_has_init))) { 47 | EventBus.getDefault().post(InitFinishEvent(true)) 48 | return 49 | } 50 | ThreadUtils.executeByIo(object : ThreadUtils.SimpleTask() { 51 | override fun doInBackground() { 52 | //复制资源 53 | copyAssets("template") 54 | copyAssets("key") 55 | //解压apk 56 | ZipUtils.unzipFile( 57 | File(Utils.getApp().packageResourcePath), 58 | FileUtils.getExistDir(PathConstants.dirUnzippedApk) 59 | ) 60 | //删除原有签名 61 | FileUtils.deleteFilesInDirWithFilter( 62 | PathConstants.dirUnzippedApkMetaINF, 63 | FileFilter { pathname -> 64 | FileUtils.getFileExtension(pathname).run { 65 | equals("MF") || equals("SF") || equals("RSA") 66 | } 67 | } 68 | ) 69 | //删除原有asset 70 | FileUtils.deleteFilesInDirWithFilter( 71 | PathConstants.dirUnzippedApkAssets, 72 | FileFilter { pathname -> 73 | pathname?.name.run { 74 | !equals(PathConstants.CONFIG_FILE) 75 | } 76 | } 77 | ) 78 | } 79 | 80 | override fun onFail(t: Throwable?) { 81 | LogUtils.w("初始化错误") 82 | EventBus.getDefault().post(InitFinishEvent(false)) 83 | t?.printStackTrace() 84 | } 85 | 86 | override fun onSuccess(result: Unit) { 87 | //写入SP中 88 | SPUtils.getInstance().put(getString(R.string.key_has_init), true) 89 | LogUtils.w("初始化完成") 90 | EventBus.getDefault().post(InitFinishEvent(true)) 91 | } 92 | }) 93 | } 94 | 95 | /** 96 | * 复制资源 97 | */ 98 | internal fun copyAssets(assetFolder: String) { 99 | for (name in Utils.getApp().assets.list(assetFolder)!!) { 100 | FileUtils.copyFileToFile( 101 | this.assets.open(assetFolder + File.separator + name), 102 | PathConstants.getSubRoot(assetFolder + File.separator + name) 103 | ) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/activity/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.activity 2 | 3 | import android.os.Bundle 4 | import android.view.KeyEvent 5 | import android.view.Menu 6 | import android.view.MenuItem 7 | import android.view.View 8 | import android.widget.LinearLayout 9 | import androidx.appcompat.app.ActionBarDrawerToggle 10 | import androidx.appcompat.app.AppCompatActivity 11 | import androidx.core.view.GravityCompat 12 | import cn.janking.webDroid.R 13 | import cn.janking.webDroid.model.Config 14 | import com.google.android.material.navigation.NavigationView 15 | import kotlinx.android.synthetic.main.activity_creator.* 16 | import kotlinx.android.synthetic.main.layout_nav.* 17 | 18 | /** 19 | * @author Janking 20 | */ 21 | abstract class BaseActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, 22 | View.OnClickListener { 23 | /** 24 | * 布局ID 25 | */ 26 | abstract val layoutId: Int 27 | 28 | /** 29 | * toolbar右边菜单id 30 | */ 31 | open val toolBarMenuId: Int? = null 32 | 33 | override fun onCreate(savedInstanceState: Bundle?) { 34 | super.onCreate(savedInstanceState) 35 | setContentView(layoutId) 36 | initToolBar() 37 | initViews() 38 | } 39 | 40 | /** 41 | * toolbar右边的菜单 42 | */ 43 | override fun onCreateOptionsMenu(menu: Menu?): Boolean { 44 | toolBarMenuId?.let { 45 | menuInflater.inflate(it, menu) 46 | return true 47 | } 48 | return false 49 | } 50 | 51 | /** 52 | * toolbar右边的菜单 点击事件 53 | */ 54 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 55 | onClickViewId(item.itemId) 56 | return super.onOptionsItemSelected(item) 57 | } 58 | 59 | 60 | protected open fun initToolBar() { 61 | initToolBarTitle() 62 | setSupportActionBar(toolbar) 63 | val toggle = ActionBarDrawerToggle( 64 | this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close 65 | ) 66 | drawer.addDrawerListener(toggle) 67 | toggle.syncState() 68 | drawerNavigation.setNavigationItemSelectedListener(this) 69 | drawerNavigation.getHeaderView(0).findViewById(R.id.navHeader) 70 | .setOnClickListener(this) 71 | } 72 | 73 | abstract fun initToolBarTitle() 74 | 75 | /** 76 | * 点击侧边导航栏的菜单 77 | */ 78 | override fun onNavigationItemSelected(item: MenuItem): Boolean { 79 | onClickViewId(item.itemId) 80 | drawer.closeDrawer(GravityCompat.START) 81 | return true 82 | } 83 | 84 | 85 | override fun onClick(v: View?) { 86 | v?.let { 87 | onClickViewId(it.id) 88 | } 89 | } 90 | 91 | /** 92 | * 根据view的id判断点击事件 93 | * 集中处理点击事件 94 | */ 95 | protected open fun onClickViewId(viewId: Int) { 96 | when (viewId) { 97 | /*toolbar菜单*/ 98 | 99 | /*侧边导航栏header*/ 100 | R.id.navHeader -> { 101 | 102 | } 103 | /*侧边导航栏菜单*/ 104 | R.id.nav_settings -> { 105 | 106 | } 107 | } 108 | } 109 | 110 | /** 111 | * 对view初始化 112 | */ 113 | protected open fun initViews() { 114 | drawerVersion.text = "版本:${Config.instance.versionName}" 115 | } 116 | 117 | /** 118 | * 统一监听返回键 119 | */ 120 | override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { 121 | return if (keyCode == KeyEvent.KEYCODE_BACK && drawer.isDrawerOpen(GravityCompat.START)) { 122 | drawer.closeDrawer(GravityCompat.START) 123 | true 124 | } else if (handleKeyEvent(keyCode, event)) { 125 | true 126 | } else { 127 | super.onKeyDown(keyCode, event) 128 | } 129 | } 130 | 131 | /** 132 | * 返回true表示返回事件已经处理 133 | */ 134 | protected open fun handleKeyEvent(keyCode: Int, event: KeyEvent?): Boolean { 135 | return false 136 | } 137 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/adapter/BasicPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.adapter 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import androidx.viewpager.widget.PagerAdapter 6 | 7 | /** 8 | * @author Janking 9 | */ 10 | abstract class BasicPagerAdapter : PagerAdapter() { 11 | override fun isViewFromObject(view: View, `object`: Any): Boolean { 12 | return view === `object` 13 | } 14 | 15 | /** 16 | * 需要重写 17 | */ 18 | /* override fun getCount(): Int { 19 | return 0 20 | }*/ 21 | 22 | /** 23 | * 需要重写 24 | */ 25 | /* override fun instantiateItem(container: ViewGroup, position: Int): Any { 26 | return null 27 | }*/ 28 | 29 | override fun destroyItem( 30 | container: ViewGroup, 31 | position: Int, 32 | `object`: Any 33 | ) { 34 | container.removeView(`object` as View) 35 | } 36 | 37 | /** 38 | * 需要重写 39 | */ 40 | /* override fun getPageTitle(position: Int): CharSequence? { 41 | 42 | }*/ 43 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/adapter/ItemTouchHelperCallback.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.adapter 2 | 3 | import androidx.recyclerview.widget.GridLayoutManager 4 | import androidx.recyclerview.widget.ItemTouchHelper 5 | import androidx.recyclerview.widget.RecyclerView 6 | 7 | /** 8 | * RecyclerView拖动和滑动删除的手势操作 9 | */ 10 | class ItemTouchHelperCallback(private val moveAndSwipedListener: OnMoveAndSwipedListener) : 11 | ItemTouchHelper.Callback() { 12 | private val typeNormal = 1 13 | override fun getMovementFlags( 14 | recyclerView: RecyclerView, 15 | viewHolder: RecyclerView.ViewHolder 16 | ): Int { 17 | return if (recyclerView.layoutManager is GridLayoutManager) { 18 | // 支持上下左右拖动,不支持删除 19 | val dragFlags = 20 | ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT 21 | val swipeFlags = 0 22 | makeMovementFlags( 23 | dragFlags, 24 | swipeFlags 25 | ) 26 | } else { 27 | //支持上下拖动,支持左右删除 28 | if (viewHolder.itemViewType == typeNormal) { 29 | val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN 30 | val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END 31 | makeMovementFlags( 32 | dragFlags, 33 | swipeFlags 34 | ) 35 | } else { 36 | 0 37 | } 38 | } 39 | } 40 | 41 | /** 42 | * 滑动移动 43 | */ 44 | override fun onMove( 45 | recyclerView: RecyclerView, 46 | viewHolder: RecyclerView.ViewHolder, 47 | target: RecyclerView.ViewHolder 48 | ): Boolean { 49 | //只支持同样类型的ITEM 50 | if (viewHolder.itemViewType != target.itemViewType) { 51 | return false 52 | } 53 | if (viewHolder is TabItemViewHolder && target is TabItemViewHolder) { 54 | viewHolder.tabItemTitle.clearFocus() 55 | viewHolder.tabItemUrl.clearFocus() 56 | target.tabItemTitle.clearFocus() 57 | target.tabItemUrl.clearFocus() 58 | } 59 | //回调 60 | moveAndSwipedListener.onItemMove( 61 | viewHolder.adapterPosition, 62 | target.adapterPosition 63 | ) 64 | return true 65 | } 66 | 67 | /** 68 | * 滑动删除 69 | */ 70 | override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { 71 | //回调 72 | moveAndSwipedListener.onItemDismiss(viewHolder.adapterPosition) 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/adapter/OnMoveAndSwipedListener.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.adapter 2 | 3 | /** 4 | * 拖动和滑动删除的监听器 5 | */ 6 | interface OnMoveAndSwipedListener { 7 | fun onItemMove(fromPosition: Int, toPosition: Int): Boolean 8 | fun onItemDismiss(position: Int) 9 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/constant/WebConstants.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.constant 2 | 3 | /** 4 | * @author Janking 5 | */ 6 | object WebConstants{ 7 | /** 8 | * INTENT 9 | */ 10 | const val INTENT_SCHEME = "intent" 11 | /** 12 | * 微信支付 13 | */ 14 | const val WEBCHAT_PAY_SCHEME = "weixin://wap/pay?" 15 | /** 16 | * 支付宝 17 | */ 18 | const val ALIPAYS_SCHEME = "alipays" 19 | /** 20 | * http scheme 21 | */ 22 | const val HTTP_SCHEME = "http" 23 | /** 24 | * https scheme 25 | */ 26 | const val HTTPS_SCHEME = "https" 27 | /** 28 | * SMS scheme 29 | */ 30 | const val SCHEME_SMS = "sms" 31 | const val SCHEME_TEL = "tel" 32 | const val SCHEME_MAILTO = "mailto" 33 | const val SCHEME_GEO = "geo" 34 | 35 | const val USERAGENT_UC = " UCBrowser/11.6.4.950 " 36 | const val USERAGENT_QQ_BROWSER = " MQQBrowser/8.0 " 37 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/event/event.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.event 2 | 3 | /** 4 | * @author Janking 5 | */ 6 | 7 | /** 8 | * 用于传递打包过程结束的信息 9 | */ 10 | class BuildFinishEvent 11 | 12 | /** 13 | * 用于结束打包任务的信息 14 | */ 15 | class CancelBuildEvent 16 | 17 | /** 18 | * 用于传达初始化完成的信息 19 | */ 20 | class InitFinishEvent(val success: Boolean) -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/helper/DialogHelper.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.helper 2 | 3 | import android.app.AlertDialog 4 | import android.content.DialogInterface 5 | import android.os.Handler 6 | import android.os.Message 7 | import cn.janking.webDroid.R 8 | import cn.janking.webDroid.util.* 9 | import com.bumptech.glide.util.Util 10 | 11 | /** 12 | */ 13 | object DialogHelper { 14 | 15 | /** 16 | * 提示用户允许权限 17 | */ 18 | fun showRationaleDialog(shouldRequest: PermissionUtils.OnRationaleListener.ShouldRequest) { 19 | val topActivity = ActivityUtils.getTopActivity() ?: return 20 | AlertDialog.Builder(topActivity) 21 | .setTitle(android.R.string.dialog_alert_title) 22 | .setMessage("You have rejected us to apply for authorization, please agree to authorization, otherwise the function can\\'t be used normally!") 23 | .setPositiveButton(android.R.string.ok) { dialog, _ -> 24 | shouldRequest.again(true) 25 | dialog.dismiss() 26 | } 27 | .setNegativeButton(android.R.string.cancel) { dialog, _ -> 28 | shouldRequest.again(false) 29 | dialog.dismiss() 30 | }.show() 31 | } 32 | 33 | /** 34 | * 打开App权限设置页面 35 | */ 36 | fun showOpenAppSettingDialog() { 37 | val topActivity = ActivityUtils.getTopActivity() ?: return 38 | AlertDialog.Builder(topActivity) 39 | .setTitle(android.R.string.dialog_alert_title) 40 | .setMessage("We need some of the permissions you rejected or the system failed to apply failed, please manually set to the page authorize, otherwise the function can\\'t be used normally!") 41 | .setPositiveButton(android.R.string.ok) { dialog, _ -> 42 | PermissionUtils.launchAppDetailsSettings() 43 | dialog.dismiss() 44 | } 45 | .setNegativeButton(android.R.string.cancel) { dialog, _ -> 46 | dialog.dismiss() 47 | }.show() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/helper/PermissionHelper.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.helper 2 | 3 | import cn.janking.webDroid.constant.PermissionConstants 4 | import cn.janking.webDroid.util.LogUtils 5 | import cn.janking.webDroid.util.PermissionUtils 6 | import kotlinx.android.synthetic.main.activity_creator.* 7 | 8 | /** 9 | * ``` 10 | * author: Blankj 11 | * blog : http://blankj.com 12 | * time : 2018/01/06 13 | * desc : helper about permission 14 | * ``` 15 | */ 16 | object PermissionHelper { 17 | /** 18 | * 检查是否有存储权限 19 | */ 20 | fun checkStorage( 21 | grantedListener: Runnable, 22 | deniedListener: Runnable? = null 23 | ) { 24 | checkPermission(PermissionConstants.STORAGE, grantedListener, deniedListener) 25 | } 26 | 27 | private fun checkPermission( 28 | @PermissionConstants.Permission permission: String, 29 | grantedListener: Runnable, 30 | deniedListener: Runnable? = null 31 | ) { 32 | //之所以要多多余这个判断是PermissionUtils会调用透明请求的Activity,导致屏幕闪烁 33 | if(PermissionUtils.isGranted(PermissionConstants.STORAGE)){ 34 | grantedListener.run() 35 | return 36 | } 37 | PermissionUtils.permission(permission) 38 | .callback(object : PermissionUtils.FullCallback { 39 | override fun onGranted(permissionsGranted: List) { 40 | LogUtils.d(permissionsGranted) 41 | grantedListener.run() 42 | } 43 | 44 | override fun onDenied( 45 | permissionsDeniedForever: List, 46 | permissionsDenied: List 47 | ) { 48 | LogUtils.d(permissionsDeniedForever, permissionsDenied) 49 | deniedListener?.run() 50 | //如果选择了“拒绝后不再询问”,则引导打开权限设置页面 51 | // if (permissionsDeniedForever.isNotEmpty()) { 52 | // DialogHelper.showOpenAppSettingDialog() 53 | // return 54 | // } 55 | } 56 | }) 57 | .request() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/layout/EditLayout.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.layout 2 | 3 | import android.view.View 4 | 5 | /** 6 | * @author Janking 7 | */ 8 | abstract class EditLayout { 9 | abstract val contentView : View 10 | 11 | abstract fun loadConfig() 12 | 13 | abstract fun generateConfig() 14 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/layout/EditTabLayout.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.layout 2 | 3 | import android.app.Activity 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.widget.ImageButton 7 | import android.widget.ImageView 8 | import android.widget.LinearLayout 9 | import android.widget.RadioGroup 10 | import androidx.core.view.get 11 | import androidx.recyclerview.widget.ItemTouchHelper 12 | import androidx.recyclerview.widget.LinearLayoutManager 13 | import androidx.recyclerview.widget.RecyclerView 14 | import cn.janking.webDroid.R 15 | import cn.janking.webDroid.adapter.ItemTouchHelperCallback 16 | import cn.janking.webDroid.adapter.TabListRVAdapter 17 | import cn.janking.webDroid.model.Config 18 | 19 | /** 20 | * @author Janking 21 | */ 22 | class EditTabLayout(activity: Activity) : EditLayout() { 23 | /** 24 | * 视图 25 | */ 26 | override val contentView = LayoutInflater.from(activity) 27 | .inflate(R.layout.layout_edit_tab, null) as LinearLayout 28 | 29 | /** 30 | * 配置tab列表的适配器 31 | */ 32 | var tabListAdapter: TabListRVAdapter = TabListRVAdapter() 33 | 34 | /** 35 | * 添加Tab 36 | */ 37 | val addTab = contentView.findViewById(R.id.addTab).apply { 38 | setOnClickListener { 39 | tabListAdapter.addTabItem() 40 | } 41 | } 42 | 43 | /** 44 | * 编辑tab列表 45 | */ 46 | val tabList = contentView.findViewById(R.id.tabList).apply { 47 | //tab设置 48 | layoutManager = LinearLayoutManager(activity) 49 | adapter = tabListAdapter 50 | } 51 | 52 | /** 53 | * tab样式 54 | */ 55 | val tabStyle = contentView.findViewById(R.id.itemTabStyle).apply { 56 | setOnCheckedChangeListener { group, checkedId -> 57 | if (checkedId == R.id.itemTabStyleTop) { 58 | for (i in 0 until tabList.childCount) { 59 | tabList[i].findViewById(R.id.itemTabIcon).visibility = View.GONE 60 | } 61 | //即时更新config 62 | Config.instance.tabStyle = 0 63 | } else if (checkedId == R.id.itemTabStyleBottom) { 64 | for (i in 0 until tabList.childCount) { 65 | tabList[i].findViewById(R.id.itemTabIcon).visibility = View.VISIBLE 66 | } 67 | //即时更新config 68 | Config.instance.tabStyle = 1 69 | } 70 | } 71 | } 72 | 73 | init { 74 | //tab滑动删除和移动的手势操作 75 | val callback: ItemTouchHelper.Callback = ItemTouchHelperCallback(tabListAdapter) 76 | val mItemTouchHelper = ItemTouchHelper(callback) 77 | mItemTouchHelper.attachToRecyclerView(tabList) 78 | //load 79 | loadConfig() 80 | } 81 | 82 | override fun loadConfig() { 83 | tabListAdapter.clearAllTab() 84 | for (i in 0 until Config.instance.tabCount) { 85 | tabListAdapter.addTabItem( 86 | Config.instance.tabTitles[i], 87 | Config.instance.tabUrls[i], 88 | Config.instance.tabIcons[i] 89 | ) 90 | } 91 | } 92 | 93 | override fun generateConfig() { 94 | tabListAdapter.generateConfig(tabList.layoutManager) 95 | } 96 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/model/Config.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.model 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.JsonSyntaxException 5 | import java.io.Serializable 6 | 7 | /** 8 | * 用于webDroid的配置项 9 | */ 10 | class Config private constructor() : Serializable { 11 | /** 12 | * 是否是预览模式 13 | */ 14 | @Transient 15 | var preview = false 16 | 17 | /** 18 | * APP的名称 19 | */ 20 | var appName = "" 21 | 22 | /** 23 | * APP包名 24 | */ 25 | var appPackage = "" 26 | 27 | /** 28 | * APP图标 29 | */ 30 | var appIcon = "" 31 | 32 | /** 33 | * 版本名称 34 | */ 35 | var versionName = "1.0.0" 36 | 37 | /** 38 | * 版本代码 39 | */ 40 | var versionCode = 1 41 | 42 | /** 43 | * tab的标题集合 44 | */ 45 | var tabTitles: List = List(0) { "" } 46 | 47 | /** 48 | * viewPager的url集合 49 | */ 50 | var tabUrls: List = List(0) { "" } 51 | 52 | /** 53 | * tab的icon集合,表示文件位置 54 | */ 55 | var tabIcons: MutableList = ArrayList(List(0) { "" }) 56 | 57 | /** 58 | * tab的个数 59 | */ 60 | @Transient 61 | var tabCount = 0 62 | 63 | /** 64 | * tab的风格 65 | * 0 : top 66 | * 1 : bottom 67 | */ 68 | var tabStyle = 1 69 | 70 | /** 71 | * 是否允许打开第三方应用 72 | * 0 : not allow 73 | * 1 : ask user 74 | * 2 : always allow 75 | */ 76 | var allowOpenApp = 0 77 | 78 | var aboutText = "" 79 | 80 | companion object { 81 | private val gson = Gson() 82 | 83 | /** 84 | * 单例 85 | */ 86 | var instance: Config = Config() 87 | private set 88 | 89 | /** 90 | * 读取json字符串 91 | */ 92 | @Throws(JsonSyntaxException::class) 93 | fun readFromString(configString: String?) { 94 | instance = gson.fromJson( 95 | configString, 96 | Config::class.java 97 | ).let { 98 | it?.apply { 99 | tabCount = tabTitles.size.coerceAtMost(tabUrls.size).coerceAtMost(tabIcons.size) 100 | } ?: Config() 101 | } 102 | } 103 | 104 | /** 105 | * 生成json配置文件 106 | */ 107 | fun toJsonString(): String { 108 | return gson.toJson(instance) 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/util/ConsoleUtils.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.util 2 | 3 | import android.widget.TextView 4 | import cn.janking.webDroid.R 5 | 6 | /** 7 | * 可视化输出的工具类 8 | */ 9 | class ConsoleUtils { 10 | companion object { 11 | 12 | fun info(console: TextView?, message: String) { 13 | console?.let { 14 | SpanUtils.with(it) 15 | .appendLine(message) 16 | .create() 17 | } 18 | } 19 | 20 | /** 21 | * 保留原有输出添加info信息 22 | */ 23 | fun infoAppend(console: TextView?, message: String) { 24 | console?.let { 25 | SpanUtils.with(it) 26 | .append(it.text) 27 | .appendLine(message) 28 | .create() 29 | } 30 | } 31 | 32 | fun warning(console: TextView?, message: String) { 33 | console?.let { 34 | SpanUtils.with(it) 35 | .appendLine(message) 36 | .setForegroundColor(ColorUtils.getColor(R.color.rainbow_yellow)) 37 | .create() 38 | } 39 | } 40 | 41 | fun error(console: TextView?, message: String) { 42 | console?.let { 43 | SpanUtils.with(it) 44 | .appendLine(message) 45 | .setForegroundColor(ColorUtils.getColor(R.color.rainbow_red)) 46 | .create() 47 | } 48 | } 49 | 50 | fun success(console: TextView?, message: String) { 51 | console?.let { 52 | SpanUtils.with(it) 53 | .appendLine(message) 54 | .setForegroundColor(ColorUtils.getColor(R.color.loveGreen)) 55 | .create() 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/util/DialogUtils.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.util 2 | 3 | import android.app.AlertDialog 4 | import cn.janking.webDroid.R 5 | 6 | /** 7 | * @author Janking 8 | */ 9 | object DialogUtils { 10 | 11 | fun showAlertDialog( 12 | message: Int, 13 | positiveListener: Runnable, 14 | negativeListener: Runnable? = null 15 | ) { 16 | showAlertDialog( 17 | Utils.getApp().resources.getString(message), 18 | positiveListener, 19 | negativeListener 20 | ) 21 | } 22 | 23 | fun showMessageDialog( 24 | message: CharSequence 25 | ) { 26 | AlertDialog.Builder(ActivityUtils.getTopActivity()) 27 | .setTitle(R.string.msg_note) 28 | .setMessage( 29 | message 30 | ) 31 | .setPositiveButton( 32 | android.R.string.ok 33 | ) { _, _ -> 34 | } 35 | .show() 36 | } 37 | 38 | /** 39 | * 统一显示dialog 40 | */ 41 | fun showAlertDialog( 42 | message: CharSequence, 43 | positiveListener: Runnable? = null, 44 | negativeListener: Runnable? = null 45 | ) { 46 | AlertDialog.Builder(ActivityUtils.getTopActivity()) 47 | .setTitle(R.string.msg_note) 48 | .setMessage( 49 | message 50 | ) 51 | .setNegativeButton( 52 | android.R.string.cancel 53 | ) { _, _ -> 54 | negativeListener?.run() 55 | } 56 | .setPositiveButton( 57 | android.R.string.ok 58 | ) { _, _ -> 59 | positiveListener?.run() 60 | } 61 | .show() 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/util/ThrowableUtils.java: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.StringTokenizer; 8 | 9 | /** 10 | *
11 |  *     author: Blankj
12 |  *     blog  : http://blankj.com
13 |  *     time  : 2019/02/12
14 |  *     desc  : utils about exception
15 |  * 
16 | */ 17 | public class ThrowableUtils { 18 | 19 | private static final String LINE_SEP = System.getProperty("line.separator"); 20 | 21 | private ThrowableUtils() { 22 | throw new UnsupportedOperationException("u can't instantiate me..."); 23 | } 24 | 25 | public static String getFullStackTrace(Throwable throwable) { 26 | final List throwableList = new ArrayList<>(); 27 | while (throwable != null && !throwableList.contains(throwable)) { 28 | throwableList.add(throwable); 29 | throwable = throwable.getCause(); 30 | } 31 | final int size = throwableList.size(); 32 | final List frames = new ArrayList<>(); 33 | List nextTrace = getStackFrameList(throwableList.get(size - 1)); 34 | for (int i = size; --i >= 0; ) { 35 | final List trace = nextTrace; 36 | if (i != 0) { 37 | nextTrace = getStackFrameList(throwableList.get(i - 1)); 38 | removeCommonFrames(trace, nextTrace); 39 | } 40 | if (i == size - 1) { 41 | frames.add(throwableList.get(i).toString()); 42 | } else { 43 | frames.add(" Caused by: " + throwableList.get(i).toString()); 44 | } 45 | frames.addAll(trace); 46 | } 47 | StringBuilder sb = new StringBuilder(); 48 | for (final String element : frames) { 49 | sb.append(element).append(LINE_SEP); 50 | } 51 | return sb.toString(); 52 | } 53 | 54 | private static List getStackFrameList(final Throwable throwable) { 55 | final StringWriter sw = new StringWriter(); 56 | final PrintWriter pw = new PrintWriter(sw, true); 57 | throwable.printStackTrace(pw); 58 | final String stackTrace = sw.toString(); 59 | final StringTokenizer frames = new StringTokenizer(stackTrace, LINE_SEP); 60 | final List list = new ArrayList<>(); 61 | boolean traceStarted = false; 62 | while (frames.hasMoreTokens()) { 63 | final String token = frames.nextToken(); 64 | // Determine if the line starts with at 65 | final int at = token.indexOf("at"); 66 | if (at != -1 && token.substring(0, at).trim().isEmpty()) { 67 | traceStarted = true; 68 | list.add(token); 69 | } else if (traceStarted) { 70 | break; 71 | } 72 | } 73 | return list; 74 | } 75 | 76 | private static void removeCommonFrames(final List causeFrames, final List wrapperFrames) { 77 | int causeFrameIndex = causeFrames.size() - 1; 78 | int wrapperFrameIndex = wrapperFrames.size() - 1; 79 | while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) { 80 | // Remove the frame from the cause trace if it is the same 81 | // as in the wrapper trace 82 | final String causeFrame = causeFrames.get(causeFrameIndex); 83 | final String wrapperFrame = wrapperFrames.get(wrapperFrameIndex); 84 | if (causeFrame.equals(wrapperFrame)) { 85 | causeFrames.remove(causeFrameIndex); 86 | } 87 | causeFrameIndex--; 88 | wrapperFrameIndex--; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/util/WebUtils.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.util 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.net.ConnectivityManager 6 | import android.telephony.TelephonyManager 7 | import android.webkit.CookieManager 8 | 9 | /** 10 | * @author Janking 11 | */ 12 | object WebUtils { 13 | /** 14 | * 检查网络状态 15 | */ 16 | fun networkAvailable(): Boolean { 17 | val connectivity = 18 | Utils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 19 | @SuppressLint("MissingPermission") val info = 20 | connectivity.activeNetworkInfo 21 | return info != null && info.isConnected 22 | } 23 | 24 | /** 25 | * 获取Cookie 26 | */ 27 | fun getCookiesByUrl(url: String?): String? { 28 | return if (CookieManager.getInstance() == null) null else CookieManager.getInstance().getCookie( 29 | url 30 | ) 31 | } 32 | 33 | /** 34 | * 检查网络类型 35 | */ 36 | fun checkNetworkType(): Int { 37 | val netType = 0 38 | //连接管理对象 39 | val manager = 40 | Utils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 41 | //获取NetworkInfo对象 42 | val networkInfo = manager.activeNetworkInfo ?: return netType 43 | return when (networkInfo.type) { 44 | ConnectivityManager.TYPE_WIFI, ConnectivityManager.TYPE_WIMAX, ConnectivityManager.TYPE_ETHERNET -> 1 45 | ConnectivityManager.TYPE_MOBILE -> when (networkInfo.subtype) { 46 | TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_EHRPD -> 2 47 | TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> 3 48 | TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE -> 4 49 | else -> netType 50 | } 51 | else -> netType 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/FilePathChooserCallback.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web 2 | 3 | import android.net.Uri 4 | 5 | /** 6 | * @author Janking 7 | */ 8 | interface FilePathChooserCallback { 9 | fun onChooseFile(uris: Array) 10 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/WebConfig.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web 2 | 3 | /** 4 | * @author Janking 5 | */ 6 | object WebConfig{ 7 | /** 8 | * 打开文件页面的请求码 9 | */ 10 | const val SELECT_FILE_REQUEST_CODE = 99 11 | /** 12 | * 直接打开其他页面 13 | */ 14 | const val DIRECT_OPEN_OTHER_PAGE = 2 15 | /** 16 | * 弹窗咨询用户是否前往其他页面 17 | */ 18 | val ASK_USER_OPEN_OTHER_PAGE: Int = 1 19 | /** 20 | * 不允许打开其他页面 21 | */ 22 | val DISALLOW_OPEN_OTHER_APP: Int = 0 23 | /** 24 | * 是否是debug模式 25 | */ 26 | val DEBUG = true 27 | /** 28 | * 打开外部链接的方式 29 | */ 30 | var handleOpenUrl = ASK_USER_OPEN_OTHER_PAGE 31 | /** 32 | * 是否拦截未知应用 33 | */ 34 | val interceptUnknownUrl = true 35 | /** 36 | * 缩放 37 | */ 38 | val abnormalScale = 7 39 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/WebFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | 9 | /** 10 | * @author Janking 11 | */ 12 | class WebFragment(val webBox: WebBox) : Fragment() { 13 | override fun onCreateView( 14 | inflater: LayoutInflater, 15 | container: ViewGroup?, 16 | savedInstanceState: Bundle? 17 | ): View? { 18 | return webBox.webLayout 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/WebVideoPlayer.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web; 2 | 3 | import android.app.Activity 4 | import android.content.pm.ActivityInfo 5 | import android.graphics.Color 6 | import android.util.Pair 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.view.WindowManager 10 | import android.webkit.WebChromeClient 11 | import android.webkit.WebView 12 | import android.widget.FrameLayout 13 | import java.util.* 14 | 15 | /** 16 | * @author Janking 17 | */ 18 | class WebVideoPlayer(private val activity: Activity, private val webViw: WebView?) { 19 | private var mFlags: MutableSet> = HashSet() 20 | private var videoView: View? = null 21 | private var videoLayout: ViewGroup? = null 22 | private var mCallback: WebChromeClient.CustomViewCallback? = null 23 | init { 24 | mFlags = HashSet() 25 | } 26 | 27 | /** 28 | * 播放视频 29 | */ 30 | fun onShowCustomView( 31 | view: View?, 32 | callback: WebChromeClient.CustomViewCallback? 33 | ) { 34 | //表示正在显示自定义View 35 | if (videoView != null) { 36 | callback?.onCustomViewHidden() 37 | return 38 | } 39 | //切换全屏 40 | activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE 41 | val mWindow = activity.window 42 | var mPair: Pair? 43 | // 保存当前屏幕的状态 44 | if (mWindow.attributes.flags and WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON == 0) { 45 | mPair = Pair( 46 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 47 | 0 48 | ) 49 | mWindow.setFlags( 50 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 51 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 52 | ) 53 | mFlags.add(mPair) 54 | } 55 | mPair = Pair( 56 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 57 | 0 58 | ) 59 | mWindow.setFlags( 60 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 61 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED 62 | ) 63 | mFlags.add(mPair) 64 | webViw?.visibility = View.GONE 65 | //添加视频布局 66 | if (videoLayout == null) { 67 | val mDecorView = 68 | activity.window.decorView as FrameLayout 69 | mDecorView.addView(FrameLayout(activity).also { 70 | it.setBackgroundColor(Color.BLACK) 71 | videoLayout = it 72 | }) 73 | } 74 | mCallback = callback 75 | videoLayout!!.addView(view.also { videoView = it }) 76 | videoLayout!!.visibility = View.VISIBLE 77 | } 78 | 79 | 80 | /** 81 | * 退出全屏播放 82 | */ 83 | fun onHideCustomView() { 84 | if (videoView == null) { 85 | return 86 | } 87 | //取消全屏 88 | if (activity.requestedOrientation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { 89 | activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT 90 | } 91 | //恢复flag 92 | if (mFlags.isNotEmpty()) { 93 | for (mPair in mFlags) { 94 | activity.window.setFlags(mPair.second, mPair.first!!) 95 | } 96 | mFlags.clear() 97 | } 98 | //去掉视频的View 99 | videoView!!.visibility = View.GONE 100 | videoLayout?.also { 101 | it.removeView(videoView) 102 | it.visibility = View.GONE 103 | } 104 | mCallback?.onCustomViewHidden() 105 | videoView = null 106 | webViw?.visibility = View.VISIBLE 107 | } 108 | 109 | 110 | /** 111 | * 处理返回事件 112 | */ 113 | fun handleKeyEvent(): Boolean { 114 | return if (videoView != null) { 115 | //退出全屏 116 | onHideCustomView() 117 | true 118 | } else { 119 | false 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/extend/WebChromeClientExtend.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web.extend 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.view.View 6 | import android.webkit.* 7 | import cn.janking.webDroid.R 8 | import cn.janking.webDroid.util.* 9 | import cn.janking.webDroid.web.FilePathChooserCallback 10 | import cn.janking.webDroid.web.WebConfig 11 | import cn.janking.webDroid.web.WebVideoPlayer 12 | 13 | /** 14 | * @author Janking 15 | */ 16 | fun WebView.defaultWebChromeClient(webVideoPlayer: WebVideoPlayer): FilePathChooserCallback { 17 | return DefaultWebChromeClient(webVideoPlayer).also { 18 | webChromeClient = it 19 | } 20 | } 21 | 22 | 23 | class DefaultWebChromeClient(private val webVideoPlayer: WebVideoPlayer?) : WebChromeClient(), 24 | FilePathChooserCallback { 25 | 26 | /** 27 | * 重载自定义页面,如播放视频 28 | */ 29 | override fun onShowCustomView(view: View?, callback: CustomViewCallback?) { 30 | webVideoPlayer?.onShowCustomView(view, callback) 31 | } 32 | 33 | /** 34 | * 重载结束自定义页面,如播放视频 35 | */ 36 | override fun onHideCustomView() { 37 | webVideoPlayer?.onHideCustomView() 38 | } 39 | 40 | /** 41 | * 重载JS的console输出 42 | */ 43 | override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean { 44 | LogUtils.i("JS", consoleMessage?.message()) 45 | return true 46 | } 47 | 48 | override fun onPermissionRequest(request: PermissionRequest?) { 49 | super.onPermissionRequest(request) 50 | } 51 | 52 | override fun onPermissionRequestCanceled(request: PermissionRequest?) { 53 | super.onPermissionRequestCanceled(request) 54 | } 55 | 56 | /** 57 | * 重载询问位置权限的对话框 58 | */ 59 | override fun onGeolocationPermissionsShowPrompt( 60 | origin: String?, 61 | callback: GeolocationPermissions.Callback? 62 | ) { 63 | DialogUtils.showAlertDialog( 64 | Utils.getString(R.string.msg_request_geo_permission, origin), 65 | Runnable { callback?.invoke(origin, true, false) }, 66 | Runnable { callback?.invoke(origin, false, true) } 67 | ) 68 | } 69 | 70 | var filePathCallback: ValueCallback>? = null 71 | 72 | /** 73 | * 重载选择文件的操作 74 | */ 75 | override fun onShowFileChooser( 76 | webView: WebView?, 77 | filePathCallback: ValueCallback>?, 78 | fileChooserParams: FileChooserParams? 79 | ): Boolean { 80 | this.filePathCallback = filePathCallback 81 | //先自动创建Intent 82 | fileChooserParams?.let { 83 | it.createIntent()?.run { 84 | if (it.mode == FileChooserParams.MODE_OPEN_MULTIPLE) { 85 | putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) 86 | } 87 | if (action == Intent.ACTION_GET_CONTENT) { 88 | action == Intent.ACTION_OPEN_DOCUMENT 89 | } 90 | ActivityUtils.startActivityForResult( 91 | ActivityUtils.getTopActivity(), 92 | this, 93 | WebConfig.SELECT_FILE_REQUEST_CODE 94 | ) 95 | return true 96 | } 97 | //创建失败的话默认选择所有类型 98 | OpenUtils.toSelectFile("*/*", WebConfig.SELECT_FILE_REQUEST_CODE) 99 | } 100 | return true 101 | } 102 | 103 | /** 104 | * 选择文件返回的回调 105 | */ 106 | override fun onChooseFile(uris: Array) { 107 | filePathCallback?.onReceiveValue(uris) 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/extend/WebDownloadExtend.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web.extend 2 | 3 | import android.net.Uri 4 | import android.webkit.DownloadListener 5 | import android.webkit.WebView 6 | import android.widget.Toast 7 | import cn.janking.webDroid.R 8 | import cn.janking.webDroid.helper.PermissionHelper 9 | import cn.janking.webDroid.util.DialogUtils 10 | import cn.janking.webDroid.util.LogUtils 11 | import cn.janking.webDroid.util.Utils 12 | import cn.janking.webDroid.util.WebUtils 13 | import cn.janking.webDroid.web.WebConfig 14 | import com.download.library.DownloadImpl 15 | import com.download.library.DownloadListenerAdapter 16 | import com.download.library.Extra 17 | import com.download.library.ResourceRequest 18 | import java.util.concurrent.ConcurrentHashMap 19 | 20 | /** 21 | * @author Janking 22 | * 设置下载器 23 | */ 24 | fun WebView.defaultDownloadListener() { 25 | setDownloadListener(DefaultDownloadImpl()) 26 | } 27 | 28 | open class DefaultDownloadImpl : DownloadListener { 29 | /** 30 | * 保存下载请求 31 | */ 32 | protected var mDownloadTasks = 33 | ConcurrentHashMap>() 34 | /** 35 | * 重载DownloadListener,下载任务开始时调用 36 | */ 37 | override fun onDownloadStart( 38 | url: String, 39 | userAgent: String, 40 | contentDisposition: String, 41 | mimetype: String, 42 | contentLength: Long 43 | ) { 44 | val resourceRequest = DownloadImpl 45 | .getInstance() 46 | .with(Utils.getApp()) 47 | .url(url) 48 | .setEnableIndicator(true) 49 | .autoOpenIgnoreMD5() 50 | mDownloadTasks[url] = resourceRequest 51 | PermissionHelper.checkStorage(Runnable { 52 | determineDownload(url) 53 | }) 54 | } 55 | 56 | 57 | /** 58 | * 判断网络 59 | */ 60 | private fun determineDownload(url: String) { 61 | // 移动数据 62 | if (WebUtils.checkNetworkType() > 1) { 63 | DialogUtils.showAlertDialog( 64 | R.string.msg_use_cellular_network, 65 | Runnable { 66 | performDownload(url) 67 | } 68 | ) 69 | return 70 | }else{ 71 | performDownload(url) 72 | } 73 | } 74 | 75 | 76 | /** 77 | * 执行下载 78 | */ 79 | private fun performDownload(url: String) { 80 | try { 81 | LogUtils.i( 82 | "download:$url", 83 | "exist:" + DownloadImpl.getInstance().exist(url) 84 | ) 85 | // 该链接是否正在下载 86 | if (DownloadImpl.getInstance().exist(url)) { 87 | Toast.makeText(Utils.getApp(), "该文件正在下载!", Toast.LENGTH_SHORT).show() 88 | return 89 | } 90 | mDownloadTasks[url]?.run { 91 | //添加当前url的Cookie 92 | addHeader("Cookie", WebUtils.getCookiesByUrl(url)) 93 | //推入队列 94 | enqueue(object : DownloadListenerAdapter() { 95 | override fun onResult( 96 | throwable: Throwable?, 97 | path: Uri?, 98 | url: String?, 99 | extra: Extra? 100 | ): Boolean { 101 | mDownloadTasks.remove(url) 102 | return super.onResult(throwable, path, url, extra) 103 | } 104 | }) 105 | } 106 | } catch (ignore: Throwable) { 107 | if (WebConfig.DEBUG) { 108 | ignore.printStackTrace() 109 | } 110 | } 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/extend/WebViewLongClickExtend.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web.extend 2 | 3 | import android.app.AlertDialog 4 | import android.webkit.WebView 5 | import cn.janking.webDroid.util.ActivityUtils 6 | import cn.janking.webDroid.util.LogUtils 7 | import cn.janking.webDroid.util.OpenUtils 8 | 9 | /** 10 | * @author Janking 11 | */ 12 | fun WebView.defaultOnLongClickListener(){ 13 | setOnLongClickListener { 14 | val result = 15 | (it as WebView).hitTestResult ?: return@setOnLongClickListener false 16 | val type = result.type 17 | if (type == WebView.HitTestResult.UNKNOWN_TYPE) return@setOnLongClickListener false 18 | 19 | // 这里可以拦截很多类型 20 | when (type) { 21 | WebView.HitTestResult.IMAGE_TYPE, 22 | WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE -> { 23 | // 获取图片的路径 24 | val imageUrl = result.extra 25 | // 使用Dialog弹出菜单 26 | AlertDialog.Builder(ActivityUtils.getTopActivity()) 27 | .setTitle("图片选项") 28 | .setItems(arrayOf("查看图片", "复制链接", "保存图片", "分享图片")) { _, which -> 29 | when (which) { 30 | 0 -> { 31 | OpenUtils.showFullImageDialogWithUrl(imageUrl) 32 | } 33 | 1 -> { 34 | OpenUtils.copyUrl(imageUrl) 35 | } 36 | 2 -> { 37 | OpenUtils.saveImage(imageUrl) 38 | } 39 | 3 -> { 40 | OpenUtils.shareImage(imageUrl) 41 | } 42 | } 43 | } 44 | .show() 45 | } 46 | else -> LogUtils.d("else") 47 | } 48 | true 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/extend/WebViewSettingExtend.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web.extend 2 | 3 | import android.os.Build 4 | import android.view.View 5 | import android.webkit.WebSettings 6 | import android.webkit.WebView 7 | import android.widget.Toast 8 | import cn.janking.webDroid.R 9 | import cn.janking.webDroid.constant.PathConstants 10 | import cn.janking.webDroid.constant.WebConstants 11 | import cn.janking.webDroid.util.LogUtils 12 | import cn.janking.webDroid.util.Utils 13 | import cn.janking.webDroid.util.WebUtils 14 | import cn.janking.webDroid.web.WebConfig 15 | 16 | /** 17 | * @author Janking 18 | */ 19 | fun WebView.defaultSetting() { 20 | settings.apply { 21 | //支持缩放,是其他设置缩放的前提 22 | setSupportZoom(true) 23 | //设置可以缩放,解决 sysu.edu.cn 不能缩放的问题 24 | builtInZoomControls = true 25 | //隐藏原生的缩放按钮 26 | displayZoomControls = false 27 | //设置文本缩放 28 | textZoom = 100 29 | //设置初始缩放比例 30 | //setInitialScale(100) 31 | //缩放至屏幕的大小 32 | loadWithOverviewMode = true 33 | //将图片调整到适合webview的大小, 解决 sysu.edu.cn 超出屏幕部分内容不加载,只有背景的问题 34 | useWideViewPort = true 35 | //根据cache-control获取数据。 36 | if (WebUtils.networkAvailable()) { 37 | //有网络时默认加载 38 | cacheMode = WebSettings.LOAD_DEFAULT 39 | } else { 40 | //无网络时从缓存加载 41 | cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK 42 | Toast.makeText( 43 | Utils.getApp(), 44 | Utils.getString(R.string.msg_load_cache_web_page), 45 | Toast.LENGTH_SHORT 46 | ).show() 47 | } 48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 49 | //适配5.0不允许http和https混合使用情况, 允许混合内容 50 | mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW 51 | setLayerType(View.LAYER_TYPE_HARDWARE, null) 52 | } 53 | //自动加载图片 54 | loadsImagesAutomatically = true 55 | //禁止多窗口 56 | setSupportMultipleWindows(false) 57 | //是否阻塞加载网络图片 协议http or https 58 | blockNetworkImage = false 59 | //设置支持javascript 60 | javaScriptEnabled = true 61 | //允许加载本地文件html file协议 62 | allowFileAccess = true 63 | //通过 file url 加载的 Javascript 读取其他的本地文件 .建议关闭 64 | allowFileAccessFromFileURLs = false 65 | //允许通过 file url 加载的 Javascript 可以访问其他的源,包括其他的文件和 http,https 等其他的源 66 | allowUniversalAccessFromFileURLs = false 67 | javaScriptCanOpenWindowsAutomatically = true 68 | //支持内容重新布局 69 | layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN 70 | domStorageEnabled = true 71 | //当webview调用requestFocus时为webview设置节点 72 | setNeedInitialFocus(true) 73 | //设置编码格式 74 | defaultTextEncodingName = "utf-8" 75 | //默认字体大小 76 | defaultFontSize = 16 77 | //设置 WebView 支持的最小字体大小,默认为 8 78 | minimumFontSize = 12 79 | //允许访问位置 80 | setGeolocationEnabled(true) 81 | val dir = PathConstants.dirWebCache 82 | if (WebConfig.DEBUG) { 83 | LogUtils.i( 84 | "WebView.defaultSetting()", 85 | "dir:" + dir + " appcache:" + PathConstants.dirWebCache 86 | ) 87 | } 88 | //允许使用数据库 89 | databaseEnabled = true 90 | //允许使用缓存 91 | setAppCacheEnabled(true) 92 | //设置缓存路径 93 | setAppCachePath(dir) 94 | //设置用户标识 95 | userAgentString += WebConstants.USERAGENT_UC 96 | if (WebConfig.DEBUG) { 97 | LogUtils.i( 98 | "WebView.defaultSetting()", 99 | "UserAgentString : $userAgentString" 100 | ) 101 | } 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/lifecycle/WebLifeCycle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cn.janking.webDroid.web.lifecycle; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | * @date 2017/5/30 22 | * @since 1.0.0 23 | */ 24 | public interface WebLifeCycle { 25 | void onResume(); 26 | void onPause(); 27 | void onDestroy(); 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/lifecycle/WebLifeCycleImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.janking.webDroid.web.lifecycle 17 | 18 | import android.os.Looper 19 | import android.view.ViewGroup 20 | import android.webkit.WebView 21 | 22 | /** 23 | * @author cenxiaozhong 24 | * @date 2017/6/3 25 | * @since 2.0.0 26 | */ 27 | class WebLifeCycleImpl internal constructor(private val mWebView: WebView?) : 28 | WebLifeCycle { 29 | override fun onResume() { 30 | mWebView?.run { 31 | onResume() 32 | resumeTimers() 33 | } 34 | } 35 | 36 | override fun onPause() { 37 | mWebView?.run { 38 | onPause() 39 | pauseTimers() 40 | } 41 | } 42 | 43 | override fun onDestroy() { 44 | mWebView?.resumeTimers() 45 | clearWebView( 46 | mWebView 47 | ) 48 | } 49 | 50 | companion object { 51 | fun clearWebView(w: WebView?) { 52 | val webView: WebView = w ?: return 53 | if (Looper.myLooper() != Looper.getMainLooper()) { 54 | return 55 | } 56 | webView.loadUrl("about:blank") 57 | webView.stopLoading() 58 | if (webView.handler != null) { 59 | webView.handler.removeCallbacksAndMessages(null) 60 | } 61 | webView.removeAllViews() 62 | val mViewGroup: ViewGroup = webView.parent as ViewGroup 63 | mViewGroup.removeView(webView) 64 | webView.webChromeClient = null 65 | webView.webViewClient = null 66 | webView.tag = null 67 | webView.clearHistory() 68 | webView.destroy() 69 | } 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/janking/webDroid/web/view/LollipopFixedWebView.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid.web.view 2 | 3 | import android.content.Context 4 | import android.content.res.Configuration 5 | import android.os.Build 6 | import android.util.AttributeSet 7 | import android.webkit.WebView 8 | 9 | /** 10 | * 修复 Android 5.0 & 5.1 打开 WebView 闪退问题: 11 | * 参阅 https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview 12 | */ 13 | open class LollipopFixedWebView : WebView { 14 | 15 | constructor( 16 | context: Context 17 | ):super(getFixedContext(context)) 18 | 19 | constructor( 20 | context: Context, 21 | attrs: AttributeSet? 22 | ) : super(getFixedContext(context), attrs) 23 | 24 | constructor( 25 | context: Context, 26 | attrs: AttributeSet?, 27 | defStyleAttr : Int 28 | ) : super(getFixedContext(context), attrs, defStyleAttr) 29 | 30 | 31 | companion object { 32 | fun getFixedContext(context: Context): Context { 33 | return if (Build.VERSION.SDK_INT in 21..22) { // Avoid crashing on Android 5 and 6 (API level 21 to 23) 34 | context.createConfigurationContext(Configuration()) 35 | } else context 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_recycler_item_show.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_primary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_outline_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_launcher_default.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tab_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_tab_0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tab_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_tab_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tab_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_tab_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tab_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_tab_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tab_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_tab_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tab_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/ic_tab_default.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_avatar_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/image_avatar_default.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/img_author_avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/app/src/main/res/drawable/img_author_avatar.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_webdroid.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 16 | 17 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_tab_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 19 | 20 | 30 | 31 | 46 | 47 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_edit_tab.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 18 | 22 | 23 | 28 | 29 | 35 | 36 | 37 | 40 | 41 | 47 | 48 | 55 | 56 | 57 | 58 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_image_dialog_fullscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_nav.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_nav_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 23 | 24 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_text_dialog_fullscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/menu/drawer_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_creator.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 16 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_webdroid.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 总是不允许 5 | 询问用户 6 | 总是允许 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 4dp 3 | 8dp 4 | 16dp 5 | 6 | 6dp 7 | 8dp 8 | 16dp 9 | 24dp 10 | 128dp 11 | 12 | 1dp 13 | 2dp 14 | 4dp 15 | 6dp 16 | 40dp 17 | 160dp 18 | 19 | 14sp 20 | 16sp 21 | 18sp 22 | 20sp 23 | 24sp 24 | 40sp 25 | 26 | 40dp 27 | 8dp 28 | 196dp 29 | 30 | 64dp 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Open navigation drawer 4 | Close navigation drawer 5 | 6 | 7 | hasInit 8 | lastConfig 9 | lastTab 10 | 11 | 12 | 13 | 14 | 15 | 我正在使用 %s(Created by https://github.com/JankingWon/WebDroid.) 16 | 分享到 17 | 提示 18 | 您需要离开%s前往%s吗? 19 | 您未安装此应用,是否安装? 20 | 是否允许使用流量下载? 21 | 页面出错了哦~\n双击TAB栏进行刷新~ 22 | 网络错误~\n请检查网络设置哦~\n双击TAB栏进行刷新~ 23 | %s正在请求访问您的位置,是否继续? 24 | 网络连接不可用,请稍后再试 25 | 网络不可用,已显示缓存页面 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 22 | 23 | 24 | 33 | 34 | 35 | 43 | 44 | 45 | 46 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/xml/util_code_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 14 | 15 | 18 | 19 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /app/src/test/java/com/janking/webDroid/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package cn.janking.webDroid 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.3.50' 5 | repositories { 6 | google() 7 | jcenter() 8 | maven { url 'https://jitpack.io' } 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.6.1' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /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 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Mar 01 16:09:45 CST 2020 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.6.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /janking.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/janking.jks -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name='WebDroid' 3 | include ':xmlparser' 4 | include ':jarsigner' 5 | -------------------------------------------------------------------------------- /xmlparser/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /xmlparser/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 19 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles 'consumer-rules.pro' 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | 29 | implementation 'androidx.appcompat:appcompat:1.1.0' 30 | testImplementation 'junit:junit:4.12' 31 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 32 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 33 | } 34 | -------------------------------------------------------------------------------- /xmlparser/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JankingWon/WebDroid/9728f371d4ed62d35bd4eed6e119e3ac958f6ec0/xmlparser/consumer-rules.pro -------------------------------------------------------------------------------- /xmlparser/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 | -------------------------------------------------------------------------------- /xmlparser/src/androidTest/java/luyao/parser/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package luyao.parser; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("luyao.parser.test", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /xmlparser/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/cn/janking/AXMLTool/XmlProcessor.java: -------------------------------------------------------------------------------- 1 | package cn.janking.AXMLTool; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | 8 | 9 | public class XmlProcessor { 10 | public byte[] source; 11 | 12 | public XmlProcessor(String srcFilePath) throws IOException { 13 | FileInputStream fileInputStream = new FileInputStream(new File(srcFilePath)); 14 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 15 | byte[] buffer = new byte[1024]; 16 | int len = 0; 17 | while ((len = fileInputStream.read(buffer)) != -1) { 18 | byteArrayOutputStream.write(buffer, 0, len); 19 | } 20 | //ParserChunkUtils.xmlStruct.byteSrc = byteArrayOutputStream.toByteArray(); 21 | fileInputStream.close(); 22 | byteArrayOutputStream.close(); 23 | } 24 | 25 | public void process(){ 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/utils/BytesReader.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.utils; 2 | 3 | import java.io.IOException; 4 | 5 | import static luyao.parser.parser.utils.TransformUtils.reverseBytes; 6 | 7 | /** 8 | * Created by luyao 9 | * on 2018/12/20 15:00 10 | */ 11 | public class BytesReader { 12 | 13 | public int position = 0; // 标记顺序读位置 14 | public byte[] data; 15 | private boolean isLittleEndian = true; 16 | 17 | public BytesReader(byte[] data) { 18 | this.data = data; 19 | } 20 | 21 | public BytesReader(byte[] data, boolean isLittleEndian) { 22 | this.data = data; 23 | this.isLittleEndian = isLittleEndian; 24 | } 25 | 26 | public static byte[] copy(byte[] stringContent, int start, int length) { 27 | byte[] b = new byte[length]; 28 | System.arraycopy(stringContent, start, b, 0, length); 29 | return b; 30 | } 31 | 32 | /** 33 | * @param count 字节数 34 | * @return 返回 little endian 字节数组 35 | */ 36 | public byte[] read(int count) { 37 | byte[] b = copy(data, position, count); 38 | position += count; 39 | if (isLittleEndian) return b; 40 | else { 41 | return reverseBytes(b); 42 | } 43 | } 44 | 45 | public byte[] readBig(int count) { 46 | byte[] b = copy(data, position, count); 47 | position += count; 48 | if (!isLittleEndian) return b; 49 | else { 50 | return reverseBytes(b); 51 | } 52 | } 53 | 54 | public byte[] read(byte[] buffer) throws IOException { 55 | buffer = copy(data, position, buffer.length); 56 | position += buffer.length; 57 | if (isLittleEndian) return buffer; 58 | else { 59 | return reverseBytes(buffer); 60 | } 61 | } 62 | 63 | public byte[] readOrigin(int count) throws IOException { 64 | byte[] b = copy(data, position, count); 65 | position += count; 66 | return b; 67 | } 68 | 69 | public byte readByte() throws IOException { 70 | byte b = copy(data, position, 1)[0]; 71 | position++; 72 | return b; 73 | } 74 | 75 | public int readUnsignedByte() throws IOException { 76 | byte b = copy(data, position, 1)[0]; 77 | position++; 78 | return b; 79 | } 80 | 81 | public short readShort() throws IOException { 82 | return TransformUtils.bytes2Short(read(2)); 83 | } 84 | 85 | public int readUnsignedShort() throws IOException { 86 | return TransformUtils.bytes2UnsignedShort(read(2)); 87 | } 88 | 89 | public int readInt() throws IOException { 90 | byte[] ints = read(4); 91 | return TransformUtils.bytes2Int(ints); 92 | } 93 | 94 | public long readUnsignedInt() throws IOException { 95 | byte[] ints = read(4); 96 | return TransformUtils.bytes2UnsignedInt(ints); 97 | } 98 | 99 | public long readLong() throws IOException { 100 | return TransformUtils.bytes2Long(read(8)); 101 | } 102 | 103 | public float readFloat() throws IOException { 104 | return Float.intBitsToFloat(readInt()); 105 | } 106 | 107 | public double readDouble() throws IOException { 108 | return Double.longBitsToDouble(readLong()); 109 | } 110 | 111 | public String readHexString(int count) throws IOException { 112 | return TransformUtils.byte2HexStr(readBig(count)); 113 | } 114 | 115 | public int avaliable() throws IOException { 116 | return data.length - position; 117 | } 118 | 119 | public void skip(long count) throws IOException { 120 | if (count > 0) 121 | position += count; 122 | } 123 | 124 | public void reset() throws IOException { 125 | position = 0; 126 | } 127 | 128 | 129 | public int getCurrentPosition() { 130 | return position; 131 | } 132 | 133 | public byte[] read(int start, int len) { 134 | position += len; 135 | return copy(data, start, len); 136 | } 137 | 138 | public void moveTo(int i) { 139 | if (i <= data.length) 140 | position = i; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.utils; 2 | 3 | 4 | import java.io.BufferedInputStream; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by luyao 15 | * on 2018/4/27 14:43 16 | */ 17 | public class Utils { 18 | 19 | private static final char[] hexCode = "0123456789ABCDEF".toCharArray(); 20 | 21 | public static String bytes2hex(byte[] bytes) { 22 | StringBuilder r = new StringBuilder(bytes.length * 2); 23 | for (byte b : bytes) { 24 | r.append(hexCode[(b >> 4) & 0xF]); 25 | r.append(hexCode[(b & 0xF)]); 26 | } 27 | return r.toString(); 28 | } 29 | 30 | public static int fromBytes(byte b1, byte b2, byte b3, byte b4) { 31 | return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF); 32 | } 33 | 34 | public static int fromBytes(byte b1, byte b2) { 35 | return b1 & 0xff | (b2 & 0xFF) << 8; 36 | } 37 | 38 | public static byte[] copy(byte[] stringContent, int start, int length) { 39 | byte[] b = new byte[length]; 40 | System.arraycopy(stringContent, start, b, 0, length); 41 | return b; 42 | } 43 | 44 | public static int byte2Short(byte[] bytes) { 45 | return fromBytes(bytes[0], bytes[1]); 46 | } 47 | 48 | public static int byte2Int(byte[] bytes) { 49 | return fromBytes(bytes[3], bytes[2], bytes[1], bytes[0]); 50 | } 51 | 52 | public static byte[] reverseByte(byte[] bytes) { 53 | int length = bytes.length; 54 | byte[] result = new byte[length]; 55 | for (int i = 0; i < length / 2; i++) { 56 | result[i] = bytes[length - i - 1]; 57 | result[length - i - 1] = bytes[i]; 58 | } 59 | return result; 60 | } 61 | 62 | public static byte[] moveBlank(byte[] data) { 63 | List byteList = new ArrayList<>(); 64 | for (Byte b : data) { 65 | if (b != 0) byteList.add(b); 66 | } 67 | byte[] result = new byte[byteList.size()]; 68 | for (int i = 0; i < result.length; i++) 69 | result[i] = byteList.get(i); 70 | return result; 71 | } 72 | 73 | public static byte[] readAll(File file) { 74 | try { 75 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 76 | InputStream in = new FileInputStream(file); 77 | BufferedInputStream bi = new BufferedInputStream(in); 78 | byte[] b = new byte[1024]; 79 | int len = 0; 80 | while ((len = bi.read(b)) != -1) { 81 | bos.write(b, 0, len); 82 | } 83 | return bos.toByteArray(); 84 | } catch (IOException e) { 85 | e.printStackTrace(); 86 | } 87 | return null; 88 | } 89 | 90 | public static byte[] readAll(InputStream in) { 91 | try { 92 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 93 | BufferedInputStream bi = new BufferedInputStream(in); 94 | byte[] b = new byte[1024]; 95 | int len = 0; 96 | while ((len = bi.read(b)) != -1) { 97 | bos.write(b, 0, len); 98 | } 99 | return bos.toByteArray(); 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | } 103 | return null; 104 | } 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/Attribute.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean; 2 | 3 | /** 4 | * Created by luyao 5 | * on 2018/12/14 14:00 6 | */ 7 | public class Attribute { 8 | 9 | private String namespaceUri; 10 | private String name; 11 | private int valueStr; 12 | private int type; 13 | private String data; 14 | 15 | 16 | public Attribute(String namespaceUri, String name, int valueStr, int type, String data) { 17 | this.namespaceUri = namespaceUri; 18 | this.name = name; 19 | this.valueStr = valueStr; 20 | this.type = type; 21 | this.data = data; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "Attribute{" + 27 | "namespaceUri='" + namespaceUri + '\'' + 28 | ", name='" + name + '\'' + 29 | ", valueStr='" + valueStr + '\'' + 30 | ", type='" + type + '\'' + 31 | ", data='" + data + '\'' + 32 | '}'; 33 | } 34 | 35 | public String getData(){ 36 | return data; 37 | } 38 | 39 | public String getNamespaceUri() { 40 | return namespaceUri; 41 | } 42 | 43 | public void setNamespaceUri(String namespaceUri) { 44 | this.namespaceUri = namespaceUri; 45 | } 46 | 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | public void setName(String name) { 52 | this.name = name; 53 | } 54 | 55 | public int getValueStr() { 56 | return valueStr; 57 | } 58 | 59 | public void setValueStr(int valueStr) { 60 | this.valueStr = valueStr; 61 | } 62 | 63 | public int getType() { 64 | return type; 65 | } 66 | 67 | public void setType(int type) { 68 | this.type = type; 69 | } 70 | 71 | public void setData(String data) { 72 | this.data = data; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/NameSpace.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by luyao 7 | * on 2018/12/14 16:09 8 | */ 9 | public class NameSpace { 10 | 11 | private List attributes; 12 | 13 | public List getAttributes() { 14 | return attributes; 15 | } 16 | 17 | public void setAttributes(List attributes) { 18 | this.attributes = attributes; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/Xml.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import luyao.parser.parser.xml.bean.chunk.Chunk; 8 | 9 | /** 10 | * Created by luyao 11 | * on 2018/5/2 13:48 12 | */ 13 | public class Xml { 14 | 15 | 16 | public static final int START_NAMESPACE_CHUNK_TYPE = 0x00100100; 17 | public static final int END_NAMESPACE_CHUNK_TYPE = 0x00100101; 18 | public static final int START_TAG_CHUNK_TYPE = 0x00100102; 19 | public static final int END_TAG_CHUNK_TYPE = 0x00100103; 20 | public static final int TEXT_CHUNK_TYPE = 0x00100104; 21 | 22 | public List stringChunkList; 23 | public List tagNameList; 24 | public List chunkList; 25 | public static Map nameSpaceMap = new HashMap<>(); 26 | public static StringBuilder BLANK = new StringBuilder(" "); 27 | public static String blank = " "; 28 | 29 | public Xml(List stringChunkList, List tagNameList, List chunkList) { 30 | this.stringChunkList = stringChunkList; 31 | this.tagNameList = tagNameList; 32 | this.chunkList = chunkList; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | StringBuilder builder = new StringBuilder(); 38 | builder.append("\n"); 39 | for (Chunk chunk : chunkList) { 40 | builder.append(chunk.toXmlString()); 41 | } 42 | return builder.toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/chunk/Chunk.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean.chunk; 2 | 3 | /** 4 | * Created by luyao 5 | * on 2018/12/14 16:17 6 | */ 7 | public abstract class Chunk { 8 | 9 | int chunkType; 10 | int chunkSize; 11 | int lineNumber; 12 | 13 | Chunk(int chunkType){ 14 | this.chunkType=chunkType; 15 | } 16 | 17 | public int getChunkSize() { 18 | return chunkSize; 19 | } 20 | 21 | public abstract String toXmlString(); 22 | } 23 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/chunk/EndNameSpaceChunk.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean.chunk; 2 | 3 | import luyao.parser.parser.xml.bean.Xml; 4 | 5 | /** 6 | * Created by luyao 7 | * on 2018/12/14 16:23 8 | */ 9 | public class EndNameSpaceChunk extends Chunk { 10 | 11 | private int prefix; 12 | private int uri; 13 | 14 | public EndNameSpaceChunk(int chunkSize, int lineNumber, int prefix, int uri) { 15 | super(Xml.END_NAMESPACE_CHUNK_TYPE); 16 | this.chunkSize = chunkSize; 17 | this.lineNumber = lineNumber; 18 | this.prefix = prefix; 19 | this.uri = uri; 20 | } 21 | 22 | public int getPrefix() { 23 | return prefix; 24 | } 25 | 26 | public void setPrefix(int prefix) { 27 | this.prefix = prefix; 28 | } 29 | 30 | public int getUri() { 31 | return uri; 32 | } 33 | 34 | public void setUri(int uri) { 35 | this.uri = uri; 36 | } 37 | 38 | @Override 39 | public String toXmlString() { 40 | return ""; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/chunk/EndTagChunk.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean.chunk; 2 | 3 | import luyao.parser.parser.xml.XmlParser; 4 | import luyao.parser.parser.xml.bean.Xml; 5 | 6 | import static luyao.parser.parser.xml.bean.Xml.BLANK; 7 | import static luyao.parser.parser.xml.bean.Xml.blank; 8 | 9 | /** 10 | * Created by luyao 11 | * on 2018/12/14 16:27 12 | */ 13 | public class EndTagChunk extends Chunk { 14 | private int nameSpaceUri; 15 | private String name; 16 | 17 | public EndTagChunk(int nameSpaceUri, String name) { 18 | super(Xml.END_TAG_CHUNK_TYPE); 19 | this.nameSpaceUri = nameSpaceUri; 20 | this.name = name; 21 | } 22 | 23 | 24 | public int getNameSpaceUri() { 25 | return nameSpaceUri; 26 | } 27 | 28 | public void setNameSpaceUri(int nameSpaceUri) { 29 | this.nameSpaceUri = nameSpaceUri; 30 | } 31 | 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | @Override 41 | public String toXmlString() { 42 | if (name.equals("manifest")) 43 | BLANK.setLength(0); 44 | else 45 | BLANK.setLength(BLANK.length() - blank.length()); 46 | 47 | return XmlParser.format("\n%s", BLANK, name); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/chunk/StartNameSpaceChunk.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean.chunk; 2 | 3 | import luyao.parser.parser.xml.bean.Xml; 4 | 5 | /** 6 | * Created by luyao 7 | * on 2018/12/14 16:19 8 | */ 9 | public class StartNameSpaceChunk extends Chunk { 10 | 11 | private int prefix; 12 | private int uri; 13 | 14 | public StartNameSpaceChunk(int chunkSize, int lineNumber, int prefix, int uri) { 15 | super(Xml.START_NAMESPACE_CHUNK_TYPE); 16 | this.chunkSize = chunkSize; 17 | this.lineNumber = lineNumber; 18 | this.prefix = prefix; 19 | this.uri = uri; 20 | } 21 | 22 | public int getPrefix() { 23 | return prefix; 24 | } 25 | 26 | public void setPrefix(int prefix) { 27 | this.prefix = prefix; 28 | } 29 | 30 | public int getUri() { 31 | return uri; 32 | } 33 | 34 | public void setUri(int uri) { 35 | this.uri = uri; 36 | } 37 | 38 | @Override 39 | public String toXmlString() { 40 | return ""; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /xmlparser/src/main/java/luyao/parser/parser/xml/bean/chunk/StartTagChunk.java: -------------------------------------------------------------------------------- 1 | package luyao.parser.parser.xml.bean.chunk; 2 | 3 | import java.util.List; 4 | 5 | import luyao.parser.parser.xml.XmlParser; 6 | import luyao.parser.parser.xml.bean.Attribute; 7 | import luyao.parser.parser.xml.bean.Xml; 8 | 9 | import static luyao.parser.parser.xml.bean.Xml.blank; 10 | 11 | /** 12 | * Created by luyao 13 | * on 2018/12/14 16:24 14 | */ 15 | public class StartTagChunk extends Chunk { 16 | 17 | private int nameSpaceUri; 18 | private String name; 19 | private List attributeList; 20 | 21 | 22 | public StartTagChunk(int nameSpaceUri, String name, List attributeList) { 23 | super(Xml.START_TAG_CHUNK_TYPE); 24 | this.nameSpaceUri = nameSpaceUri; 25 | this.name = name; 26 | this.attributeList = attributeList; 27 | } 28 | 29 | public int getNameSpaceUri() { 30 | return nameSpaceUri; 31 | } 32 | 33 | public void setNameSpaceUri(int nameSpaceUri) { 34 | this.nameSpaceUri = nameSpaceUri; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public List getAttributeList() { 46 | return attributeList; 47 | } 48 | 49 | public void setAttributeList(List attributeList) { 50 | this.attributeList = attributeList; 51 | } 52 | 53 | @Override 54 | public String toXmlString() { 55 | StringBuilder builder = new StringBuilder(); 56 | if (name.replace(" ", "").equals("manifest")) { 57 | builder.append("", Xml.BLANK, name)); 65 | else 66 | builder.append(XmlParser.format("\n%s<%s", Xml.BLANK, name)); 67 | } 68 | Xml.BLANK.append(blank); 69 | for (int i = 0; i < attributeList.size(); i++) { 70 | Attribute attribute = attributeList.get(i); 71 | 72 | String prefix = XmlParser.getNamespacePrefix(Xml.nameSpaceMap.get(attribute.getNamespaceUri())); 73 | builder.append(XmlParser.format("\n%s%s%s=\"%s\"", Xml.BLANK.toString(), prefix, attribute.getName(), attribute.getData())); 74 | 75 | if (i == attributeList.size() - 1) builder.append(">"); 76 | } 77 | return builder.toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /xmlparser/src/test/java/luyao/parser/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package luyao.parser; 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 | } --------------------------------------------------------------------------------