├── .gitignore ├── AppUpdateLibrary.gif ├── LICENSE ├── README.md ├── app-debug.apk ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── dcastalia │ │ └── localapkupdatelibrary │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── dcastalia │ │ │ └── localapkupdatelibrary │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── provider_paths.xml │ └── test │ └── java │ └── com │ └── dcastalia │ └── localapkupdatelibrary │ └── ExampleUnitTest.java ├── appupdatelibrary ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── dcastalia │ │ └── localappupdate │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── dcastalia │ │ │ └── localappupdate │ │ │ └── DownloadApk.kt │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── dcastalia │ └── localappupdate │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.aar 3 | *.ap_ 4 | *.aab 5 | 6 | # Files for the ART/Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | out/ 16 | # Uncomment the following line in case you need and you don't have the release build type files in your app 17 | # release/ 18 | 19 | # Gradle files 20 | .gradle/ 21 | build/ 22 | 23 | # Local configuration file (sdk path, etc) 24 | local.properties 25 | 26 | # Proguard folder generated by Eclipse 27 | proguard/ 28 | 29 | # Log Files 30 | *.log 31 | 32 | # Android Studio Navigation editor temp files 33 | .navigation/ 34 | 35 | # Android Studio captures folder 36 | captures/ 37 | 38 | # IntelliJ 39 | *.iml 40 | .idea/ 41 | 42 | # Keystore files 43 | # Uncomment the following lines if you do not want to check your keystore files in. 44 | #*.jks 45 | #*.keystore 46 | 47 | # External native build folder generated in Android Studio 2.2 and later 48 | .externalNativeBuild 49 | .cxx/ 50 | 51 | # Google Services (e.g. APIs or Firebase) 52 | # google-services.json 53 | 54 | # Freeline 55 | freeline.py 56 | freeline/ 57 | freeline_project_description.json 58 | 59 | # fastlane 60 | fastlane/report.xml 61 | fastlane/Preview.html 62 | fastlane/screenshots 63 | fastlane/test_output 64 | fastlane/readme.md 65 | 66 | # Version control 67 | vcs.xml 68 | 69 | # lint 70 | lint/intermediates/ 71 | lint/generated/ 72 | lint/outputs/ 73 | lint/tmp/ 74 | # lint/reports/ 75 | 76 | # Android Profiling 77 | *.hprof 78 | -------------------------------------------------------------------------------- /AppUpdateLibrary.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Piashsarker/AndroidAppUpdateLibrary/2903b1c97a764a71133dfe19692c95d620d0323a/AppUpdateLibrary.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Piash Sarker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidAppUpdateLibrary 2 | Android App Update Library can be used for downloading the Apk from a link , Save it to External or Internal Storage, Than automatic installing the apk. Remember to add provider xml and android runtime permission before using this library. See sample use in app folder. 3 | 4 | ### Changelog 5 | Version: 1.0.4 6 | - Updated dependencies (upgrade to AndroidX) (df0ce1a) 7 | - Fixed failed install on lower Android versions (4603d10) 8 | - Rewrite to Kotlin (8d32d31) 9 | - Fixed calcualtion of download percentage (42e4dbb) 10 | - Made installation possible on higher Android versions (8a9be2e) 11 | - New optional file name parameter (fe4c1ab) 12 | 13 | Thanks to @cyb3rko 14 | 15 | Version : 1.0.3 16 | 17 | Update Target SDK Version To 27 ( Android Oreo) 18 | Added Permission For Package Install For Android Oreo. 19 | 20 | 21 | 22 | 23 | [![](https://jitpack.io/v/Piashsarker/AndroidAppUpdateLibrary.svg)](https://jitpack.io/#Piashsarker/AndroidAppUpdateLibrary) 24 | 25 | ![AndroidAppUpdateLibrary](https://github.com/Piashsarker/AndroidAppUpdateLibrary/blob/master/AppUpdateLibrary.gif) 26 | 27 | ## Usage 28 | 29 | #### Step 1. Add the JitPack repository to your build file 30 | 31 | Add it in your project level root build.gradle at the end of repositories:
32 | 33 | 34 | allprojects { 35 | repositories { 36 | ... 37 | maven { url 'https://jitpack.io' } 38 | } 39 | } 40 | 41 | #### Step 2. Add the dependency in your app build.gradle file 42 | 43 | dependencies { 44 | implementation 'com.github.Piashsarker:AndroidAppUpdateLibrary:1.0.4' 45 | } 46 | 47 | 48 | #### Step 3. Add Runtime Permission 49 | 50 | Remember to add below permission in `Manifest.xml file` . And Also add runtime permission for (Version => Marshmallow ). See the sample app. 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | #### Step 4. Add Provider XML 60 | Create a folder called `xml` in `res` folder. Create a xml file and named it `provider_paths`. Paste below code: 61 | 62 | 63 | 64 | 65 | 66 | 67 | Add below code in your `AndroidManifest.xml` file. 68 | 69 | 70 | 78 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | #### Step 5. For downloading and installing the apk automatically. 88 | 89 | After setting up all neccessary files it's just two line of code to download and install the apk updates in your device. 90 | 91 | String url = "https://github.com/Piashsarker/AndroidAppUpdateLibrary/raw/master/app-debug.apk"; 92 | 93 | DownloadApk downloadApk = new DownloadApk(MainActivity.this); 94 | 95 | // With standard fileName 'App Update.apk' 96 | downloadApk.startDownloadingApk(url); 97 | 98 | // With custom fileName, e.g. 'Update 2.0' 99 | downloadApk.startDownloadingApk(url, "Update 2.0"); 100 | 101 | 102 | You are Good To Go. Happy Coding 103 | 104 | ### MIT License 105 | 106 | #### Copyright (c) 2018 Piash Sarker 107 | 108 | Permission is hereby granted, free of charge, to any person obtaining a copy 109 | of this software and associated documentation files (the "Software"), to deal 110 | in the Software without restriction, including without limitation the rights 111 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 112 | copies of the Software, and to permit persons to whom the Software is 113 | furnished to do so, subject to the following conditions: 114 | 115 | The above copyright notice and this permission notice shall be included in all 116 | copies or substantial portions of the Software. 117 | 118 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 119 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 120 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 121 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 122 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 123 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 124 | SOFTWARE. 125 | -------------------------------------------------------------------------------- /app-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Piashsarker/AndroidAppUpdateLibrary/2903b1c97a764a71133dfe19692c95d620d0323a/app-debug.apk -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | buildToolsVersion "29.0.3" 6 | defaultConfig { 7 | applicationId "com.dcastalia.localapkupdatelibrary" 8 | minSdkVersion 19 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(include: ['*.jar'], dir: 'libs') 24 | implementation 'androidx.appcompat:appcompat:1.2.0' 25 | implementation 'com.android.support.constraint:constraint-layout:2.0.4' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 28 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 29 | implementation project(':appupdatelibrary') 30 | } 31 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/dcastalia/localapkupdatelibrary/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.dcastalia.localapkupdatelibrary; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.dcastalia.localapkupdatelibrary", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/dcastalia/localapkupdatelibrary/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.dcastalia.localapkupdatelibrary; 2 | 3 | import android.Manifest; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | import android.widget.Toast; 10 | import androidx.annotation.NonNull; 11 | import androidx.appcompat.app.AppCompatActivity; 12 | import androidx.core.app.ActivityCompat; 13 | 14 | import com.dcastalia.localappupdate.DownloadApk; 15 | 16 | public class MainActivity extends AppCompatActivity { 17 | private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1001; 18 | private TextView versionText ; 19 | private String version; 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | try { 25 | PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0); 26 | version = pInfo.versionName; 27 | } catch (PackageManager.NameNotFoundException e) { 28 | e.printStackTrace(); 29 | } 30 | versionText= findViewById(R.id.txt_version); 31 | versionText.setText("Current Version "+version); 32 | } 33 | 34 | /** TODO: Must need to check the External Storage Permission Because we are storing the 35 | * ApK in the External Or Internal Storage. 36 | */ 37 | private void checkWriteExternalStoragePermission() { 38 | 39 | if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 40 | // If we have permission than we can Start the Download the task 41 | downloadTask(); 42 | } else { 43 | // If we don't have permission than requesting the permission 44 | requestWriteExternalStoragePermission(); 45 | } 46 | } 47 | 48 | private void requestWriteExternalStoragePermission() { 49 | if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) { 50 | ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); 51 | } else{ 52 | ActivityCompat.requestPermissions(MainActivity.this,new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); 53 | } 54 | } 55 | 56 | @Override 57 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 58 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 59 | if (requestCode==MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 60 | downloadTask(); 61 | } else { 62 | Toast.makeText(MainActivity.this, "Permission Not Granted.", Toast.LENGTH_SHORT).show(); 63 | } 64 | } 65 | 66 | 67 | 68 | public void download(View view) { 69 | // First check the external storage permission 70 | checkWriteExternalStoragePermission(); 71 | } 72 | 73 | private void downloadTask() { 74 | // This @DownloadApk class is provided by our library 75 | // Pass the Context when creating object of DownloadApk 76 | 77 | DownloadApk downloadApk = new DownloadApk(MainActivity.this); 78 | 79 | // For starting download call the method startDownloadingApk() by passing the URL and the optional filename 80 | downloadApk.startDownloadingApk("https://github.com/Piashsarker/AndroidAppUpdateLibrary/raw/master/app-debug.apk", "Update 2.0"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |