Aktualisiere Installer und optimiere Updater-Code
parent
2ebc7b4c97
commit
74b53d7630
@ -1,77 +0,0 @@
|
||||
package com.cyb3rko.techniklogger
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.androidnetworking.AndroidNetworking
|
||||
import com.androidnetworking.error.ANError
|
||||
import com.androidnetworking.interfaces.StringRequestListener
|
||||
import com.cyb3rko.installer.DownloadApk
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import es.dmoral.toasty.Toasty
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
internal fun updateCheck(activity: MainActivity) {
|
||||
AndroidNetworking.initialize(activity)
|
||||
AndroidNetworking.get("https://git.aldiserver.de/api/v1/repos/niko/technik-logger-app/contents/app/build.gradle")
|
||||
.addHeaders("Authorization", "token d70a26aa455b25e60885ba5ff31cce231d454f82")
|
||||
.doNotCacheResponse()
|
||||
.build()
|
||||
.getAsString(object : StringRequestListener {
|
||||
override fun onResponse(response: String?) {
|
||||
try {
|
||||
var parts = response!!.split("content\":\"")
|
||||
var parts2 = parts[1].split("\",\"target")
|
||||
val content = String(Base64.decode(parts2[0], Base64.DEFAULT), StandardCharsets.UTF_8)
|
||||
|
||||
parts = content.split("versionCode ")
|
||||
parts2 = parts[1].split("\n")
|
||||
val neuesterVersionCode = parts2[0].toInt()
|
||||
parts = parts2[1].split("\"")
|
||||
parts2 = parts[1].split("\"")
|
||||
val newestVersion = parts2[0]
|
||||
|
||||
if (BuildConfig.VERSION_CODE != neuesterVersionCode) {
|
||||
Log.d("Technik-Logger Updater", "Update verfügbar: $newestVersion")
|
||||
showDownloadDialog(activity, newestVersion)
|
||||
|
||||
ActivityCompat.requestPermissions(
|
||||
activity, arrayOf(Manifest.permission.INTERNET, Manifest.permission.WRITE_EXTERNAL_STORAGE), 1
|
||||
)
|
||||
} else {
|
||||
Log.d(activity.toString(), "App auf dem neuesten Stand")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Toasty.error(activity, "Update-Check fehlgeschlagen", Toasty.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(anError: ANError?) {
|
||||
Log.d(activity.toString(), "Update-Abfrage fehlgeschlagen: ${anError!!.errorBody.trimIndent()}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
internal fun showDownloadDialog(context: Context, newestVersion: String) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle("Neues Update verfügbar")
|
||||
.setMessage("Das Update '$newestVersion' steht zum Download bereit!\n\nAktuell installierte Version: '${BuildConfig.VERSION_NAME}'")
|
||||
.setPositiveButton("Herunterladen") { _, _ ->
|
||||
downloadApk(context, newestVersion)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun downloadApk(context: Context, newestVersion: String) {
|
||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
val link = "https://cdn.cyb3rko.de/Apps/Technik-Logger/Technik-Logger%20v$newestVersion.apk"
|
||||
DownloadApk(context).startDownloadingApk(link)
|
||||
} else {
|
||||
Toasty.error(context, "Fehlende Berechtigung, erteile diese beim nächsten App-Start", Toasty.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
package com.cyb3rko.techniklogger.update
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import android.webkit.URLUtil
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.FileProvider
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* Created by piashsarker on 1/16/18, rewritten by Cyb3rKo on 12/21/20.
|
||||
*/
|
||||
|
||||
class DownloadApk(var context: Context) : AppCompatActivity() {
|
||||
|
||||
@JvmOverloads
|
||||
fun startDownloadingApk(url: String, fileName: String = "App Update") {
|
||||
if (URLUtil.isValidUrl(url)) {
|
||||
DownloadNewVersion(context, url, fileName).execute()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private class DownloadNewVersion(
|
||||
val context: Context,
|
||||
val downloadUrl: String,
|
||||
val fileName: String
|
||||
): AsyncTask<String, Int, Boolean>() {
|
||||
private lateinit var bar: ProgressDialog
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
bar = ProgressDialog(context).apply {
|
||||
setCancelable(false)
|
||||
setMessage("Downloading...")
|
||||
isIndeterminate = true
|
||||
setCanceledOnTouchOutside(false)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgressUpdate(vararg values: Int?) {
|
||||
super.onProgressUpdate(*values)
|
||||
var msg = ""
|
||||
val progress = values[0]
|
||||
if (progress != null) {
|
||||
bar.progress = progress
|
||||
msg = if (progress > 99) "Finishing... " else "Downloading... $progress%"
|
||||
}
|
||||
|
||||
bar.apply {
|
||||
isIndeterminate = false
|
||||
max = 100
|
||||
setMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: Boolean?) {
|
||||
super.onPostExecute(result)
|
||||
bar.dismiss()
|
||||
if (result != null && result) {
|
||||
Toast.makeText(context, "Update Done", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(context, "Error: Try Again", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg p0: String?): Boolean {
|
||||
var flag = false
|
||||
|
||||
try {
|
||||
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/"
|
||||
var outputFile = File("$path$fileName.apk")
|
||||
var repetition = 1
|
||||
while (outputFile.exists()) {
|
||||
outputFile = File("$path$fileName ($repetition).apk")
|
||||
repetition++
|
||||
}
|
||||
|
||||
val directory = File(path)
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
|
||||
val url = URL(downloadUrl)
|
||||
val c = url.openConnection() as HttpURLConnection
|
||||
c.requestMethod = "GET"
|
||||
c.connect()
|
||||
|
||||
val fos = FileOutputStream(outputFile)
|
||||
val inputStream = c.inputStream
|
||||
val totalSize = c.contentLength.toFloat() //size of apk
|
||||
|
||||
val buffer = ByteArray(1024)
|
||||
var len1: Int
|
||||
var per: Float
|
||||
var downloaded = 0f
|
||||
while (inputStream.read(buffer).also { len1 = it } != -1) {
|
||||
fos.write(buffer, 0, len1)
|
||||
downloaded += len1
|
||||
per = (downloaded * 100 / totalSize)
|
||||
publishProgress(per.toInt())
|
||||
}
|
||||
fos.close()
|
||||
inputStream.close()
|
||||
openNewVersion(outputFile.path)
|
||||
flag = true
|
||||
} catch (e: MalformedURLException) {
|
||||
Log.e("DownloadApk", "Update Error: " + e.message)
|
||||
flag = false
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return flag
|
||||
}
|
||||
|
||||
private fun openNewVersion(location: String) {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(
|
||||
getUriFromFile(location),
|
||||
"application/vnd.android.package-archive"
|
||||
)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
private fun getUriFromFile(filePath: String): Uri {
|
||||
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
Uri.fromFile(File(filePath))
|
||||
} else {
|
||||
FileProvider.getUriForFile(
|
||||
context,
|
||||
context.packageName + ".provider",
|
||||
File(filePath)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package com.cyb3rko.techniklogger.update
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.androidnetworking.AndroidNetworking
|
||||
import com.androidnetworking.error.ANError
|
||||
import com.androidnetworking.interfaces.StringRequestListener
|
||||
import com.cyb3rko.techniklogger.BuildConfig
|
||||
import com.cyb3rko.techniklogger.MainActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import es.dmoral.toasty.Toasty
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
internal object Updater {
|
||||
internal fun updateCheck(activity: MainActivity) {
|
||||
AndroidNetworking.initialize(activity)
|
||||
AndroidNetworking.get("https://git.aldiserver.de/api/v1/repos/niko/technik-logger-app/contents/app/build.gradle")
|
||||
.addHeaders("Authorization", "token d70a26aa455b25e60885ba5ff31cce231d454f82")
|
||||
.doNotCacheResponse()
|
||||
.build()
|
||||
.getAsString(object : StringRequestListener {
|
||||
override fun onResponse(response: String?) {
|
||||
try {
|
||||
var parts = response!!.split("content\":\"")
|
||||
var parts2 = parts[1].split("\",\"target")
|
||||
val content = String(Base64.decode(parts2[0], Base64.DEFAULT), StandardCharsets.UTF_8)
|
||||
|
||||
parts = content.split("versionCode ")
|
||||
parts2 = parts[1].split("\n")
|
||||
val neuesterVersionCode = parts2[0].toInt()
|
||||
parts = parts2[1].split("\"")
|
||||
parts2 = parts[1].split("\"")
|
||||
val newestVersion = parts2[0]
|
||||
|
||||
if (BuildConfig.VERSION_CODE != neuesterVersionCode) {
|
||||
Log.d("Technik-Logger Updater", "Update verfügbar: $newestVersion")
|
||||
showDownloadDialog(activity, newestVersion)
|
||||
|
||||
ActivityCompat.requestPermissions(
|
||||
activity, arrayOf(Manifest.permission.INTERNET, Manifest.permission.WRITE_EXTERNAL_STORAGE), 1
|
||||
)
|
||||
} else {
|
||||
Log.d(activity.toString(), "App auf dem neuesten Stand")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Toasty.error(activity, "Update-Check fehlgeschlagen", Toasty.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(anError: ANError?) {
|
||||
Log.d(activity.toString(), "Update-Abfrage fehlgeschlagen: ${anError!!.errorBody.trimIndent()}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun showDownloadDialog(context: Context, newestVersion: String) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle("Neues Update verfügbar")
|
||||
.setMessage("Das Update '$newestVersion' steht zum Download bereit!\n\nAktuell installierte Version: '${BuildConfig.VERSION_NAME}'")
|
||||
.setPositiveButton("Herunterladen") { _, _ ->
|
||||
downloadApk(context, newestVersion)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun downloadApk(context: Context, newestVersion: String) {
|
||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
val link = "https://cdn.cyb3rko.de/Apps/Technik-Logger/Technik-Logger%20v$newestVersion.apk"
|
||||
DownloadApk(context).startDownloadingApk(link, "Technik-Logger $newestVersion")
|
||||
} else {
|
||||
Toasty.error(context, "Fehlende Berechtigung, erteile diese beim nächsten App-Start", Toasty.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
/build
|
||||
@ -1,43 +0,0 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'kotlin-android'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 31
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.20"
|
||||
implementation 'androidx.core:core-ktx:1.6.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.cyb3rko.installer">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||
</manifest>
|
||||
@ -1,161 +0,0 @@
|
||||
package com.cyb3rko.installer;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
import androidx.core.content.FileProvider;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class DownloadApk extends Activity {
|
||||
private static Context context;
|
||||
private static String downloadUrl;
|
||||
private static String fileName;
|
||||
private static final String TAG = "DownloadApk";
|
||||
|
||||
public DownloadApk(Context context){
|
||||
DownloadApk.context = context;
|
||||
}
|
||||
|
||||
public void startDownloadingApk(String url){
|
||||
downloadUrl = url;
|
||||
fileName = url.split("Technik-Logger/")[1].replace("%20", " ");
|
||||
if (downloadUrl != null){
|
||||
new DownloadNewVersion(context).execute();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DownloadNewVersion extends AsyncTask<String, Integer, Boolean> {
|
||||
private ProgressDialog bar;
|
||||
private final Context context;
|
||||
|
||||
DownloadNewVersion(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
if (bar == null){
|
||||
bar = new ProgressDialog(context);
|
||||
bar.setCancelable(false);
|
||||
bar.setMessage("Lädt herunter...");
|
||||
bar.setIndeterminate(true);
|
||||
bar.setCanceledOnTouchOutside(false);
|
||||
bar.show();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onProgressUpdate(Integer... progress) {
|
||||
super.onProgressUpdate(progress);
|
||||
bar.setIndeterminate(false);
|
||||
bar.setMax(100);
|
||||
bar.setProgress(progress[0]);
|
||||
String msg = "";
|
||||
if (progress[0] > 99) {
|
||||
msg = "Beenden... ";
|
||||
} else {
|
||||
msg = "Herunterladen... " + progress[0] + "%";
|
||||
}
|
||||
bar.setMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
if (bar.isShowing() && bar != null) {
|
||||
bar.dismiss();
|
||||
bar = null;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
Toast.makeText(context,"Download erfolgreich", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(context,"Download fehlgeschlagen", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... arg0) {
|
||||
boolean flag = false;
|
||||
try {
|
||||
String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/";
|
||||
File outputFile = new File(destination + fileName);
|
||||
if (outputFile.exists()) {
|
||||
try {
|
||||
openNewVersion(outputFile.getPath());
|
||||
return true;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
outputFile.createNewFile();
|
||||
|
||||
File directory = new File(destination);
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
|
||||
URL url = new URL(downloadUrl);
|
||||
HttpURLConnection c = (HttpURLConnection) url.openConnection();
|
||||
c.setRequestMethod("GET");
|
||||
c.connect();
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(outputFile);
|
||||
InputStream is = c.getInputStream();
|
||||
|
||||
// size of apk
|
||||
int total_size = c.getContentLength();
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int len1;
|
||||
int per;
|
||||
int downloaded = 0;
|
||||
while ((len1 = is.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len1);
|
||||
downloaded += len1;
|
||||
per = downloaded * 100 / total_size;
|
||||
publishProgress(per);
|
||||
}
|
||||
fos.close();
|
||||
is.close();
|
||||
openNewVersion(outputFile.getPath());
|
||||
flag = true;
|
||||
} catch (MalformedURLException e) {
|
||||
Log.e(TAG, "Update-Fehler: " + e.getMessage());
|
||||
flag = false;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Update-Fehler: " + e.getMessage());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
private static void openNewVersion(String filePath) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(getUriFromFile(filePath), "application/vnd.android.package-archive");
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private static Uri getUriFromFile(String filePath) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
return Uri.fromFile(new File(filePath));
|
||||
} else {
|
||||
return FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider",
|
||||
new File(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,2 @@
|
||||
include ':installer'
|
||||
include ':app'
|
||||
rootProject.name = "Technik-Logger"
|
||||
rootProject.name = "Technik-Logger"
|
||||
include ':app'
|
||||
Loading…
Reference in New Issue