├── .github └── issue_template.md ├── .gitignore ├── .idea ├── codeStyleSettings.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── copyright │ ├── apache2.xml │ └── profiles_settings.xml ├── dictionaries │ └── Jacksgong.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── .travis.yml ├── CHANGELOG-ZH.md ├── CHANGELOG.md ├── LICENSE.txt ├── README-zh.md ├── README.md ├── art ├── Cause_of_Attached.png ├── avoid_drop_frames1.gif ├── avoid_drop_frames2.gif ├── chunked_demo.gif ├── filedownload_sample_description.png ├── filedownloader-eclipse.jpg ├── filedownloadlistener_callback_flow.png ├── hybrid_test_demo.gif ├── message-system.png ├── mix.gif ├── mix_tasks_demo.gif ├── parallel.gif ├── parallel_tasks_demo.gif ├── remit-database.png ├── serial.gif ├── serial_tasks_demo.gif ├── single.gif ├── single_demo.gif ├── single_progress.gif ├── single_task_demo.gif ├── single_task_demo_en.gif ├── structure.png └── tasks_manager_demo.gif ├── build.gradle ├── checkstyle.xml ├── demo ├── .gitignore ├── build.gradle ├── filedownloaderdemo.jks ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── filedownloader.properties │ └── performance_test_data │ ├── java │ └── com │ │ └── liulishuo │ │ └── filedownloader │ │ └── demo │ │ ├── Constant.java │ │ ├── DemoApplication.java │ │ ├── GlobalMonitor.java │ │ ├── HybridTestActivity.java │ │ ├── MainActivity.java │ │ ├── MultitaskTestActivity.java │ │ ├── NotificationSampleActivity.java │ │ ├── SingleTaskTestActivity.java │ │ ├── TasksManagerDemoActivity.java │ │ ├── Utils.java │ │ └── performance │ │ ├── IntParcel.java │ │ ├── LongParcel.java │ │ └── PerformanceTestActivity.java │ └── res │ ├── drawable │ └── bg_item_task_manager.xml │ ├── layout │ ├── activity_hybrid_test.xml │ ├── activity_main.xml │ ├── activity_mutitask_test.xml │ ├── activity_notification_minset.xml │ ├── activity_notification_sample.xml │ ├── activity_performance.xml │ ├── activity_single.xml │ ├── activity_tasks_manager_demo.xml │ └── item_tasks_manager.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-zh │ └── strings.xml │ ├── values │ ├── colors.xml │ ├── donottranslate.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── network_security_config.xml ├── gradle.properties ├── gradle ├── bintray.gradle ├── mvn-local.gradle ├── mvn-push.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── install.sh ├── library ├── .gitignore ├── LICENSE ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── aidl │ │ └── com │ │ │ └── liulishuo │ │ │ └── filedownloader │ │ │ ├── i │ │ │ ├── IFileDownloadIPCCallback.aidl │ │ │ └── IFileDownloadIPCService.aidl │ │ │ ├── message │ │ │ └── MessageSnapshot.aidl │ │ │ └── model │ │ │ ├── FileDownloadHeader.aidl │ │ │ └── FileDownloadTaskAtom.aidl │ ├── java │ │ └── com │ │ │ └── liulishuo │ │ │ └── filedownloader │ │ │ ├── BaseDownloadTask.java │ │ │ ├── DownloadSpeedMonitor.java │ │ │ ├── DownloadTask.java │ │ │ ├── DownloadTaskHunter.java │ │ │ ├── FileDownloadConnectListener.java │ │ │ ├── FileDownloadEventPool.java │ │ │ ├── FileDownloadLargeFileListener.java │ │ │ ├── FileDownloadLine.java │ │ │ ├── FileDownloadLineAsync.java │ │ │ ├── FileDownloadList.java │ │ │ ├── FileDownloadListener.java │ │ │ ├── FileDownloadMessageStation.java │ │ │ ├── FileDownloadMessenger.java │ │ │ ├── FileDownloadMonitor.java │ │ │ ├── FileDownloadQueueSet.java │ │ │ ├── FileDownloadSampleListener.java │ │ │ ├── FileDownloadServiceProxy.java │ │ │ ├── FileDownloadServiceSharedTransmit.java │ │ │ ├── FileDownloadServiceUIGuard.java │ │ │ ├── FileDownloadTaskLauncher.java │ │ │ ├── FileDownloader.java │ │ │ ├── IDownloadSpeed.java │ │ │ ├── IFileDownloadMessenger.java │ │ │ ├── IFileDownloadServiceProxy.java │ │ │ ├── ILostServiceConnectedHandler.java │ │ │ ├── IQueuesHandler.java │ │ │ ├── ITaskHunter.java │ │ │ ├── IThreadPoolMonitor.java │ │ │ ├── LostServiceConnectedHandler.java │ │ │ ├── MessageSnapshotGate.java │ │ │ ├── PauseAllMarker.java │ │ │ ├── QueuesHandler.java │ │ │ ├── connection │ │ │ ├── DefaultConnectionCountAdapter.java │ │ │ ├── FileDownloadConnection.java │ │ │ ├── FileDownloadUrlConnection.java │ │ │ └── RedirectHandler.java │ │ │ ├── database │ │ │ ├── FileDownloadDatabase.java │ │ │ ├── NoDatabaseImpl.java │ │ │ ├── RemitDatabase.java │ │ │ ├── SqliteDatabaseImpl.java │ │ │ └── SqliteDatabaseOpenHelper.java │ │ │ ├── download │ │ │ ├── ConnectTask.java │ │ │ ├── ConnectionProfile.java │ │ │ ├── CustomComponentHolder.java │ │ │ ├── DownloadLaunchRunnable.java │ │ │ ├── DownloadRunnable.java │ │ │ ├── DownloadStatusCallback.java │ │ │ ├── FetchDataTask.java │ │ │ └── ProcessCallback.java │ │ │ ├── event │ │ │ ├── DownloadEventPoolImpl.java │ │ │ ├── DownloadEventSampleListener.java │ │ │ ├── DownloadServiceConnectChangedEvent.java │ │ │ ├── IDownloadEvent.java │ │ │ ├── IDownloadEventPool.java │ │ │ └── IDownloadListener.java │ │ │ ├── exception │ │ │ ├── FileDownloadGiveUpRetryException.java │ │ │ ├── FileDownloadHttpException.java │ │ │ ├── FileDownloadNetworkPolicyException.java │ │ │ ├── FileDownloadOutOfSpaceException.java │ │ │ ├── FileDownloadSecurityException.java │ │ │ └── PathConflictException.java │ │ │ ├── message │ │ │ ├── BlockCompleteMessage.java │ │ │ ├── IFlowDirectly.java │ │ │ ├── IMessageSnapshot.java │ │ │ ├── LargeMessageSnapshot.java │ │ │ ├── MessageSnapshot.java │ │ │ ├── MessageSnapshotFlow.java │ │ │ ├── MessageSnapshotTaker.java │ │ │ ├── MessageSnapshotThreadPool.java │ │ │ └── SmallMessageSnapshot.java │ │ │ ├── model │ │ │ ├── ConnectionModel.java │ │ │ ├── FileDownloadHeader.java │ │ │ ├── FileDownloadModel.java │ │ │ ├── FileDownloadStatus.java │ │ │ └── FileDownloadTaskAtom.java │ │ │ ├── notification │ │ │ ├── BaseNotificationItem.java │ │ │ ├── FileDownloadNotificationHelper.java │ │ │ └── FileDownloadNotificationListener.java │ │ │ ├── services │ │ │ ├── BaseFileServiceUIGuard.java │ │ │ ├── DefaultIdGenerator.java │ │ │ ├── DownloadMgrInitialParams.java │ │ │ ├── FDServiceSeparateHandler.java │ │ │ ├── FDServiceSharedHandler.java │ │ │ ├── FileDownloadBroadcastHandler.java │ │ │ ├── FileDownloadManager.java │ │ │ ├── FileDownloadService.java │ │ │ ├── FileDownloadThreadPool.java │ │ │ ├── ForegroundServiceConfig.java │ │ │ └── IFileDownloadServiceHandler.java │ │ │ ├── stream │ │ │ ├── FileDownloadOutputStream.java │ │ │ └── FileDownloadRandomAccessFile.java │ │ │ └── util │ │ │ ├── DownloadServiceNotConnectedHelper.java │ │ │ ├── ExtraKeys.java │ │ │ ├── FileDownloadExecutors.java │ │ │ ├── FileDownloadHelper.java │ │ │ ├── FileDownloadLog.java │ │ │ ├── FileDownloadProperties.java │ │ │ ├── FileDownloadSerialQueue.java │ │ │ └── FileDownloadUtils.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ ├── java │ └── com │ │ └── liulishuo │ │ └── filedownloader │ │ ├── FileDownloaderTest.java │ │ ├── connection │ │ └── FileDownloadUrlConnectionTest.java │ │ ├── download │ │ ├── DownloadLaunchRunnableTest.java │ │ └── DownloadRunnableTest.java │ │ └── util │ │ └── FileDownloadUtilsTest.java │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── okcat.yml └── settings.gradle /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | #### Before Issue 2 | 3 | 1. Please search on the [Issues](https://github.com/lingochamp/FileDownloader/issues) 4 | 2. Please search on the [wiki](https://github.com/lingochamp/FileDownloader/wiki) 5 | 3. Please set `FileDownloadLog.NEED_LOG=true` and review the Logcat output from main process and `:filedownloader` process ( pay attention to Warn and Error level logcat) 6 | 7 | #### Issue 8 | 9 | 1. What problem do you get? 10 | 2. Which version of FileDownloader are you using when you produce such problem? 11 | 3. How to reproduce such problem? 12 | 4. Do you set `FileDownloadLog.NEED_LOG=true`? 13 | 5. Could you please reproduce this problem and provide all main process and `:filedownloader` process logcat 14 | 6. Can you fix it by yourself and request PR, if not, what's problem do you get when you try to fix it 15 | 16 | >P.S. If you don't know how to get `:filedownloader` process, it's recommended to using `pidcat` to just filter all your application logcat, or define `process.non-separate=true` on [filedownloader.properties](https://github.com/lingochamp/FileDownloader/wiki/filedownloader.properties) 17 | 18 | --- 19 | 20 | 请在Issue前认真的跟进上面提到的建议,这样将可以极大的加快你遇到问题的处理。 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | /.idea/misc.xml 7 | /.idea/checkstyle-idea.xml 8 | /.idea/caches 9 | .DS_Store 10 | /build 11 | /captures 12 | .classpath 13 | .project 14 | .settings 15 | .vscode 16 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/apache2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 11 | 13 | 14 | 16 | 17 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/dictionaries/Jacksgong.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | buildship 5 | chunked 6 | classpathentry 7 | dreamtobe 8 | etag 9 | filedownloader 10 | gradleclasspathcontainer 11 | gradleprojectbuilder 12 | gradleprojectnature 13 | jacksgong 14 | javabuilder 15 | javanature 16 | liulishuo 17 | okhttp 18 | robolectric 19 | sofar 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | jdk: 4 | # build-tools 24.0.2 need jdk8 or above. 5 | - oraclejdk8 6 | android: 7 | components: 8 | # Ref https://github.com/travis-ci/travis-ci/issues/6260. 9 | - tools 10 | - platform-tools 11 | - build-tools-28.0.3 12 | - android-28 13 | - extra 14 | 15 | script: 16 | - ./gradlew clean check 17 | 18 | after_script: 19 | - cat ./demo/build/outputs/lint-results.xml 20 | - cat ./library/build/outputs/lint-results.xml 21 | 22 | sudo: false 23 | 24 | before_cache: 25 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 26 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 27 | 28 | cache: 29 | directories: 30 | - $HOME/.gradle/caches/ 31 | - $HOME/.gradle/wrapper/ 32 | - $HOME/.android/build-cache 33 | -------------------------------------------------------------------------------- /art/Cause_of_Attached.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/Cause_of_Attached.png -------------------------------------------------------------------------------- /art/avoid_drop_frames1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/avoid_drop_frames1.gif -------------------------------------------------------------------------------- /art/avoid_drop_frames2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/avoid_drop_frames2.gif -------------------------------------------------------------------------------- /art/chunked_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/chunked_demo.gif -------------------------------------------------------------------------------- /art/filedownload_sample_description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/filedownload_sample_description.png -------------------------------------------------------------------------------- /art/filedownloader-eclipse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/filedownloader-eclipse.jpg -------------------------------------------------------------------------------- /art/filedownloadlistener_callback_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/filedownloadlistener_callback_flow.png -------------------------------------------------------------------------------- /art/hybrid_test_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/hybrid_test_demo.gif -------------------------------------------------------------------------------- /art/message-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/message-system.png -------------------------------------------------------------------------------- /art/mix.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/mix.gif -------------------------------------------------------------------------------- /art/mix_tasks_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/mix_tasks_demo.gif -------------------------------------------------------------------------------- /art/parallel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/parallel.gif -------------------------------------------------------------------------------- /art/parallel_tasks_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/parallel_tasks_demo.gif -------------------------------------------------------------------------------- /art/remit-database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/remit-database.png -------------------------------------------------------------------------------- /art/serial.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/serial.gif -------------------------------------------------------------------------------- /art/serial_tasks_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/serial_tasks_demo.gif -------------------------------------------------------------------------------- /art/single.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/single.gif -------------------------------------------------------------------------------- /art/single_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/single_demo.gif -------------------------------------------------------------------------------- /art/single_progress.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/single_progress.gif -------------------------------------------------------------------------------- /art/single_task_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/single_task_demo.gif -------------------------------------------------------------------------------- /art/single_task_demo_en.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/single_task_demo_en.gif -------------------------------------------------------------------------------- /art/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/structure.png -------------------------------------------------------------------------------- /art/tasks_manager_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/art/tasks_manager_demo.gif -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | google() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:3.3.1' 8 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | jcenter() 15 | google() 16 | } 17 | } 18 | 19 | subprojects { 20 | group = GROUP 21 | version = VERSION_NAME 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | signingConfigs { 5 | release { 6 | keyAlias 'FileDownloaderDemoKey' 7 | keyPassword 'liulishuo' 8 | storeFile file('filedownloaderdemo.jks') 9 | storePassword 'liulishuo' 10 | } 11 | } 12 | compileSdkVersion COMPILE_SDK_VERSION as int 13 | buildToolsVersion BUILD_TOOLS_VERSION as String 14 | 15 | defaultConfig { 16 | minSdkVersion 14 17 | targetSdkVersion COMPILE_SDK_VERSION as int 18 | 19 | File file = project.rootProject.file('local.properties'); 20 | def needLog = null 21 | if (file.exists()) { 22 | Properties p = new Properties() 23 | p.load(file.newDataInputStream()) 24 | needLog = p.getProperty("needLog") 25 | } 26 | buildConfigField "boolean", "DOWNLOAD_NEED_LOG", needLog == "true" ? "true" : "false" 27 | } 28 | buildTypes { 29 | release { 30 | minifyEnabled true 31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 32 | signingConfig signingConfigs.release 33 | } 34 | 35 | debug { 36 | minifyEnabled false 37 | } 38 | } 39 | lintOptions { 40 | // This seems to be firing due to okio referencing java.nio.File 41 | // which is harmless for us. 42 | warning 'InvalidPackage' 43 | } 44 | } 45 | 46 | dependencies { 47 | implementation 'com.android.support:appcompat-v7:28.0.0' 48 | implementation 'com.android.support:recyclerview-v7:28.0.0' 49 | implementation 'com.android.support:design:28.0.0' 50 | debugImplementation 'cn.dreamtobe.threaddebugger:threaddebugger:1.3.3' 51 | releaseImplementation 'cn.dreamtobe.threaddebugger:threaddebugger-no-op:1.3.3' 52 | implementation project(':library') 53 | // for testing 54 | implementation 'com.squareup.okio:okio:1.14.0' 55 | } 56 | -------------------------------------------------------------------------------- /demo/filedownloaderdemo.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/demo/filedownloaderdemo.jks -------------------------------------------------------------------------------- /demo/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # filedownloader uses okhttp3-lib, so need add below proguard rules. 2 | -dontwarn okhttp3.* 3 | -dontwarn okio.** -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 14 | 15 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 36 | 39 | 42 | 45 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /demo/src/main/assets/filedownloader.properties: -------------------------------------------------------------------------------- 1 | # If you occur exception: 'can't know the size of the download file, and its Transfer-Encoding is not Chunked either', 2 | # but you want to ignore such exception, set true, will deal with it as the case of transfer encoding chunk. default false 3 | # 4 | # If true, will ignore HTTP response header does not has content-length either not chunk transfer 5 | # encoding. 6 | # 7 | # Default false. 8 | http.lenient=false 9 | 10 | # The FileDownloadService runs in the separate process ':filedownloader' as default, if you want to 11 | # run the FileDownloadService in the main process, just set true. default false. 12 | process.non-separate=false 13 | 14 | # The min buffered so far bytes. 15 | # 16 | # Used for adjudging whether is time to sync the downloaded so far bytes to database and make sure 17 | # sync the downloaded buffer to local file. 18 | # 19 | # More smaller more frequently, then download more slowly, but will more safer in scene of the 20 | # process is killed unexpectedly. 21 | # 22 | # Default 65536, which follow the value in com.android.providers.downloads.Constants. 23 | download.min-progress-step=65536 24 | 25 | # The min buffered millisecond. 26 | # 27 | # Used for adjudging whether is time to sync the downloaded so far bytes to database and make sure 28 | # sync the downloaded buffer to local file. 29 | # 30 | # More smaller more frequently, then download more slowly, but will more safer in scene of the 31 | # process is killed unexpectedly. 32 | # 33 | # Default 2000, which follow the value in com.android.providers.downloads.Constants. 34 | download.min-progress-time=2000 35 | 36 | # The maximum network thread count for downloading simultaneously. 37 | # 38 | # FileDownloader is designed to download 3 files simultaneously as maximum size as default, and the 39 | # rest of the task is in the FIFO(First In First Out) pending queue. 40 | # 41 | # Because the network resource is limited to one device, it means if FileDownloader start 42 | # downloading tasks unlimited simultaneously, it will be blocked by lack of the network resource, 43 | # and more useless CPU occupy. 44 | # 45 | # The relative efficiency of 3 is higher than others(As Fresco or Picasso do), But for case by case 46 | # FileDownloader is support to configure for this. 47 | # 48 | # Default 3. 49 | # max 12, min 1. If the value more than {@code max} will be replaced with {@code max}; If the value 50 | # less than {@code min} will be replaced with {@code min}. 51 | download.max-network-thread-count=3 52 | 53 | # Whether need to pre-allocates the 'content-length' space when start downloading. 54 | # 55 | # FileDownloader is designed to create the file and pre-allocates the 'content-length' space for it 56 | # when start downloading. 57 | # 58 | # Because FileDownloader want to prevent the space is not enough to store coming data in downloading 59 | # state as default. 60 | # 61 | # Default false. 62 | # 63 | file.non-pre-allocation=false 64 | 65 | # Whether need to post an broadcast when downloading is completed. 66 | # 67 | # This option is very useful when you download something silent on the background on the filedownloader 68 | # process, and the main process is killed, but you want to do something on the main process when tasks 69 | # are completed downloading on the filedownloader process, so you can set this one to `true`, then 70 | # when a task is completed task, you will receive the broadcast, and the main process will be relaunched 71 | # to handle the broadcast. 72 | # 73 | # If you want to receive such broadcast, you also need to register receiver with 74 | # 'filedownloader.intent.action.completed' action name on 'AndroidManifest.xml'. 75 | # 76 | # You can use FileDownloadBroadcastHandler class to parse the received intent. 77 | # 78 | # Default false. 79 | # 80 | broadcast.completed=false 81 | 82 | # Whether you want the first trial connection with HEAD method to request to backend or not. 83 | # 84 | # if this value is true, the first trial connection will with HEAD method instead of GET method and 85 | # then you will reduce 1 byte cost on the response body, but if the backend can't support HEAD 86 | # method you will receive 405 response code and failed to download. 87 | # 88 | # Default false. 89 | # 90 | download.trial-connection-head-method=false 91 | -------------------------------------------------------------------------------- /demo/src/main/assets/performance_test_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingochamp/FileDownloader/6237a8cac174bcc916e4342b14ab1ab72a5768d4/demo/src/main/assets/performance_test_data -------------------------------------------------------------------------------- /demo/src/main/java/com/liulishuo/filedownloader/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.liulishuo.filedownloader.demo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.util.Log; 6 | 7 | import com.liulishuo.filedownloader.FileDownloader; 8 | import com.liulishuo.filedownloader.connection.FileDownloadUrlConnection; 9 | import com.liulishuo.filedownloader.util.FileDownloadLog; 10 | import com.liulishuo.filedownloader.util.FileDownloadUtils; 11 | 12 | import cn.dreamtobe.threaddebugger.IThreadDebugger; 13 | import cn.dreamtobe.threaddebugger.ThreadDebugger; 14 | import cn.dreamtobe.threaddebugger.ThreadDebuggers; 15 | 16 | /** 17 | * Created by Jacksgong on 12/17/15. 18 | */ 19 | public class DemoApplication extends Application { 20 | public static Context CONTEXT; 21 | private final static String TAG = "FileDownloadApplication"; 22 | 23 | @Override 24 | public void onCreate() { 25 | super.onCreate(); 26 | // for demo. 27 | CONTEXT = this; 28 | 29 | // just for open the log in this demo project. 30 | FileDownloadLog.NEED_LOG = BuildConfig.DOWNLOAD_NEED_LOG; 31 | 32 | /** 33 | * just for cache Application's Context, and ':filedownloader' progress will NOT be launched 34 | * by below code, so please do not worry about performance. 35 | * @see FileDownloader#init(Context) 36 | */ 37 | FileDownloader.setupOnApplicationOnCreate(this) 38 | .connectionCreator(new FileDownloadUrlConnection 39 | .Creator(new FileDownloadUrlConnection.Configuration() 40 | .connectTimeout(15_000) // set connection timeout. 41 | .readTimeout(15_000) // set read timeout. 42 | )) 43 | .commit(); 44 | 45 | // below codes just for monitoring thread pools in the FileDownloader: 46 | IThreadDebugger debugger = ThreadDebugger.install( 47 | ThreadDebuggers.create() /** The ThreadDebugger with known thread Categories **/ 48 | // add Thread Category 49 | .add("OkHttp").add("okio").add("Binder") 50 | .add(FileDownloadUtils.getThreadPoolName("Network"), "Network") 51 | .add(FileDownloadUtils.getThreadPoolName("Flow"), "FlowSingle") 52 | .add(FileDownloadUtils.getThreadPoolName("EventPool"), "Event") 53 | .add(FileDownloadUtils.getThreadPoolName("LauncherTask"), "LauncherTask") 54 | .add(FileDownloadUtils.getThreadPoolName("ConnectionBlock"), "Connection") 55 | .add(FileDownloadUtils.getThreadPoolName("RemitHandoverToDB"), "RemitHandoverToDB") 56 | .add(FileDownloadUtils.getThreadPoolName("BlockCompleted"), "BlockCompleted"), 57 | 58 | 2000, /** The frequent of Updating Thread Activity information **/ 59 | 60 | new ThreadDebugger.ThreadChangedCallback() { 61 | /** 62 | * The threads changed callback 63 | **/ 64 | @Override 65 | public void onChanged(IThreadDebugger debugger) { 66 | // callback this method when the threads in this application has changed. 67 | Log.d(TAG, debugger.drawUpEachThreadInfoDiff()); 68 | Log.d(TAG, debugger.drawUpEachThreadSizeDiff()); 69 | Log.d(TAG, debugger.drawUpEachThreadSize()); 70 | } 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /demo/src/main/java/com/liulishuo/filedownloader/demo/GlobalMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 LingoChamp Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.liulishuo.filedownloader.demo; 18 | 19 | import android.util.Log; 20 | 21 | import com.liulishuo.filedownloader.BaseDownloadTask; 22 | import com.liulishuo.filedownloader.FileDownloadListener; 23 | import com.liulishuo.filedownloader.FileDownloadMonitor; 24 | 25 | /** 26 | * Created by Jacksgong on 1/19/16. 27 | */ 28 | public class GlobalMonitor implements FileDownloadMonitor.IMonitor { 29 | private volatile int markStart; 30 | private volatile int markOver; 31 | 32 | private final static class HolderClass { 33 | private final static GlobalMonitor INSTANCE = new GlobalMonitor(); 34 | } 35 | 36 | public static GlobalMonitor getImpl() { 37 | return HolderClass.INSTANCE; 38 | } 39 | 40 | private final static String TAG = "GlobalMonitor"; 41 | 42 | @Override 43 | public void onRequestStart(int count, boolean serial, FileDownloadListener lis) { 44 | markStart = 0; 45 | markOver = 0; 46 | Log.d(TAG, String.format("on request start %d %B", count, serial)); 47 | } 48 | 49 | @Override 50 | public void onRequestStart(BaseDownloadTask task) { 51 | } 52 | 53 | @Override 54 | public void onTaskBegin(BaseDownloadTask task) { 55 | markStart++; 56 | } 57 | 58 | @Override 59 | public void onTaskStarted(BaseDownloadTask task) { 60 | 61 | } 62 | 63 | @Override 64 | public void onTaskOver(BaseDownloadTask task) { 65 | markOver++; 66 | } 67 | 68 | public int getMarkStart() { 69 | return markStart; 70 | } 71 | 72 | public int getMarkOver() { 73 | return markOver; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /demo/src/main/java/com/liulishuo/filedownloader/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.liulishuo.filedownloader.demo; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | 11 | import com.liulishuo.filedownloader.FileDownloadMonitor; 12 | import com.liulishuo.filedownloader.FileDownloader; 13 | import com.liulishuo.filedownloader.demo.performance.PerformanceTestActivity; 14 | 15 | /** 16 | * Created by Jacksgong on 12/17/15. 17 | */ 18 | public class MainActivity extends AppCompatActivity { 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | 24 | setContentView(R.layout.activity_main); 25 | 26 | // 这是只是为了全局监控。如果你有需求需要全局监控(比如用于打点/统计)可以使用这个方式,如果没有类似需求就不需要 27 | // 如果你有这个需求,实现FileDownloadMonitor.IMonitor接口,也使用FileDownloadMonitor.setGlobalMonitor 28 | // 注册进去即可 29 | // You do not have to add below code to your project only if you need monitor the global 30 | // FileDownloader Engine for statistic or others 31 | // If you have such requirement, just implement FileDownloadMonitor.IMonitor, and register it 32 | // use FileDownloadDownloader.setGlobalMonitor the same as below code. 33 | FileDownloadMonitor.setGlobalMonitor(GlobalMonitor.getImpl()); 34 | } 35 | 36 | public void onClickMultitask(final View view) { 37 | startActivity(new Intent(this, MultitaskTestActivity.class)); 38 | } 39 | 40 | public void onClickSingle(final View view) { 41 | startActivity(new Intent(this, SingleTaskTestActivity.class)); 42 | } 43 | 44 | public void onClickHybridTest(final View view) { 45 | startActivity(new Intent(this, HybridTestActivity.class)); 46 | } 47 | 48 | public void onClickTasksManager(final View view) { 49 | startActivity(new Intent(this, TasksManagerDemoActivity.class)); 50 | } 51 | 52 | public void onClickPerformance(final View view) { 53 | startActivity(new Intent(this, PerformanceTestActivity.class)); 54 | } 55 | 56 | public void onClickNotification(final View view){ 57 | startActivity(new Intent(this, NotificationSampleActivity.class)); 58 | } 59 | 60 | @Override 61 | public boolean onCreateOptionsMenu(Menu menu) { 62 | getMenuInflater().inflate(R.menu.menu_main, menu); 63 | return super.onCreateOptionsMenu(menu); 64 | } 65 | 66 | 67 | @Override 68 | public boolean onOptionsItemSelected(MenuItem item) { 69 | switch (item.getItemId()) { 70 | case R.id.menu_github: 71 | openGitHub(); 72 | return true; 73 | default: 74 | return super.onOptionsItemSelected(item); 75 | } 76 | } 77 | 78 | private void openGitHub() { 79 | Uri uri = Uri.parse(getString(R.string.app_github_url)); 80 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 81 | startActivity(intent); 82 | } 83 | 84 | @Override 85 | protected void onDestroy() { 86 | super.onDestroy(); 87 | // unbind and stop service manually if idle 88 | FileDownloader.getImpl().unBindServiceIfIdle(); 89 | 90 | FileDownloadMonitor.releaseGlobalMonitor(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /demo/src/main/java/com/liulishuo/filedownloader/demo/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 LingoChamp Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.liulishuo.filedownloader.demo; 18 | 19 | import android.app.NotificationChannel; 20 | import android.app.NotificationManager; 21 | import android.content.Context; 22 | import android.os.Build; 23 | import android.support.annotation.Nullable; 24 | 25 | public class Utils { 26 | public static void createNotificationChannel( 27 | String channelId, 28 | String channelName, 29 | Context context 30 | ) { 31 | NotificationManager notificationManager = getNotificationManager(context); 32 | if (notificationManager == null) return; 33 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 34 | NotificationChannel channel = new NotificationChannel( 35 | channelId, 36 | channelName, 37 | NotificationManager.IMPORTANCE_LOW); 38 | notificationManager.createNotificationChannel(channel); 39 | } 40 | } 41 | 42 | public static void deleteNotificationChannel(String channelId, Context context) { 43 | NotificationManager notificationManager = getNotificationManager(context); 44 | if (notificationManager == null) return; 45 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 46 | notificationManager.deleteNotificationChannel(channelId); 47 | } 48 | } 49 | 50 | @Nullable 51 | public static NotificationManager getNotificationManager(Context context) { 52 | return ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /demo/src/main/java/com/liulishuo/filedownloader/demo/performance/IntParcel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 LingoChamp Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.liulishuo.filedownloader.demo.performance; 18 | 19 | import android.os.Parcel; 20 | import android.os.Parcelable; 21 | 22 | /** 23 | * Created by Jacksgong on 1/4/16. 24 | */ 25 | public class IntParcel implements Parcelable { 26 | 27 | private int v1 = Integer.MAX_VALUE; 28 | private int v2 = Integer.MAX_VALUE; 29 | private int v3 = Integer.MAX_VALUE; 30 | 31 | 32 | public void operate() { 33 | v1 -= 11; 34 | v2 -= 12; 35 | v3 -= 13; 36 | } 37 | 38 | @Override 39 | public int describeContents() { 40 | return 0; 41 | } 42 | 43 | @Override 44 | public void writeToParcel(Parcel dest, int flags) { 45 | dest.writeInt(this.v1); 46 | dest.writeInt(this.v2); 47 | dest.writeInt(this.v3); 48 | } 49 | 50 | public IntParcel() { 51 | } 52 | 53 | protected IntParcel(Parcel in) { 54 | this.v1 = in.readInt(); 55 | this.v2 = in.readInt(); 56 | this.v3 = in.readInt(); 57 | } 58 | 59 | public static final Creator CREATOR = new Creator() { 60 | public IntParcel createFromParcel(Parcel source) { 61 | return new IntParcel(source); 62 | } 63 | 64 | public IntParcel[] newArray(int size) { 65 | return new IntParcel[size]; 66 | } 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /demo/src/main/java/com/liulishuo/filedownloader/demo/performance/LongParcel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 LingoChamp Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.liulishuo.filedownloader.demo.performance; 18 | 19 | import android.os.Parcel; 20 | import android.os.Parcelable; 21 | 22 | /** 23 | * Created by Jacksgong on 1/4/16. 24 | */ 25 | public class LongParcel implements Parcelable { 26 | 27 | private long v1 = Integer.MAX_VALUE; 28 | private long v2 = Integer.MAX_VALUE; 29 | private long v3 = Integer.MAX_VALUE; 30 | 31 | public void operate() { 32 | v1 -= 11; 33 | v2 -= 12; 34 | v3 -= 13; 35 | } 36 | 37 | @Override 38 | public int describeContents() { 39 | return 0; 40 | } 41 | 42 | @Override 43 | public void writeToParcel(Parcel dest, int flags) { 44 | dest.writeLong(this.v1); 45 | dest.writeLong(this.v2); 46 | dest.writeLong(this.v3); 47 | } 48 | 49 | public LongParcel() { 50 | } 51 | 52 | protected LongParcel(Parcel in) { 53 | this.v1 = in.readLong(); 54 | this.v2 = in.readLong(); 55 | this.v3 = in.readLong(); 56 | } 57 | 58 | public static final Creator CREATOR = new Creator() { 59 | public LongParcel createFromParcel(Parcel source) { 60 | return new LongParcel(source); 61 | } 62 | 63 | public LongParcel[] newArray(int size) { 64 | return new LongParcel[size]; 65 | } 66 | }; 67 | } 68 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable/bg_item_task_manager.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_hybrid_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 |