├── app ├── .gitignore ├── ci-unsecured.jks ├── src │ └── main │ │ ├── res │ │ ├── drawable │ │ │ └── logo.png │ │ ├── values │ │ │ ├── dimens.xml │ │ │ └── strings.xml │ │ ├── xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ │ └── layout │ │ │ ├── activity_main.xml │ │ │ └── activity_qing_long_login.xml │ │ ├── java │ │ └── cn │ │ │ └── moon │ │ │ └── ql │ │ │ ├── SiteType.java │ │ │ ├── data │ │ │ ├── model │ │ │ │ ├── QLLoginData.java │ │ │ │ ├── QLStoreData.java │ │ │ │ ├── QLSettingsData.java │ │ │ │ └── QLEnvData.java │ │ │ └── QLSdk.java │ │ │ ├── util │ │ │ └── CookieUtil.java │ │ │ ├── EnvUploader.java │ │ │ ├── App.java │ │ │ └── ui │ │ │ ├── ql │ │ │ └── QLLoginActivity.java │ │ │ └── app │ │ │ └── MainActivity.java │ │ └── AndroidManifest.xml ├── ci-keystore.properties ├── proguard-rules.pro └── build.gradle ├── docs ├── app.png ├── run.png ├── web.png ├── actions.png ├── ql-app.png └── release.png ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── .gitignore ├── README.md ├── .github └── workflows │ └── ci.yml ├── settings.gradle ├── gradle.properties ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /docs/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/docs/app.png -------------------------------------------------------------------------------- /docs/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/docs/run.png -------------------------------------------------------------------------------- /docs/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/docs/web.png -------------------------------------------------------------------------------- /docs/actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/docs/actions.png -------------------------------------------------------------------------------- /docs/ql-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/docs/ql-app.png -------------------------------------------------------------------------------- /docs/release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/docs/release.png -------------------------------------------------------------------------------- /app/ci-unsecured.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/app/ci-unsecured.jks -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangood/qinglong-jd-apk/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/ci-keystore.properties: -------------------------------------------------------------------------------- 1 | storeFile=./ci-unsecured.jks 2 | storePassword=phono-unsecured 3 | keyAlias=phono-unsecured 4 | keyPassword=phono-unsecured 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jun 08 07:46:30 CST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /.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 | local.properties 16 | /.idea/ 17 | -------------------------------------------------------------------------------- /app/src/main/java/cn/moon/ql/SiteType.java: -------------------------------------------------------------------------------- 1 | package cn.moon.ql; 2 | 3 | public enum SiteType { 4 | JD("https://m.jd.com","JD_COOKIE"); 5 | 6 | private String url; 7 | private String env; // 青龙环境变量 8 | 9 | 10 | SiteType(String url, String env){ 11 | this.url = url; 12 | this.env = env; 13 | } 14 | 15 | 16 | public String getUrl() { 17 | return url; 18 | } 19 | 20 | public String getEnv() { 21 | return env; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 青龙脚本,京东cookie获取上传APP 3 | - 手机使用app 4 | - 登录后,自动将cookie上传到青龙脚本服务器 5 | - 源码全部开放 6 | 7 | 8 | 9 | ## 界面 10 | ![docs/app.png](docs/app.png) 11 | 12 | ![docs/web.png](docs/web.png) 13 | 14 | # 使用方式:直接下载右侧apk 15 | 在青龙后台创建一个应用,赋予修改变量的权限。 依次点击【系统设置】【应用设置】【创建应用】 ,名称无所谓,权限选择 环境变量。 创建后得到Client ID,Client Secret 16 | ![img.png](docs/ql-app.png) 17 | 18 | 19 | 20 | 21 | # 开发自行编译 22 | IDE 用的2021版 23 | 1. 克隆 本项目 24 | 2. 直接打包即可 25 | 26 | 27 | # 开发笔记, 记录开发过程中遇到的问题 28 | 接口参考文档:https://qinglong.ukenn.top 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/java/cn/moon/ql/data/model/QLLoginData.java: -------------------------------------------------------------------------------- 1 | package cn.moon.ql.data.model; 2 | 3 | 4 | public class QLLoginData { 5 | 6 | private String tokenType; 7 | private String token; 8 | 9 | public QLLoginData(String userId, String token) { 10 | this.tokenType = userId; 11 | this.token = token; 12 | } 13 | 14 | public String getTokenType() { 15 | return tokenType; 16 | } 17 | 18 | public String getToken() { 19 | return token; 20 | } 21 | 22 | public String toAuthValue(){ 23 | return this.tokenType + " " + token; 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/cn/moon/ql/data/model/QLStoreData.java: -------------------------------------------------------------------------------- 1 | package cn.moon.ql.data.model; 2 | 3 | public class QLStoreData { 4 | private QLLoginData loginData; 5 | private QLSettingsData settingsData; 6 | 7 | public QLStoreData(QLLoginData loginData, QLSettingsData settingsData) { 8 | this.loginData = loginData; 9 | this.settingsData = settingsData; 10 | } 11 | 12 | public QLLoginData getLoginData() { 13 | return loginData; 14 | } 15 | 16 | public QLSettingsData getSettingsData() { 17 | return settingsData; 18 | } 19 | 20 | public boolean isLoggedQL() { 21 | return this.loginData != null && loginData.getToken() != null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: APK 打包 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "v*.*.*" 8 | 9 | 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: write 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: 设置Java环境 21 | uses: actions/setup-java@v3 22 | with: 23 | java-version: '17' 24 | distribution: 'temurin' 25 | 26 | - name: 打包 27 | run: | 28 | chmod +x gradlew 29 | ./gradlew assembleCiRelease 30 | 31 | - name: 发布 32 | uses: softprops/action-gh-release@v2 33 | with: 34 | files: | 35 | app/build/outputs/apk/ci/**/*.* 36 | -------------------------------------------------------------------------------- /app/src/main/java/cn/moon/ql/data/model/QLSettingsData.java: -------------------------------------------------------------------------------- 1 | package cn.moon.ql.data.model; 2 | 3 | /** 4 | * Data class that captures user information for logged in users retrieved from LoginRepository 5 | */ 6 | public class QLSettingsData { 7 | 8 | private String url; 9 | private String cid; 10 | private String csk; 11 | 12 | public QLSettingsData(String url, String cid,String csk) { 13 | this.url = url; 14 | this.cid = cid; 15 | this.csk = csk; 16 | } 17 | 18 | public String getUrl() { 19 | return url; 20 | } 21 | 22 | public String getCid() { 23 | return cid; 24 | } 25 | 26 | public String getCsk() { 27 | return csk; 28 | } 29 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { url "https://jitpack.io" } 4 | maven { url 'https://maven.aliyun.com/repository/releases' } 5 | maven { url 'https://maven.aliyun.com/repository/jcenter' } 6 | maven { url 'https://maven.aliyun.com/repository/google' } 7 | maven { url 'https://maven.aliyun.com/repository/central' } 8 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } 9 | maven { url 'https://maven.aliyun.com/repository/public' } 10 | google() 11 | mavenCentral() 12 | gradlePluginPortal() 13 | } 14 | } 15 | dependencyResolutionManagement { 16 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 17 | repositories { 18 | google() 19 | mavenCentral() 20 | } 21 | } 22 | rootProject.name = "QinglongClient" 23 | include ':app' 24 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 青龙京东 3 | 上传 4 | 登录青龙 5 | 青龙ClientID 6 | 青龙ClientSecret 7 | 地址,如 http://127.0.0.1:5700 8 | ClientID 9 | ClientSecret 10 | 登录 11 | 无效的URL 12 | 无效的ClientID 13 | 无效的ClientSecret 14 | "登录失败" 15 | 登录青龙 16 | 17 | 18 | 刷新 19 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 15 | 16 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /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=-Xmx2048m -Dfile.encoding=UTF-8 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 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true 22 | android.defaults.buildfeatures.buildconfig=true 23 | android.nonFinalResIds=false -------------------------------------------------------------------------------- /app/src/main/java/cn/moon/ql/util/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package cn.moon.ql.util; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.ArrayList; 6 | import java.util.LinkedHashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class CookieUtil { 11 | 12 | public static Map parse(String cookies) { 13 | String[] cookiesArr = cookies.split(";"); 14 | 15 | Map map = new LinkedHashMap<>(); 16 | for (String ck : cookiesArr) { 17 | String[] arr = ck.split("="); 18 | if (arr.length == 2) { 19 | String k = arr[0]; 20 | String v = arr[1]; 21 | 22 | if(!TextUtils.isEmpty(v)){ 23 | map.put(k.trim(), v.trim()); 24 | } 25 | 26 | 27 | } 28 | } 29 | 30 | return map; 31 | } 32 | 33 | public static Map parse(String cookies,String... keys) { 34 | Map map = parse(cookies); 35 | 36 | Map newMap = new LinkedHashMap<>(); 37 | for (String key : keys) { 38 | String value = map.get(key); 39 | if(!TextUtils.isEmpty(value)){ 40 | newMap.put(key, value); 41 | } 42 | } 43 | return newMap; 44 | } 45 | 46 | public static String join(Map cookieMap) { 47 | List list = new ArrayList<>(); 48 | for (Map.Entry e : cookieMap.entrySet()) { 49 | String key = e.getKey(); 50 | String value = e.getValue(); 51 | 52 | list.add(key+"="+value); 53 | } 54 | return TextUtils.join("; ", list) + ";"; 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | agp = "8.4.0" 3 | kotlin = "1.9.0" 4 | coreKtx = "1.10.1" 5 | junit = "4.13.2" 6 | junitVersion = "1.1.5" 7 | espressoCore = "3.5.1" 8 | appcompat = "1.6.1" 9 | material = "1.10.0" 10 | activity = "1.8.0" 11 | constraintlayout = "2.1.4" 12 | annotation = "1.7.0" 13 | lifecycle-livedata-ktx = "2.6.2" 14 | lifecycle-viewmodel-ktx = "2.6.2" 15 | 16 | [libraries] 17 | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } 18 | junit = { group = "junit", name = "junit", version.ref = "junit" } 19 | androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } 20 | androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } 21 | androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } 22 | material = { group = "com.google.android.material", name = "material", version.ref = "material" } 23 | androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } 24 | androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } 25 | annotation = { group = "androidx.annotation", name = "annotation", version.ref = "annotation" } 26 | lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle-livedata-ktx" } 27 | lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle-viewmodel-ktx" } 28 | 29 | [plugins] 30 | android-application = { id = "com.android.application", version.ref = "agp" } 31 | jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 |