diff --git a/android/.idea/jarRepositories.xml b/android/.idea/jarRepositories.xml
new file mode 100644
index 0000000..ddeabf5
--- /dev/null
+++ b/android/.idea/jarRepositories.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 5de6c95..a6da5d1 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 28
+ compileSdkVersion 30
def versionPropsFile = file('version.properties')
def vNumber
@@ -16,7 +16,7 @@ android {
defaultConfig {
applicationId "com.blackforestbytes.simplecloudnotifier"
minSdkVersion 21
- targetSdkVersion 28
+ targetSdkVersion 30
versionCode vNumber
versionName vName
}
@@ -35,78 +35,82 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.cardview:cardview:1.0.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'androidx.recyclerview:recyclerview:1.0.0'
- implementation 'androidx.recyclerview:recyclerview:1.0.0'
- implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ implementation 'androidx.recyclerview:recyclerview:1.1.0'
+ implementation 'androidx.recyclerview:recyclerview:1.1.0'
+ implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
- implementation 'com.google.android.material:material:1.0.0'
- implementation 'com.google.firebase:firebase-core:16.0.6'
- implementation 'com.google.firebase:firebase-messaging:17.3.4'
- implementation 'com.google.android.gms:play-services-ads:17.1.2'
- implementation 'com.android.billingclient:billing:1.2'
+ implementation 'com.google.android.material:material:1.2.1'
+ implementation 'com.google.firebase:firebase-core:18.0.0'
+ implementation 'com.google.firebase:firebase-messaging:21.0.0'
+ implementation 'com.google.android.gms:play-services-ads:19.5.0'
+ implementation 'com.android.billingclient:billing:3.0.1'
- implementation 'com.squareup.okhttp3:okhttp:3.10.0'
+ implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.github.kenglxn.QRGen:android:2.5.0'
implementation "com.github.DeweyReed:UltimateMusicPicker:2.0.0"
implementation 'com.github.duanhong169:colorpicker:1.1.5'
- implementation 'net.danlew:android.joda:2.9.9.2'
+ implementation 'net.danlew:android.joda:2.10.7.1'
}
apply plugin: 'com.google.gms.google-services'
-task updateVersion << {
- def lastTag = ['git', 'describe', "--abbrev=0", "--tags"].execute().text.trim()
+tasks.register("updateVersion") {
+ group = 'Custom'
- def versionPropsFile = file('version.properties')
- if (!versionPropsFile.canRead()) throw new FileNotFoundException("Could not read version.properties!")
- Properties versionProps = new Properties()
- new FileInputStream(versionPropsFile).withCloseable { fis -> versionProps.load(fis) }
+ doLast {
+ def lastTag = ['git', 'describe', "--abbrev=0", "--tags"].execute().text.trim()
- def matcher = lastTag =~ /^v([0-9]+)\.([0-9]+)\.([0-9]+)$/
+ def versionPropsFile = file('version.properties')
+ if (!versionPropsFile.canRead()) throw new FileNotFoundException("Could not read version.properties!")
+ Properties versionProps = new Properties()
+ new FileInputStream(versionPropsFile).withCloseable { fis -> versionProps.load(fis) }
- if (!matcher.matches()) throw new Exception("Last Tag ('" + lastTag + "') has invalid format :(")
+ def matcher = lastTag =~ /^v([0-9]+)\.([0-9]+)\.([0-9]+)$/
- def vName = (matcher[0][1] as Integer) + "." + (matcher[0][2] as Integer) + "." + (matcher[0][3] as Integer)
- def vCode = versionProps['VERSION_CODE'] as Integer
+ if (!matcher.matches()) throw new Exception("Last Tag ('" + lastTag + "') has invalid format :(")
- if (new File(".do_publish_beta_release").exists()) new File(".do_publish_beta_release").delete()
- if (new File(".do_publish_prod_release").exists()) new File(".do_publish_prod_release").delete()
+ def vName = (matcher[0][1] as Integer) + "." + (matcher[0][2] as Integer) + "." + (matcher[0][3] as Integer)
+ def vCode = versionProps['VERSION_CODE'] as Integer
- if (vName == versionProps['VERSION_NAME'].toString()) {
- println "This version was already built - skip deployment"
- } else if (vName.endsWith(".0")) {
- println ""
- println "====================================================================="
- println "====================================================================="
- println "(!) This is a new PRODUCTION release - create deployment trigger file"
- println "====================================================================="
- println "====================================================================="
- println ""
+ if (new File(".do_publish_beta_release").exists()) new File(".do_publish_beta_release").delete()
+ if (new File(".do_publish_prod_release").exists()) new File(".do_publish_prod_release").delete()
- vCode++
- new File(".do_publish_prod_release").createNewFile()
+ if (vName == versionProps['VERSION_NAME'].toString()) {
+ println "This version was already built - skip deployment"
+ } else if (vName.endsWith(".0")) {
+ println ""
+ println "====================================================================="
+ println "====================================================================="
+ println "(!) This is a new PRODUCTION release - create deployment trigger file"
+ println "====================================================================="
+ println "====================================================================="
+ println ""
- versionProps['VERSION_NAME'] = vName.toString()
- versionProps['VERSION_CODE'] = vCode.toString()
+ vCode++
+ new File(".do_publish_prod_release").createNewFile()
- versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
- } else {
- println ""
- println "==============================================================="
- println "(!) This is a new beta release - create deployment trigger file"
- println "==============================================================="
- println ""
+ versionProps['VERSION_NAME'] = vName.toString()
+ versionProps['VERSION_CODE'] = vCode.toString()
- vCode++
- new File(".do_publish_beta_release").createNewFile()
+ versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
+ } else {
+ println ""
+ println "==============================================================="
+ println "(!) This is a new beta release - create deployment trigger file"
+ println "==============================================================="
+ println ""
- versionProps['VERSION_NAME'] = vName.toString()
- versionProps['VERSION_CODE'] = vCode.toString()
+ vCode++
+ new File(".do_publish_beta_release").createNewFile()
- versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
+ versionProps['VERSION_NAME'] = vName.toString()
+ versionProps['VERSION_CODE'] = vCode.toString()
+
+ versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
+ }
}
}
diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java
index d2e18be..558e384 100644
--- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java
+++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/model/ServerCommunication.java
@@ -68,6 +68,7 @@ public class ServerCommunication
if (!json_bool(json, "success"))
{
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("register", call, response, r);
return;
}
@@ -134,6 +135,7 @@ public class ServerCommunication
if (!json_bool(json, "success"))
{
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("update<1>", call, response, r);
return;
}
@@ -200,6 +202,7 @@ public class ServerCommunication
if (!json_bool(json, "success")) {
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("update<2>", call, response, r);
return;
}
@@ -269,6 +272,7 @@ public class ServerCommunication
if (!json_bool(json, "success"))
{
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("info", call, response, r);
int errid = json.optInt("errid", 0);
@@ -356,6 +360,7 @@ public class ServerCommunication
if (!json_bool(json, "success"))
{
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("requery", call, response, r);
return;
}
@@ -420,8 +425,7 @@ public class ServerCommunication
String r = Str.Empty;
try (ResponseBody responseBody = response.body())
{
- if (!response.isSuccessful())
- throw new IOException("Unexpected code " + response);
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
if (responseBody == null) throw new IOException("No response");
r = responseBody.string();
@@ -431,6 +435,7 @@ public class ServerCommunication
if (!json_bool(json, "success")) {
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("upgrade", call, response, r);
return;
}
@@ -492,7 +497,11 @@ public class ServerCommunication
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
- if (!json_bool(json, "success")) SCNApp.showToast(json_str(json, "message"), 4000);
+ if (!json_bool(json, "success"))
+ {
+ SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("ack", call, response, r);
+ }
handleSuccess("ack", call, response, r);
}
@@ -542,6 +551,7 @@ public class ServerCommunication
if (!json_bool(json, "success"))
{
SCNApp.showToast(json_str(json, "message"), 4000);
+ handleNonSuccess("expand", call, response, r);
return;
}
@@ -621,6 +631,28 @@ public class ServerCommunication
}
}
+ private static void handleNonSuccess(String source, Call call, Response resp, String respBody)
+ {
+ Log.d("SC:"+source, respBody);
+
+ try
+ {
+ Instant i = Instant.now();
+ String s = source;
+ String u = call.request().url().toString();
+ int rc = resp.code();
+ String r = respBody;
+ LogLevel l = LogLevel.WARN;
+
+ SingleQuery q = new SingleQuery(l, i, s, u, r, rc, "NON-SUCCESS");
+ QueryLog.inst().add(q);
+ }
+ catch (Exception e2)
+ {
+ Log.e("SC:HandleSuccess", e2.toString());
+ }
+ }
+
private static void handleError(String source, Call call, Response resp, String respBody, boolean isio, Exception e)
{
Log.e("SC:"+source, e.toString());
diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/IABService.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/IABService.java
index 206b787..54333d9 100644
--- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/IABService.java
+++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/IABService.java
@@ -9,8 +9,12 @@ import android.widget.Toast;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
+import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
+import com.android.billingclient.api.SkuDetails;
+import com.android.billingclient.api.SkuDetailsParams;
+import com.android.billingclient.api.SkuDetailsResponseListener;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple2;
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple3;
@@ -20,11 +24,15 @@ import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import static androidx.constraintlayout.widget.Constraints.TAG;
@@ -58,7 +66,7 @@ public class IABService implements PurchasesUpdatedListener
private final List purchases = new ArrayList<>();
private boolean _isInitialized = false;
- private Map _localCache= new HashMap<>();
+ private final Map _localCache= new HashMap<>();
public IABService(Context c)
{
@@ -72,6 +80,7 @@ public class IABService implements PurchasesUpdatedListener
.build();
startServiceConnection(this::queryPurchases, false);
+ startServiceConnection(this::querySkuDetails, false);
}
public void reloadPrefs()
@@ -126,9 +135,9 @@ public class IABService implements PurchasesUpdatedListener
Purchase.PurchasesResult purchasesResult = client.queryPurchases(BillingClient.SkuType.INAPP);
Log.i(TAG, "Querying purchases elapsed time: " + (System.currentTimeMillis() - time) + "ms");
- if (purchasesResult.getResponseCode() == BillingClient.BillingResponse.OK)
+ if (purchasesResult.getResponseCode() == BillingClient.BillingResponseCode.OK)
{
- for (Purchase p : purchasesResult.getPurchasesList())
+ for (Purchase p : Objects.requireNonNull(purchasesResult.getPurchasesList()))
{
handlePurchase(p, false);
}
@@ -150,17 +159,35 @@ public class IABService implements PurchasesUpdatedListener
executeServiceRequest(queryToExecute, false);
}
+ public void querySkuDetails() {
+ }
+
public void purchase(Activity a, String id)
{
- executeServiceRequest(() ->
- {
- BillingFlowParams flowParams = BillingFlowParams
- .newBuilder()
- .setSku(id)
- .setType(BillingClient.SkuType.INAPP) // SkuType.SUB for subscription
- .build();
- client.launchBillingFlow(a, flowParams);
- }, true);
+ Func0to0 queryRequest = () -> {
+ // Query the purchase async
+ SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
+ params.setSkusList(Collections.singletonList(id)).setType(BillingClient.SkuType.INAPP);
+ client.querySkuDetailsAsync(params.build(), (billingResult, skuDetailsList) ->
+ {
+ if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK || skuDetailsList == null || skuDetailsList.size() != 1)
+ {
+ SCNApp.showToast("Could not find product", Toast.LENGTH_SHORT);
+ return;
+ }
+
+ executeServiceRequest(() ->
+ {
+ BillingFlowParams flowParams = BillingFlowParams
+ .newBuilder()
+ .setSkuDetails(skuDetailsList.get(0))
+ .build();
+ client.launchBillingFlow(a, flowParams);
+ }, true);
+ });
+ };
+ executeServiceRequest(queryRequest, false);
+
}
private void executeServiceRequest(Func0to0 runnable, final boolean userRequest)
@@ -186,16 +213,16 @@ public class IABService implements PurchasesUpdatedListener
}
@Override
- public void onPurchasesUpdated(int responseCode, @Nullable List purchases)
+ public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List purchases)
{
- if (responseCode == BillingClient.BillingResponse.OK && purchases != null)
+ if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null)
{
for (Purchase purchase : purchases)
{
handlePurchase(purchase, true);
}
}
- else if (responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED && purchases != null)
+ else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED && purchases != null)
{
for (Purchase purchase : purchases)
{
@@ -228,9 +255,9 @@ public class IABService implements PurchasesUpdatedListener
client.startConnection(new BillingClientStateListener()
{
@Override
- public void onBillingSetupFinished(@BillingClient.BillingResponse int billingResponseCode)
+ public void onBillingSetupFinished(@NonNull BillingResult billingResult)
{
- if (billingResponseCode == BillingClient.BillingResponse.OK)
+ if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK)
{
isServiceConnected = true;
if (executeOnSuccess != null) executeOnSuccess.invoke();
diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java
index 43dbb75..db9535a 100644
--- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java
+++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java
@@ -3,17 +3,12 @@ package com.blackforestbytes.simplecloudnotifier.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.text.Editable;
import android.util.Log;
import android.view.LayoutInflater;
@@ -30,11 +25,12 @@ import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.billingclient.api.Purchase;
-import com.blackforestbytes.simplecloudnotifier.BuildConfig;
+import androidx.annotation.NonNull;
+import androidx.core.content.FileProvider;
+import androidx.fragment.app.Fragment;
+
import com.blackforestbytes.simplecloudnotifier.R;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
-import com.blackforestbytes.simplecloudnotifier.lib.android.ThreadUtils;
import com.blackforestbytes.simplecloudnotifier.lib.lambda.FI;
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
@@ -47,12 +43,8 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
-import java.util.Date;
import java.util.Map;
-import androidx.annotation.NonNull;
-import androidx.core.content.FileProvider;
-import androidx.fragment.app.Fragment;
import top.defaults.colorpicker.ColorPickerPopup;
import xyz.aprildown.ultimatemusicpicker.MusicPickerListener;
import xyz.aprildown.ultimatemusicpicker.UltimateMusicPicker;
diff --git a/android/build.gradle b/android/build.gradle
index d21b66f..653a5fa 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -7,8 +7,8 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.2.1'
- classpath 'com.google.gms:google-services:4.2.0'
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath 'com.google.gms:google-services:4.3.4'
}
}
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 7465871..5c71486 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Sep 26 22:10:14 CEST 2018
+#Tue Nov 03 14:10:19 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip