├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── themes.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── lancewu
│ │ │ │ └── taskscheduler
│ │ │ │ └── MainActivity.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── lancewu
│ │ │ └── taskscheduler
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── lancewu
│ │ └── taskscheduler
│ │ └── ExampleInstrumentedTest.kt
├── proguard-rules.pro
└── build.gradle
├── taskscheduler
├── .gitignore
├── consumer-rules.pro
├── src
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── lancewu
│ │ │ └── taskscheduler
│ │ │ ├── graph
│ │ │ └── DirectedAcyclicGraph.kt
│ │ │ └── TaskScheduler.kt
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── lancewu
│ │ │ └── taskscheduler
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── lancewu
│ │ └── taskscheduler
│ │ ├── ExampleInstrumentedTest.kt
│ │ └── TaskSchedulerTest.kt
├── proguard-rules.pro
├── build.gradle
└── plugin_maven_publish.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── CHANGELOG.md
├── settings.gradle
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/taskscheduler/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/taskscheduler/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TaskScheduler
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wurensen/TaskScheduler/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 | local.properties
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | > 版本号定义遵循:[语义化版本 2.0.0](https://semver.org/lang/zh-CN/)
4 |
5 | ## 0.1.0 (2022-08-22)
6 |
7 | **Feature**
8 |
9 | 1. 发布首个版本
10 |
--------------------------------------------------------------------------------
/taskscheduler/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Aug 19 15:58:41 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lancewu/taskscheduler/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
2 |
3 | import androidx.appcompat.app.AppCompatActivity
4 | import android.os.Bundle
5 |
6 | class MainActivity : AppCompatActivity() {
7 | override fun onCreate(savedInstanceState: Bundle?) {
8 | super.onCreate(savedInstanceState)
9 | setContentView(R.layout.activity_main)
10 | }
11 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "TaskScheduler"
16 | include ':app'
17 | include ':taskscheduler'
18 |
--------------------------------------------------------------------------------
/app/src/test/java/com/lancewu/taskscheduler/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
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 | }
--------------------------------------------------------------------------------
/taskscheduler/src/test/java/com/lancewu/taskscheduler/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
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 | }
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/lancewu/taskscheduler/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
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("com.lancewu.taskscheduler", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/taskscheduler/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
--------------------------------------------------------------------------------
/taskscheduler/src/androidTest/java/com/lancewu/taskscheduler/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
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("com.lancewu.taskscheduler.test", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/taskscheduler/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 |
6 | android {
7 | compileSdk 31
8 |
9 | defaultConfig {
10 | minSdk 19
11 | targetSdk 31
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 | compileOptions {
24 | sourceCompatibility JavaVersion.VERSION_1_8
25 | targetCompatibility JavaVersion.VERSION_1_8
26 | }
27 | kotlinOptions {
28 | jvmTarget = '1.8'
29 | }
30 | }
31 |
32 | dependencies {
33 | api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
34 | testImplementation 'junit:junit:4.13.2'
35 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
37 | }
38 |
39 | // 发布maven插件
40 | apply from: project.file("plugin_maven_publish.gradle")
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 |
6 | android {
7 | compileSdk 31
8 |
9 | defaultConfig {
10 | applicationId "com.lancewu.taskscheduler"
11 | minSdk 21
12 | targetSdk 31
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | kotlinOptions {
30 | jvmTarget = '1.8'
31 | }
32 | }
33 |
34 | dependencies {
35 |
36 | implementation 'androidx.core:core-ktx:1.7.0'
37 | implementation 'androidx.appcompat:appcompat:1.4.2'
38 | implementation 'com.google.android.material:material:1.4.0'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
40 | testImplementation 'junit:junit:4.13.2'
41 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
43 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/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 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
24 |
25 | #项目属性配置
26 | LIB_GROUP=io.github.wurensen
27 | LIB_ARTIFACT = taskscheduler
28 | #版本号,快照版本号加'-SNAPSHOT'
29 | LIB_VERSION=0.1.0
30 | #基于Kotlin协程以及DAG(有向无环图)实现的Android任务调度框架,可以根据任务间的依赖关系进行调度。
31 | LIB_DES=An Android library based on Kotlin Coroutines and DAG(Directd Acyclic Graph), which schdules dependent tasks.
32 | LIB_URL=https://github.com/wurensen/TaskScheduler
33 |
34 | SCM_URL=https://github.com/wurensen/TaskScheduler
35 |
36 | DEVELOPER_NAME=LanceWu
37 | DEVELOPER_EMAIL=wurensen@gmail.com
38 |
39 | LICENSE_NAME=The Apache Software License, Version 2.0
40 | LICENSE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
41 | LICENSE_DIST=repo
--------------------------------------------------------------------------------
/taskscheduler/plugin_maven_publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'signing'
3 |
4 | // 设置group和版本名称
5 | group = LIB_GROUP
6 | version = LIB_VERSION
7 |
8 | // 如何配置,参考文档:https://developer.android.com/studio/publish-library
9 | android {
10 | publishing {
11 | singleVariant('release') {
12 | withSourcesJar()
13 | withJavadocJar()
14 | }
15 | }
16 | }
17 |
18 | publishing {
19 | publications {
20 | // release:自定义发布产物名称
21 | release(MavenPublication) {
22 | afterEvaluate {
23 | from components.release
24 | }
25 |
26 | artifactId = LIB_ARTIFACT
27 |
28 | pom {
29 | name = LIB_ARTIFACT
30 | description = LIB_DES
31 | url = LIB_URL
32 | licenses {
33 | license {
34 | name = LICENSE_NAME
35 | url = LICENSE_URL
36 | distribution = LICENSE_DIST
37 | }
38 | }
39 | developers {
40 | developer {
41 | name = DEVELOPER_NAME
42 | email = DEVELOPER_EMAIL
43 | }
44 | }
45 | scm {
46 | url = SCM_URL
47 | }
48 | }
49 | }
50 | }
51 | repositories {
52 | maven {
53 | // change URLs to point to your repos, e.g. http://my.org/repo
54 | def releasesRepoUrl = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
55 | def snapshotsRepoUrl = 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
56 | def mavenUrl = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
57 | url = mavenUrl
58 |
59 | println("publish to mavenUrl=$mavenUrl")
60 | // 校验不支持本地文件目录
61 | if (mavenUrl.startsWith("https")) {
62 | credentials {
63 | username = ossrhUsername
64 | password = ossrhPassword
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
71 | signing {
72 | // 指定要签名的产物
73 | sign publishing.publications.release
74 | }
75 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/taskscheduler/src/androidTest/java/com/lancewu/taskscheduler/TaskSchedulerTest.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
2 |
3 | import android.util.Log
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 | import com.lancewu.taskscheduler.graph.DirectedAcyclicGraph
6 | import kotlinx.coroutines.MainScope
7 | import kotlinx.coroutines.delay
8 | import kotlinx.coroutines.runBlocking
9 | import org.junit.Test
10 | import org.junit.runner.RunWith
11 | import java.lang.RuntimeException
12 |
13 | /**
14 | * Created by LanceWu on 2022/8/10.
15 | * 测试
16 | */
17 | @RunWith(AndroidJUnit4::class)
18 | class TaskSchedulerTest {
19 |
20 | companion object {
21 | const val TAG = "TaskSchedulerTest"
22 | }
23 |
24 | @Test
25 | fun test_TaskScheduler() {
26 | runBlocking {
27 | val task1 = TaskScheduler.Task("1").apply {
28 | doOnScheduled = {
29 | delay(1000)
30 | log("任务执行完成:$this")
31 | }
32 | }
33 | val task2 = TaskScheduler.Task("2").apply {
34 | doOnScheduled = {
35 | delay(1000)
36 | log("任务执行完成:$this")
37 | }
38 | }
39 | val task3 = TaskScheduler.Task("3").apply {
40 | doOnScheduled = {
41 | delay(2000)
42 | log("任务执行完成:$this")
43 | }
44 | }
45 | val task4 = TaskScheduler.Task("4").apply {
46 | doOnScheduled = {
47 | delay(1000)
48 | log("任务执行完成:$this")
49 | }
50 | }
51 | val task5 = TaskScheduler.Task("5").apply {
52 | doOnScheduled = {
53 | delay(1000)
54 | log("任务执行完成:$this")
55 | }
56 | }
57 | val graph = DirectedAcyclicGraph.Builder()
58 | .addEdge(task1, task2)
59 | .addEdge(task1, task3)
60 | .addEdge(task2, task4)
61 | .addEdge(task3, task4)
62 | .addNode(task5)
63 | .build()
64 | val taskScheduler = TaskScheduler(MainScope(), graph)
65 | taskScheduler.schedule(task1)
66 | .schedule(task2)
67 | .schedule(task3)
68 | .schedule(task4)
69 | .schedule(task5)
70 | delay(5000)
71 | }
72 |
73 | }
74 |
75 | @Test
76 | fun test_CyclicDependencies() {
77 | // 有环,抛出异常
78 | var exception: Exception? = null
79 | try {
80 | DirectedAcyclicGraph.Builder()
81 | .addEdge("1", "2")
82 | .addEdge("1", "3")
83 | .addEdge("2", "4")
84 | .addEdge("3", "4")
85 | .addEdge("4", "1")
86 | .build()
87 | } catch (e: Exception) {
88 | e.printStackTrace()
89 | exception = e
90 | }
91 | assert(exception is RuntimeException)
92 | }
93 |
94 | private fun log(message: String) {
95 | Log.e(TAG, message)
96 | }
97 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TaskScheduler
2 |
3 | ## 简介
4 |
5 | 在Android开发场景中,经常会碰到多个耗时任务之间有依赖关系。
6 |
7 | 为了快速实现任务可以按照依赖关系调度执行,本库基于Kotlin的协程来实现线程的切换,以及基于图论的DAG(DirectedAcyclicGraph:有向无环图)来实现任务的依赖调度。
8 |
9 | ## 主要功能
10 |
11 | ### 依赖任务调度
12 |
13 | 可以实现异步任务按照依赖关系进行调度执行,常见使用场景:
14 |
15 | - 执行任务一开始就已经准备就绪,依赖关系构造后可以直接调度执行,如启动任务依赖执行
16 |
17 | - 执行任务一开始未准备就绪,只能先构造依赖关系,执行任务准备完毕后根据依赖关系来决定是否调度还是继续等待
18 |
19 | 任务调度`doOnScheduled`为`suspend`函数对象,执行在主线程,具体任务执行由开发者自行决定执行在什么线程,`doOnScheduled`调度执行结束表示任务结束,将进行后续的调度。
20 |
21 | ### 循环任务检查
22 |
23 | 当依赖任务之间出现循环依赖时,在构造任务图的时候将抛出异常。
24 |
25 | ## 使用方式
26 |
27 | `build.gradle`添加依赖:
28 |
29 | ```groovy
30 | // 确保仓库已添加:mavenCentral()
31 | allprojects {
32 | repositories {
33 | ...
34 | mavenCentral()
35 | }
36 | }
37 |
38 | // 添加依赖
39 | dependencies {
40 | compile 'io.github.wurensen:taskscheduler:'
41 | }
42 | ```
43 |
44 | > ``请替换为对应的版本号。
45 |
46 | 构造依赖图并执行调度:
47 |
48 | ```kotlin
49 | fun test_TaskScheduler() {
50 | runBlocking {
51 | val task1 = TaskScheduler.Task("1").apply {
52 | doOnScheduled = {
53 | delay(1000)
54 | log("任务执行完成:$this")
55 | }
56 | }
57 | val task2 = TaskScheduler.Task("2").apply {
58 | doOnScheduled = {
59 | delay(1000)
60 | log("任务执行完成:$this")
61 | }
62 | }
63 | val task3 = TaskScheduler.Task("3").apply {
64 | doOnScheduled = {
65 | delay(2000)
66 | log("任务执行完成:$this")
67 | }
68 | }
69 | val task4 = TaskScheduler.Task("4").apply {
70 | doOnScheduled = {
71 | delay(1000)
72 | log("任务执行完成:$this")
73 | }
74 | }
75 | val task5 = TaskScheduler.Task("5").apply {
76 | doOnScheduled = {
77 | delay(1000)
78 | log("任务执行完成:$this")
79 | }
80 | }
81 | val graph = DirectedAcyclicGraph.Builder()
82 | .addEdge(task1, task2)
83 | .addEdge(task1, task3)
84 | .addEdge(task2, task4)
85 | .addEdge(task3, task4)
86 | .addNode(task5)
87 | .build()
88 | val taskScheduler = TaskScheduler(MainScope(), graph)
89 | taskScheduler.schedule(task1)
90 | .schedule(task2)
91 | .schedule(task3)
92 | .schedule(task4)
93 | .schedule(task5)
94 | delay(5000)
95 | }
96 |
97 | }
98 | ```
99 |
100 | 更多使用例子,请参考:[测试用例](taskscheduler/src/androidTest/java/com/lancewu/taskscheduler/TaskSchedulerTest.kt)
101 |
102 | ## Change Log
103 |
104 | [Change Log](CHANGELOG.md)
105 |
106 | ## License
107 |
108 | ```txt
109 | Copyright 2022 LanceWu
110 |
111 | Licensed under the Apache License, Version 2.0 (the "License");
112 | you may not use this file except in compliance with the License.
113 | You may obtain a copy of the License at
114 |
115 | http://www.apache.org/licenses/LICENSE-2.0
116 |
117 | Unless required by applicable law or agreed to in writing, software
118 | distributed under the License is distributed on an "AS IS" BASIS,
119 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120 | See the License for the specific language governing permissions and
121 | limitations under the License.
122 | ```
123 |
--------------------------------------------------------------------------------
/taskscheduler/src/main/java/com/lancewu/taskscheduler/graph/DirectedAcyclicGraph.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler.graph
2 |
3 | import com.lancewu.taskscheduler.graph.DirectedAcyclicGraph.Builder
4 | import java.util.*
5 |
6 | /**
7 | * DAG图(有向无环图)
8 | * @param Node 节点类型
9 | * @property graph Map?> 图,value表示入度节点
10 | * @constructor 通过[Builder.build]创建实例
11 | */
12 | class DirectedAcyclicGraph private constructor(val graph: Map?>) {
13 |
14 | init {
15 | checkCyclicDependencies()
16 | }
17 |
18 | private fun checkCyclicDependencies() {
19 | // 已经访问过的节点
20 | val visited = mutableListOf()
21 | val stack = Stack()
22 | // 先找到入度为0的节点,添加到栈中
23 | for (key in graph.keys) {
24 | if (getIncomingNodes(key).isNullOrEmpty()) {
25 | stack.push(key)
26 | }
27 | }
28 | var count = 0
29 | while (stack.isNotEmpty()) {
30 | val node = stack.pop()
31 | visited.add(node)
32 | count++
33 | // 当前顶点所有指向顶点入度-1,如果计算后为0,则加入栈中
34 | getOutgoingNodes(node)?.forEach { outgoing ->
35 | // outgoing的已经无入度节点,入栈
36 | val incomingVisited = getIncomingNodes(outgoing)?.let {
37 | visited.containsAll(it)
38 | } ?: true
39 | if (incomingVisited) {
40 | stack.push(outgoing)
41 | }
42 | }
43 | }
44 | if (count < graph.size) {
45 | throw RuntimeException("This graph contains cyclic dependencies")
46 | }
47 | }
48 |
49 | /**
50 | * 获取[node]的所有入度节点
51 | * @param node Node
52 | * @return List?
53 | */
54 | fun getIncomingNodes(node: Node): List? {
55 | return graph[node]
56 | }
57 |
58 | /**
59 | * 获取[node]的所有出度节点
60 | * @param node Node
61 | * @return List?
62 | */
63 | fun getOutgoingNodes(node: Node): List? {
64 | var outgoing: MutableList? = null
65 | for ((item, incomingEdges) in graph) {
66 | if (incomingEdges?.contains(node) == true) {
67 | if (outgoing == null) {
68 | outgoing = mutableListOf()
69 | }
70 | outgoing.add(item)
71 | }
72 | }
73 | return outgoing
74 | }
75 |
76 | /**
77 | * 构造器
78 | * @param Node 节点
79 | * @property graph MutableMap?>
80 | */
81 | class Builder {
82 |
83 | // DAG图(key-节点,value-入度节点)
84 | private val graph = mutableMapOf?>()
85 |
86 | /***
87 | * 添加节点
88 | * @param node Node
89 | */
90 | fun addNode(node: Node): Builder {
91 | if (!graph.containsKey(node)) {
92 | graph[node] = null
93 | }
94 | return this
95 | }
96 |
97 | /**
98 | * 添加边:[nodeU]->[nodeV]
99 | * @param nodeU Node
100 | * @param nodeV Node
101 | */
102 | fun addEdge(nodeU: Node, nodeV: Node): Builder {
103 | addNode(nodeU)
104 | addNode(nodeV)
105 | val incoming = graph[nodeV] ?: mutableListOf()
106 | if (!incoming.contains(nodeU)) {
107 | incoming.add(nodeU)
108 | }
109 | graph[nodeV] = incoming
110 | return this
111 | }
112 |
113 | /**
114 | * 创建DAG图,如果有环将抛出异常
115 | * @return DirectedAcyclicGraph
116 | */
117 | fun build(): DirectedAcyclicGraph {
118 | return DirectedAcyclicGraph(graph)
119 | }
120 | }
121 |
122 | }
--------------------------------------------------------------------------------
/taskscheduler/src/main/java/com/lancewu/taskscheduler/TaskScheduler.kt:
--------------------------------------------------------------------------------
1 | package com.lancewu.taskscheduler
2 |
3 | import com.lancewu.taskscheduler.graph.DirectedAcyclicGraph
4 | import kotlinx.coroutines.CoroutineScope
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.launch
7 |
8 | /**
9 | * Created by LanceWu on 2022/8/5
10 | *
11 | * 依赖任务调度器
12 | *
13 | * 可以实现异步任务按照依赖关系进行调度执行,常见使用场景:
14 | * - 执行任务一开始就已经准备就绪,依赖关系构造后可以直接调度执行,如启动任务依赖执行
15 | * - 执行任务一开始未准备就绪,只能先构造依赖关系,执行任务准备完毕后根据依赖关系来决定是否调度还是继续等待
16 | */
17 | class TaskScheduler(
18 | val scope: CoroutineScope,
19 | val taskGraph: DirectedAcyclicGraph
20 | ) {
21 |
22 | /**
23 | * 任务状态
24 | */
25 | private val taskStates: MutableMap
26 |
27 | /**
28 | * 调度线程
29 | */
30 | private val scheduleDispatcher = Dispatchers.Main
31 |
32 | init {
33 | taskStates = taskGraph.graph.mapValuesTo(mutableMapOf()) {
34 | State.INIT
35 | }
36 | }
37 |
38 | /**
39 | * 根据任务标签获取任务(如果多个任务标签一致,只获取检索到的第一个)
40 | * @param taskTag Any
41 | * @return Task?
42 | */
43 | fun getTaskByTag(taskTag: Any): Task? {
44 | return taskGraph.graph.keys.firstOrNull { it.tag == taskTag }
45 | }
46 |
47 | /**
48 | * 获取当前任务状态
49 | * @param task Task
50 | * @return State
51 | */
52 | fun getTaskState(task: Task): State {
53 | return taskStates[task]!!
54 | }
55 |
56 | /**
57 | * 调度任务
58 | * @param task Task
59 | */
60 | fun schedule(task: Task): TaskScheduler {
61 | // 统一在主线程调度,防止多线程问题
62 | scope.launch(scheduleDispatcher) {
63 | val state = taskStates[task]
64 | if (state == State.INIT) {
65 | nextState(task)
66 | scheduleCurrent(task)
67 | }
68 | }
69 | return this
70 | }
71 |
72 | private fun scheduleCurrent(task: Task) {
73 | scope.launch(scheduleDispatcher) {
74 | val state = taskStates[task]
75 | // 准备就绪的任务才参与调度
76 | if (state == State.PREPARED && isIncomingFinished(task)) {
77 | nextState(task)
78 | task.doOnScheduled?.invoke(scope)
79 | nextState(task)
80 | scheduleNext(task)
81 | }
82 | }
83 | }
84 |
85 | private fun scheduleNext(task: Task) {
86 | taskGraph.getOutgoingNodes(task)?.forEach {
87 | scheduleCurrent(it)
88 | }
89 | }
90 |
91 | private fun nextState(task: Task) {
92 | taskStates[task] = getTaskState(task).next()
93 | }
94 |
95 | private fun isIncomingFinished(task: Task): Boolean {
96 | return taskGraph.getIncomingNodes(task)?.all { taskStates[it] == State.FINISHED } ?: true
97 | }
98 |
99 | /**
100 | * 任务状态,枚举顺序为状态顺序
101 | */
102 | enum class State {
103 | /**
104 | * 初始状态
105 | */
106 | INIT,
107 |
108 | /**
109 | * 准备就绪
110 | */
111 | PREPARED,
112 |
113 | /**
114 | * 已被调度
115 | */
116 | SCHEDULED,
117 |
118 | /**
119 | * 完成
120 | */
121 | FINISHED;
122 |
123 | /**
124 | * 进入下一个状态
125 | * @return State
126 | */
127 | fun next(): State {
128 | val values = values()
129 | val nextOrdinal = (this.ordinal + 1) % values.size
130 | return values[nextOrdinal]
131 | }
132 | }
133 |
134 | /**
135 | * 任务
136 | * @param tag 任务标签
137 | */
138 | class Task(val tag: Any) {
139 |
140 | /**
141 | * 调度执行行为,执行结束后会被标记为任务结束,任务在主线程被调度,如果需要执行在异步需要自行切到其它线程
142 | */
143 | var doOnScheduled: (suspend (scope: CoroutineScope) -> Unit)? = null
144 |
145 | override fun toString(): String {
146 | return "Task(tag='$tag')"
147 | }
148 |
149 | }
150 |
151 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------