diff --git a/app/build.gradle b/app/build.gradle
index aba0cb1..c7fb330 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -74,5 +74,4 @@ dependencies {
implementation 'com.google.android.material:material:1.6.1'
implementation 'com.google.firebase:firebase-crashlytics-ktx' // BOM versioning
implementation 'com.itextpdf:itextpdf:5.5.13.2'
- implementation project(':installer')
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f61898c..853ab09 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
+
- 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()
- }
-}
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/update/DownloadApk.kt b/app/src/main/java/com/cyb3rko/techniklogger/update/DownloadApk.kt
new file mode 100644
index 0000000..3f4393e
--- /dev/null
+++ b/app/src/main/java/com/cyb3rko/techniklogger/update/DownloadApk.kt
@@ -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() {
+ 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)
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/update/Updater.kt b/app/src/main/java/com/cyb3rko/techniklogger/update/Updater.kt
new file mode 100644
index 0000000..cd80eb8
--- /dev/null
+++ b/app/src/main/java/com/cyb3rko/techniklogger/update/Updater.kt
@@ -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()
+ }
+ }
+}
diff --git a/installer/.gitignore b/installer/.gitignore
deleted file mode 100644
index 42afabf..0000000
--- a/installer/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/installer/build.gradle b/installer/build.gradle
deleted file mode 100644
index 67abf1b..0000000
--- a/installer/build.gradle
+++ /dev/null
@@ -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'
-}
\ No newline at end of file
diff --git a/installer/consumer-rules.pro b/installer/consumer-rules.pro
deleted file mode 100644
index e69de29..0000000
diff --git a/installer/proguard-rules.pro b/installer/proguard-rules.pro
deleted file mode 100644
index 481bb43..0000000
--- a/installer/proguard-rules.pro
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/installer/src/main/AndroidManifest.xml b/installer/src/main/AndroidManifest.xml
deleted file mode 100644
index d68c97f..0000000
--- a/installer/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/installer/src/main/java/com/cyb3rko/installer/DownloadApk.java b/installer/src/main/java/com/cyb3rko/installer/DownloadApk.java
deleted file mode 100644
index b4b3d5f..0000000
--- a/installer/src/main/java/com/cyb3rko/installer/DownloadApk.java
+++ /dev/null
@@ -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 {
- 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));
- }
- }
-}
diff --git a/settings.gradle b/settings.gradle
index e566ff0..7edb7b7 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,2 @@
-include ':installer'
-include ':app'
-rootProject.name = "Technik-Logger"
\ No newline at end of file
+rootProject.name = "Technik-Logger"
+include ':app'
\ No newline at end of file