Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
ce641bf7d2
|
|||
f1c7314dca
|
|||
019408dc6d
|
|||
![]() |
cdba3540c2 | ||
885d997ff3
|
|||
5118ab3cbf
|
|||
![]() |
2812377f5c | ||
93b40a9c7f
|
|||
b95ddcc811
|
|||
90ba3c1134
|
|||
05174958b2
|
|||
![]() |
24be9b2013 | ||
29ce4b727c
|
|||
![]() |
f178019ffe | ||
0a1b948042
|
|||
![]() |
74cbfb235e |
85
android/.idea/assetWizardSettings.xml
generated
85
android/.idea/assetWizardSettings.xml
generated
@@ -1,85 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="WizardSettings">
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="imageWizard">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="imageAssetPanel">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="launcherLegacy">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="assetType" value="IMAGE" />
|
|
||||||
<entry key="cropped" value="true" />
|
|
||||||
<entry key="iconShape" value="NONE" />
|
|
||||||
<entry key="imageAsset" value="F:\Eigene Dateien\Dropbox\Programming\Java\AndroidStudioProjects\SimpleCloudNotifier\data\icon_512_nobox.png" />
|
|
||||||
<entry key="outputName" value="ic_notification_full" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="notification">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="assetType" value="IMAGE" />
|
|
||||||
<entry key="imageAsset" value="F:\Eigene Dateien\Dropbox\Programming\Java\AndroidStudioProjects\SimpleCloudNotifier\data\icon_512_transparent.png" />
|
|
||||||
<entry key="outputName" value="ic_notification_white" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="outputIconType" value="LAUNCHER_LEGACY" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="vectorWizard">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="vectorAssetStep">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="assetSourceType" value="FILE" />
|
|
||||||
<entry key="outputName" value="ic_share" />
|
|
||||||
<entry key="sourceFile" value="C:\Users\Mike\Downloads\baseline-share-24px.svg" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
134
android/.idea/codeStyles/Project.xml
generated
134
android/.idea/codeStyles/Project.xml
generated
@@ -1,29 +1,113 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<Objective-C-extensions>
|
<codeStyleSettings language="XML">
|
||||||
<file>
|
<arrangement>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
<rules>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
<section>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
<rule>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
<match>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
<AND>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
<NAME>xmlns:android</NAME>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
<XML_ATTRIBUTE />
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
</AND>
|
||||||
</file>
|
</match>
|
||||||
<class>
|
</rule>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
</section>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
<section>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
<rule>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
<match>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
<AND>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
<NAME>xmlns:.*</NAME>
|
||||||
</class>
|
<XML_ATTRIBUTE />
|
||||||
<extensions>
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
</AND>
|
||||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
</match>
|
||||||
</extensions>
|
<order>BY_NAME</order>
|
||||||
</Objective-C-extensions>
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>style</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
</rules>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
40
android/.idea/jarRepositories.xml
generated
Normal file
40
android/.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RemoteRepositoriesConfiguration">
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Maven Central repository" />
|
||||||
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jboss.community" />
|
||||||
|
<option name="name" value="JBoss Community repository" />
|
||||||
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven2" />
|
||||||
|
<option name="name" value="maven2" />
|
||||||
|
<option name="url" value="https://dl.bintray.com/gericop/maven" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven3" />
|
||||||
|
<option name="name" value="maven3" />
|
||||||
|
<option name="url" value="https://maven.google.com" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="BintrayJCenter" />
|
||||||
|
<option name="name" value="BintrayJCenter" />
|
||||||
|
<option name="url" value="https://jcenter.bintray.com/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven" />
|
||||||
|
<option name="name" value="maven" />
|
||||||
|
<option name="url" value="https://jitpack.io" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="Google" />
|
||||||
|
<option name="name" value="Google" />
|
||||||
|
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||||
|
</remote-repository>
|
||||||
|
</component>
|
||||||
|
</project>
|
@@ -1,7 +1,7 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 30
|
||||||
|
|
||||||
def versionPropsFile = file('version.properties')
|
def versionPropsFile = file('version.properties')
|
||||||
def vNumber
|
def vNumber
|
||||||
@@ -16,7 +16,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.blackforestbytes.simplecloudnotifier"
|
applicationId "com.blackforestbytes.simplecloudnotifier"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 30
|
||||||
versionCode vNumber
|
versionCode vNumber
|
||||||
versionName vName
|
versionName vName
|
||||||
}
|
}
|
||||||
@@ -35,30 +35,33 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
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.cardview:cardview:1.0.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
implementation 'com.google.firebase:firebase-core:16.0.6'
|
implementation 'com.google.firebase:firebase-core:18.0.0'
|
||||||
implementation 'com.google.firebase:firebase-messaging:17.3.4'
|
implementation 'com.google.firebase:firebase-messaging:21.0.0'
|
||||||
implementation 'com.google.android.gms:play-services-ads:17.1.2'
|
implementation 'com.google.android.gms:play-services-ads:19.5.0'
|
||||||
implementation 'com.android.billingclient:billing:1.2'
|
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.kenglxn.QRGen:android:2.5.0'
|
||||||
implementation "com.github.DeweyReed:UltimateMusicPicker:2.0.0"
|
implementation "com.github.DeweyReed:UltimateMusicPicker:2.0.0"
|
||||||
implementation 'com.github.duanhong169:colorpicker:1.1.5'
|
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'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|
||||||
task updateVersion << {
|
tasks.register("updateVersion") {
|
||||||
|
group = 'Custom'
|
||||||
|
|
||||||
|
doLast {
|
||||||
def lastTag = ['git', 'describe', "--abbrev=0", "--tags"].execute().text.trim()
|
def lastTag = ['git', 'describe', "--abbrev=0", "--tags"].execute().text.trim()
|
||||||
|
|
||||||
def versionPropsFile = file('version.properties')
|
def versionPropsFile = file('version.properties')
|
||||||
@@ -110,3 +113,4 @@ task updateVersion << {
|
|||||||
versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
|
versionPropsFile.newWriter().withCloseable { w -> versionProps.store(w, null) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@@ -24,6 +24,15 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="com.blackforestbytes.simplecloudnotifier.fileprovider"
|
||||||
|
android:grantUriPermissions="true"
|
||||||
|
android:exported="false">
|
||||||
|
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" />
|
||||||
|
</provider>
|
||||||
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||||
android:resource="@drawable/icon" />
|
android:resource="@drawable/icon" />
|
||||||
@@ -53,7 +62,7 @@
|
|||||||
android:name=".view.debug.QueryLogActivity"
|
android:name=".view.debug.QueryLogActivity"
|
||||||
android:label="@string/title_activity_query_log"
|
android:label="@string/title_activity_query_log"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".view.debug.SingleQueryLogActivity"></activity>
|
<activity android:name=".view.debug.SingleQueryLogActivity" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@@ -35,6 +35,11 @@ public class CMessageList
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CMessageList()
|
private CMessageList()
|
||||||
|
{
|
||||||
|
reloadPrefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadPrefs()
|
||||||
{
|
{
|
||||||
synchronized (msg_lock)
|
synchronized (msg_lock)
|
||||||
{
|
{
|
||||||
|
@@ -15,9 +15,9 @@ public class QueryLog
|
|||||||
private final static int MAX_HISTORY_SIZE = 192;
|
private final static int MAX_HISTORY_SIZE = 192;
|
||||||
|
|
||||||
private static QueryLog _instance;
|
private static QueryLog _instance;
|
||||||
public static QueryLog instance() { if (_instance == null) synchronized (QueryLog.class) { if (_instance == null) _instance = new QueryLog(); } return _instance; }
|
public static QueryLog inst() { if (_instance == null) synchronized (QueryLog.class) { if (_instance == null) _instance = new QueryLog(); } return _instance; }
|
||||||
|
|
||||||
private QueryLog(){ load(); }
|
private QueryLog(){ reloadPrefs(); }
|
||||||
|
|
||||||
private final List<SingleQuery> history = new ArrayList<>();
|
private final List<SingleQuery> history = new ArrayList<>();
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class QueryLog
|
|||||||
e.apply();
|
e.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void load()
|
public synchronized void reloadPrefs()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@@ -62,6 +62,11 @@ public class SCNSettings
|
|||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
public SCNSettings()
|
public SCNSettings()
|
||||||
|
{
|
||||||
|
reloadPrefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadPrefs()
|
||||||
{
|
{
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE);
|
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE);
|
||||||
|
|
||||||
@@ -122,6 +127,9 @@ public class SCNSettings
|
|||||||
e.putString( "user_key", user_key);
|
e.putString( "user_key", user_key);
|
||||||
e.putString( "fcm_token_local", fcm_token_local);
|
e.putString( "fcm_token_local", fcm_token_local);
|
||||||
e.putString( "fcm_token_server", fcm_token_server);
|
e.putString( "fcm_token_server", fcm_token_server);
|
||||||
|
e.putBoolean("promode_local", promode_local);
|
||||||
|
e.putBoolean("promode_server", promode_server);
|
||||||
|
e.putString( "promode_token", promode_token);
|
||||||
|
|
||||||
e.putBoolean("app_enabled", Enabled);
|
e.putBoolean("app_enabled", Enabled);
|
||||||
e.putInt( "local_cache_size", LocalCacheSize);
|
e.putInt( "local_cache_size", LocalCacheSize);
|
||||||
@@ -244,15 +252,16 @@ public class SCNSettings
|
|||||||
public void updateProState(View loader)
|
public void updateProState(View loader)
|
||||||
{
|
{
|
||||||
Tuple3<Boolean, Boolean, String> state = IABService.inst().getPurchaseCachedExtended(IABService.IAB_PRO_MODE);
|
Tuple3<Boolean, Boolean, String> state = IABService.inst().getPurchaseCachedExtended(IABService.IAB_PRO_MODE);
|
||||||
if (!state.Item2) return; // not nitialized
|
if (!state.Item2) return; // not initialized
|
||||||
|
|
||||||
boolean promode_real = state.Item1;
|
boolean promode_real = state.Item1;
|
||||||
|
|
||||||
if (promode_real != promode_local || promode_real != promode_server)
|
if (promode_real != promode_local || promode_real != promode_server)
|
||||||
{
|
{
|
||||||
promode_local = promode_real;
|
promode_local = promode_real;
|
||||||
|
|
||||||
promode_token = promode_real ? state.Item3 : "";
|
promode_token = promode_real ? state.Item3 : "";
|
||||||
|
save();
|
||||||
|
|
||||||
updateProStateOnServer(loader);
|
updateProStateOnServer(loader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,6 +68,7 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("register", call, response, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ public class ServerCommunication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(BASE_URL + "updateFCMToken.php?user_id="+id+"&user_key="+key+"&fcm_token="+token)
|
.url(BASE_URL + "update.php?user_id="+id+"&user_key="+key+"&fcm_token="+token)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback()
|
client.newCall(request).enqueue(new Callback()
|
||||||
@@ -134,6 +135,7 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("update<1>", call, response, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +174,7 @@ public class ServerCommunication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(BASE_URL + "updateFCMToken.php?user_id=" + id + "&user_key=" + key)
|
.url(BASE_URL + "update.php?user_id=" + id + "&user_key=" + key)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback() {
|
client.newCall(request).enqueue(new Callback() {
|
||||||
@@ -200,6 +202,7 @@ public class ServerCommunication
|
|||||||
|
|
||||||
if (!json_bool(json, "success")) {
|
if (!json_bool(json, "success")) {
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("update<2>", call, response, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +272,7 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("info", call, response, r);
|
||||||
|
|
||||||
int errid = json.optInt("errid", 0);
|
int errid = json.optInt("errid", 0);
|
||||||
|
|
||||||
@@ -356,6 +360,7 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("requery", call, response, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,8 +425,7 @@ public class ServerCommunication
|
|||||||
String r = Str.Empty;
|
String r = Str.Empty;
|
||||||
try (ResponseBody responseBody = response.body())
|
try (ResponseBody responseBody = response.body())
|
||||||
{
|
{
|
||||||
if (!response.isSuccessful())
|
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
if (responseBody == null) throw new IOException("No response");
|
if (responseBody == null) throw new IOException("No response");
|
||||||
|
|
||||||
r = responseBody.string();
|
r = responseBody.string();
|
||||||
@@ -431,6 +435,7 @@ public class ServerCommunication
|
|||||||
|
|
||||||
if (!json_bool(json, "success")) {
|
if (!json_bool(json, "success")) {
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("upgrade", call, response, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +497,11 @@ public class ServerCommunication
|
|||||||
|
|
||||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
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);
|
handleSuccess("ack", call, response, r);
|
||||||
}
|
}
|
||||||
@@ -542,6 +551,7 @@ public class ServerCommunication
|
|||||||
if (!json_bool(json, "success"))
|
if (!json_bool(json, "success"))
|
||||||
{
|
{
|
||||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||||
|
handleNonSuccess("expand", call, response, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +623,29 @@ public class ServerCommunication
|
|||||||
LogLevel l = LogLevel.INFO;
|
LogLevel l = LogLevel.INFO;
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, "SUCCESS");
|
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, "SUCCESS");
|
||||||
QueryLog.instance().add(q);
|
QueryLog.inst().add(q);
|
||||||
|
}
|
||||||
|
catch (Exception e2)
|
||||||
|
{
|
||||||
|
Log.e("SC:HandleSuccess", e2.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
catch (Exception e2)
|
||||||
{
|
{
|
||||||
@@ -644,7 +676,7 @@ public class ServerCommunication
|
|||||||
LogLevel l = isio?LogLevel.WARN:LogLevel.ERROR;
|
LogLevel l = isio?LogLevel.WARN:LogLevel.ERROR;
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, e.toString());
|
SingleQuery q = new SingleQuery(l, i, s, u, r, rc, e.toString());
|
||||||
QueryLog.instance().add(q);
|
QueryLog.inst().add(q);
|
||||||
}
|
}
|
||||||
catch (Exception e2)
|
catch (Exception e2)
|
||||||
{
|
{
|
||||||
|
@@ -4,8 +4,6 @@ import android.util.Log;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple4;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple5;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
||||||
@@ -15,7 +13,6 @@ import com.blackforestbytes.simplecloudnotifier.model.QueryLog;
|
|||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
|
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SingleQuery;
|
import com.blackforestbytes.simplecloudnotifier.model.SingleQuery;
|
||||||
import com.google.android.gms.common.util.JsonUtils;
|
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
|
|
||||||
@@ -52,7 +49,7 @@ public class FBMService extends FirebaseMessagingService
|
|||||||
|
|
||||||
|
|
||||||
SingleQuery q = new SingleQuery(LogLevel.INFO, Instant.now(), "FBM<recieve>", Str.Empty, new JSONObject(remoteMessage.getData()).toString(), 0, "SUCCESS");
|
SingleQuery q = new SingleQuery(LogLevel.INFO, Instant.now(), "FBM<recieve>", Str.Empty, new JSONObject(remoteMessage.getData()).toString(), 0, "SUCCESS");
|
||||||
QueryLog.instance().add(q);
|
QueryLog.inst().add(q);
|
||||||
|
|
||||||
if (trimmed)
|
if (trimmed)
|
||||||
{
|
{
|
||||||
|
@@ -9,8 +9,12 @@ import android.widget.Toast;
|
|||||||
import com.android.billingclient.api.BillingClient;
|
import com.android.billingclient.api.BillingClient;
|
||||||
import com.android.billingclient.api.BillingClientStateListener;
|
import com.android.billingclient.api.BillingClientStateListener;
|
||||||
import com.android.billingclient.api.BillingFlowParams;
|
import com.android.billingclient.api.BillingFlowParams;
|
||||||
|
import com.android.billingclient.api.BillingResult;
|
||||||
import com.android.billingclient.api.Purchase;
|
import com.android.billingclient.api.Purchase;
|
||||||
import com.android.billingclient.api.PurchasesUpdatedListener;
|
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.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple2;
|
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple2;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple3;
|
import com.blackforestbytes.simplecloudnotifier.lib.datatypes.Tuple3;
|
||||||
@@ -20,11 +24,15 @@ import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
|||||||
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
|
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Dictionary;
|
import java.util.Dictionary;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import static androidx.constraintlayout.widget.Constraints.TAG;
|
import static androidx.constraintlayout.widget.Constraints.TAG;
|
||||||
@@ -58,7 +66,7 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
private final List<Purchase> purchases = new ArrayList<>();
|
private final List<Purchase> purchases = new ArrayList<>();
|
||||||
private boolean _isInitialized = false;
|
private boolean _isInitialized = false;
|
||||||
|
|
||||||
private Map<String, Boolean> _localCache= new HashMap<>();
|
private final Map<String, Boolean> _localCache= new HashMap<>();
|
||||||
|
|
||||||
public IABService(Context c)
|
public IABService(Context c)
|
||||||
{
|
{
|
||||||
@@ -72,12 +80,18 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
startServiceConnection(this::queryPurchases, false);
|
startServiceConnection(this::queryPurchases, false);
|
||||||
|
startServiceConnection(this::querySkuDetails, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadPrefs()
|
||||||
|
{
|
||||||
|
loadCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadCache()
|
private void loadCache()
|
||||||
{
|
{
|
||||||
_localCache.clear();
|
_localCache.clear();
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("iab", Context.MODE_PRIVATE);
|
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("IAB", Context.MODE_PRIVATE);
|
||||||
int count = sharedPref.getInt("c", 0);
|
int count = sharedPref.getInt("c", 0);
|
||||||
for (int i=0; i < count; i++)
|
for (int i=0; i < count; i++)
|
||||||
{
|
{
|
||||||
@@ -90,7 +104,7 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
|
|
||||||
private void saveCache()
|
private void saveCache()
|
||||||
{
|
{
|
||||||
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("CMessageList", Context.MODE_PRIVATE);
|
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("IAB", Context.MODE_PRIVATE);
|
||||||
SharedPreferences.Editor editor= sharedPref.edit();
|
SharedPreferences.Editor editor= sharedPref.edit();
|
||||||
|
|
||||||
editor.putInt("c", _localCache.size());
|
editor.putInt("c", _localCache.size());
|
||||||
@@ -121,9 +135,9 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
Purchase.PurchasesResult purchasesResult = client.queryPurchases(BillingClient.SkuType.INAPP);
|
Purchase.PurchasesResult purchasesResult = client.queryPurchases(BillingClient.SkuType.INAPP);
|
||||||
Log.i(TAG, "Querying purchases elapsed time: " + (System.currentTimeMillis() - time) + "ms");
|
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);
|
handlePurchase(p, false);
|
||||||
}
|
}
|
||||||
@@ -145,17 +159,35 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
executeServiceRequest(queryToExecute, false);
|
executeServiceRequest(queryToExecute, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void querySkuDetails() {
|
||||||
|
}
|
||||||
|
|
||||||
public void purchase(Activity a, String id)
|
public void purchase(Activity a, String id)
|
||||||
{
|
{
|
||||||
|
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(() ->
|
executeServiceRequest(() ->
|
||||||
{
|
{
|
||||||
BillingFlowParams flowParams = BillingFlowParams
|
BillingFlowParams flowParams = BillingFlowParams
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setSku(id)
|
.setSkuDetails(skuDetailsList.get(0))
|
||||||
.setType(BillingClient.SkuType.INAPP) // SkuType.SUB for subscription
|
|
||||||
.build();
|
.build();
|
||||||
client.launchBillingFlow(a, flowParams);
|
client.launchBillingFlow(a, flowParams);
|
||||||
}, true);
|
}, true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
executeServiceRequest(queryRequest, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeServiceRequest(Func0to0 runnable, final boolean userRequest)
|
private void executeServiceRequest(Func0to0 runnable, final boolean userRequest)
|
||||||
@@ -181,16 +213,16 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases)
|
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases)
|
||||||
{
|
{
|
||||||
if (responseCode == BillingClient.BillingResponse.OK && purchases != null)
|
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null)
|
||||||
{
|
{
|
||||||
for (Purchase purchase : purchases)
|
for (Purchase purchase : purchases)
|
||||||
{
|
{
|
||||||
handlePurchase(purchase, true);
|
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)
|
for (Purchase purchase : purchases)
|
||||||
{
|
{
|
||||||
@@ -223,9 +255,9 @@ public class IABService implements PurchasesUpdatedListener
|
|||||||
client.startConnection(new BillingClientStateListener()
|
client.startConnection(new BillingClientStateListener()
|
||||||
{
|
{
|
||||||
@Override
|
@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;
|
isServiceConnected = true;
|
||||||
if (executeOnSuccess != null) executeOnSuccess.invoke();
|
if (executeOnSuccess != null) executeOnSuccess.invoke();
|
||||||
|
@@ -229,10 +229,10 @@ public class NotificationService
|
|||||||
if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||||
if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||||
|
|
||||||
Intent intnt_click = new Intent(SCNApp.getContext(), BroadcastReceiverService.class);
|
Intent intent = new Intent(ctxt, MainActivity.class);
|
||||||
intnt_click.putExtra(BroadcastReceiverService.ID_KEY, BroadcastReceiverService.NOTIF_SHOW_MAIN);
|
PendingIntent pi = PendingIntent.getActivity(ctxt, 0, intent, 0);
|
||||||
PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, intnt_click, 0);
|
|
||||||
mBuilder.setContentIntent(pi);
|
mBuilder.setContentIntent(pi);
|
||||||
|
|
||||||
NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if (mNotificationManager == null) return;
|
if (mNotificationManager == null) return;
|
||||||
|
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
package com.blackforestbytes.simplecloudnotifier.view;
|
package com.blackforestbytes.simplecloudnotifier.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.icu.text.SymbolTable;
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
import com.blackforestbytes.simplecloudnotifier.R;
|
||||||
@@ -23,6 +25,12 @@ import androidx.appcompat.widget.Toolbar;
|
|||||||
import androidx.viewpager.widget.PagerAdapter;
|
import androidx.viewpager.widget.PagerAdapter;
|
||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity
|
public class MainActivity extends AppCompatActivity
|
||||||
{
|
{
|
||||||
public TabAdapter adpTabs;
|
public TabAdapter adpTabs;
|
||||||
@@ -31,7 +39,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
QueryLog.instance();
|
QueryLog.inst();
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
@@ -103,4 +111,114 @@ public class MainActivity extends AppCompatActivity
|
|||||||
|
|
||||||
if (clickCount == 4) startActivity(new Intent(this, QueryLogActivity.class));
|
if (clickCount == 4) startActivity(new Intent(this, QueryLogActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if(requestCode == 1991 && resultCode == RESULT_OK)
|
||||||
|
{
|
||||||
|
Uri uri = data.getData(); //The uri with the location of the file
|
||||||
|
|
||||||
|
Context ctxt = this;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ObjectInputStream stream = new ObjectInputStream(getContentResolver().openInputStream(uri));
|
||||||
|
|
||||||
|
Map<String, ?> d1 = (Map<String, ?>)stream.readObject();
|
||||||
|
Map<String, ?> d2 = (Map<String, ?>)stream.readObject();
|
||||||
|
Map<String, ?> d3 = (Map<String, ?>)stream.readObject();
|
||||||
|
Map<String, ?> d4 = (Map<String, ?>)stream.readObject();
|
||||||
|
|
||||||
|
stream.close();
|
||||||
|
|
||||||
|
runOnUiThread(() ->
|
||||||
|
{
|
||||||
|
|
||||||
|
SharedPreferences.Editor e1 = ctxt.getSharedPreferences("Config", Context.MODE_PRIVATE).edit();
|
||||||
|
SharedPreferences.Editor e2 = ctxt.getSharedPreferences("IAB", Context.MODE_PRIVATE).edit();
|
||||||
|
SharedPreferences.Editor e3 = ctxt.getSharedPreferences("CMessageList", Context.MODE_PRIVATE).edit();
|
||||||
|
SharedPreferences.Editor e4 = ctxt.getSharedPreferences("QueryLog", Context.MODE_PRIVATE).edit();
|
||||||
|
|
||||||
|
e1.clear();
|
||||||
|
for (Map.Entry<String, ?> entry : d1.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue() instanceof String) e1.putString(entry.getKey(), (String)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Boolean) e1.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Float) e1.putFloat(entry.getKey(), (Float)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Integer) e1.putInt(entry.getKey(), (Integer)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Long) e1.putLong(entry.getKey(), (Long)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Set<?>) e1.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
e2.clear();
|
||||||
|
for (Map.Entry<String, ?> entry : d2.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue() instanceof String) e2.putString(entry.getKey(), (String)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Boolean) e2.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Float) e2.putFloat(entry.getKey(), (Float)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Integer) e2.putInt(entry.getKey(), (Integer)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Long) e2.putLong(entry.getKey(), (Long)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Set<?>) e2.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
e2.clear();
|
||||||
|
for (Map.Entry<String, ?> entry : d3.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue() instanceof String) e3.putString(entry.getKey(), (String)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Boolean) e3.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Float) e3.putFloat(entry.getKey(), (Float)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Integer) e3.putInt(entry.getKey(), (Integer)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Long) e3.putLong(entry.getKey(), (Long)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Set<?>) e3.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
e4.clear();
|
||||||
|
for (Map.Entry<String, ?> entry : d4.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue() instanceof String) e4.putString(entry.getKey(), (String)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Boolean) e4.putBoolean(entry.getKey(), (Boolean)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Float) e4.putFloat(entry.getKey(), (Float)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Integer) e4.putInt(entry.getKey(), (Integer)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Long) e4.putLong(entry.getKey(), (Long)entry.getValue());
|
||||||
|
if (entry.getValue() instanceof Set<?>) e4.putStringSet(entry.getKey(), (Set<String>)entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
e1.apply();
|
||||||
|
e2.apply();
|
||||||
|
e3.apply();
|
||||||
|
e4.apply();
|
||||||
|
|
||||||
|
|
||||||
|
SCNSettings.inst().reloadPrefs();
|
||||||
|
IABService.inst().reloadPrefs();
|
||||||
|
CMessageList.inst().reloadPrefs();
|
||||||
|
QueryLog.inst().reloadPrefs();
|
||||||
|
|
||||||
|
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
ViewPager viewPager = findViewById(R.id.pager);
|
||||||
|
PagerAdapter adapter = adpTabs = new TabAdapter(getSupportFragmentManager());
|
||||||
|
viewPager.setAdapter(adapter);
|
||||||
|
|
||||||
|
TabLayout tabLayout = findViewById(R.id.tab_layout);
|
||||||
|
tabLayout.setupWithViewPager(viewPager);
|
||||||
|
|
||||||
|
|
||||||
|
SCNSettings.inst().work(this);
|
||||||
|
|
||||||
|
SCNApp.showToast("Backup imported", Toast.LENGTH_LONG);
|
||||||
|
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.e("Import:Err", e.toString());
|
||||||
|
SCNApp.showToast("Import failed", Toast.LENGTH_LONG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,14 +2,12 @@ package com.blackforestbytes.simplecloudnotifier.view;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.media.AudioAttributes;
|
import android.media.AudioAttributes;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
import android.media.Ringtone;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -27,10 +25,12 @@ import android.widget.Switch;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.billingclient.api.Purchase;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.R;
|
import com.blackforestbytes.simplecloudnotifier.R;
|
||||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.android.ThreadUtils;
|
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.lambda.FI;
|
import com.blackforestbytes.simplecloudnotifier.lib.lambda.FI;
|
||||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||||
@@ -39,10 +39,12 @@ import com.blackforestbytes.simplecloudnotifier.util.TextChangedListener;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import top.defaults.colorpicker.ColorPickerPopup;
|
import top.defaults.colorpicker.ColorPickerPopup;
|
||||||
import xyz.aprildown.ultimatemusicpicker.MusicPickerListener;
|
import xyz.aprildown.ultimatemusicpicker.MusicPickerListener;
|
||||||
import xyz.aprildown.ultimatemusicpicker.UltimateMusicPicker;
|
import xyz.aprildown.ultimatemusicpicker.UltimateMusicPicker;
|
||||||
@@ -93,6 +95,9 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
private SeekBar prefMsgHighVolume;
|
private SeekBar prefMsgHighVolume;
|
||||||
private ImageView prefMsgHighVolumeTest;
|
private ImageView prefMsgHighVolumeTest;
|
||||||
|
|
||||||
|
private Button prefBtnImport;
|
||||||
|
private Button prefBtnExport;
|
||||||
|
|
||||||
private int musicPickerSwitch = -1;
|
private int musicPickerSwitch = -1;
|
||||||
|
|
||||||
private MediaPlayer[] mPlayers = new MediaPlayer[3];
|
private MediaPlayer[] mPlayers = new MediaPlayer[3];
|
||||||
@@ -160,6 +165,9 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
prefMsgHighVolume = v.findViewById(R.id.prefMsgHighVolume);
|
prefMsgHighVolume = v.findViewById(R.id.prefMsgHighVolume);
|
||||||
prefMsgHighVolumeTest = v.findViewById(R.id.btnHighVolumeTest);
|
prefMsgHighVolumeTest = v.findViewById(R.id.btnHighVolumeTest);
|
||||||
|
|
||||||
|
prefBtnExport = v.findViewById(R.id.prefExport);
|
||||||
|
prefBtnImport = v.findViewById(R.id.prefImport);
|
||||||
|
|
||||||
ArrayAdapter<Integer> plcsa = new ArrayAdapter<>(v.getContext(), android.R.layout.simple_spinner_item, SCNSettings.CHOOSABLE_CACHE_SIZES);
|
ArrayAdapter<Integer> plcsa = new ArrayAdapter<>(v.getContext(), android.R.layout.simple_spinner_item, SCNSettings.CHOOSABLE_CACHE_SIZES);
|
||||||
plcsa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
plcsa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
prefLocalCacheSize.setAdapter(plcsa);
|
prefLocalCacheSize.setAdapter(plcsa);
|
||||||
@@ -246,6 +254,9 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
|
|
||||||
prefUpgradeAccount.setOnClickListener(a -> onUpgradeAccount());
|
prefUpgradeAccount.setOnClickListener(a -> onUpgradeAccount());
|
||||||
|
|
||||||
|
prefBtnExport.setOnClickListener(a -> onExport());
|
||||||
|
prefBtnImport.setOnClickListener(a -> onImport());
|
||||||
|
|
||||||
prefMsgLowEnableSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.EnableSound=b; saveAndUpdate(); });
|
prefMsgLowEnableSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.EnableSound=b; saveAndUpdate(); });
|
||||||
prefMsgLowRingtone_container.setOnClickListener(a -> chooseRingtoneLow());
|
prefMsgLowRingtone_container.setOnClickListener(a -> chooseRingtoneLow());
|
||||||
prefMsgLowRepeatSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.RepeatSound=b; saveAndUpdate(); });
|
prefMsgLowRepeatSound.setOnCheckedChangeListener((a,b) -> { s.PriorityLow.RepeatSound=b; saveAndUpdate(); });
|
||||||
@@ -277,6 +288,55 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
|||||||
prefMsgHighVolumeTest.setOnClickListener((v) -> { if (s.PriorityHigh.ForceVolume) playTestSound(2, prefMsgHighVolumeTest, s.PriorityHigh.SoundSource, s.PriorityHigh.ForceVolumeValue); });
|
prefMsgHighVolumeTest.setOnClickListener((v) -> { if (s.PriorityHigh.ForceVolume) playTestSound(2, prefMsgHighVolumeTest, s.PriorityHigh.SoundSource, s.PriorityHigh.ForceVolumeValue); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onExport()
|
||||||
|
{
|
||||||
|
Context ctxt = getContext();
|
||||||
|
if (ctxt == null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File outputDir = ctxt.getCacheDir(); // context being the Activity pointer
|
||||||
|
File outputFile = File.createTempFile("scn_export_", ".dat", outputDir);
|
||||||
|
|
||||||
|
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(outputFile));
|
||||||
|
|
||||||
|
Map<String, ?> d1 = ctxt.getSharedPreferences("Config", Context.MODE_PRIVATE).getAll();
|
||||||
|
Map<String, ?> d2 = ctxt.getSharedPreferences("IAB", Context.MODE_PRIVATE).getAll();
|
||||||
|
Map<String, ?> d3 = ctxt.getSharedPreferences("CMessageList", Context.MODE_PRIVATE).getAll();
|
||||||
|
Map<String, ?> d4 = ctxt.getSharedPreferences("QueryLog", Context.MODE_PRIVATE).getAll();
|
||||||
|
|
||||||
|
output.writeObject(d1);
|
||||||
|
output.writeObject(d2);
|
||||||
|
output.writeObject(d3);
|
||||||
|
output.writeObject(d4);
|
||||||
|
|
||||||
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
|
|
||||||
|
Uri uri = FileProvider.getUriForFile(ctxt, "com.blackforestbytes.simplecloudnotifier.fileprovider", outputFile);
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||||
|
intent.setType("*/*");
|
||||||
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
|
||||||
|
startActivity(Intent.createChooser(intent, "Export"));
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Log.e("Export:Err", e.toString());
|
||||||
|
SCNApp.showToast("Export failed", Toast.LENGTH_LONG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onImport()
|
||||||
|
{
|
||||||
|
SCNApp.getMainActivity().setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
Intent intent = new Intent()
|
||||||
|
.setType("*/*")
|
||||||
|
.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
|
|
||||||
|
((MainActivity)getActivity()).startActivityForResult(Intent.createChooser(intent, "Select a file"), 1991);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateEnabled(boolean prev, boolean now)
|
private void updateEnabled(boolean prev, boolean now)
|
||||||
{
|
{
|
||||||
if (!prev && now)
|
if (!prev && now)
|
||||||
|
@@ -22,7 +22,7 @@ public class QueryLogActivity extends AppCompatActivity
|
|||||||
setContentView(R.layout.activity_querylog);
|
setContentView(R.layout.activity_querylog);
|
||||||
|
|
||||||
ListView lvMain = findViewById(R.id.lvQueryList);
|
ListView lvMain = findViewById(R.id.lvQueryList);
|
||||||
SingleQuery[] arr = QueryLog.instance().get().toArray(new SingleQuery[0]);
|
SingleQuery[] arr = QueryLog.inst().get().toArray(new SingleQuery[0]);
|
||||||
QueryLogAdapter a = new QueryLogAdapter(this, arr);
|
QueryLogAdapter a = new QueryLogAdapter(this, arr);
|
||||||
lvMain.setAdapter(a);
|
lvMain.setAdapter(a);
|
||||||
|
|
||||||
|
@@ -805,6 +805,24 @@
|
|||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/prefExport"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
android:backgroundTint="#444444"
|
||||||
|
android:text="@string/export_settings" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/prefImport"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
android:backgroundTint="#666666"
|
||||||
|
android:text="@string/import_settings" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@@ -37,4 +37,6 @@
|
|||||||
<string name="play_test_sound">Play test sound</string>
|
<string name="play_test_sound">Play test sound</string>
|
||||||
<string name="delete">DELETE</string>
|
<string name="delete">DELETE</string>
|
||||||
<string name="title_activity_query_log">QueryLogActivity</string>
|
<string name="title_activity_query_log">QueryLogActivity</string>
|
||||||
|
<string name="import_settings">Import settings</string>
|
||||||
|
<string name="export_settings">Export settings</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
7
android/app/src/main/res/xml/filepaths.xml
Normal file
7
android/app/src/main/res/xml/filepaths.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<paths>
|
||||||
|
<files-path path="/" name="files" />
|
||||||
|
<cache-path path="/" name="cache" />
|
||||||
|
<external-path path="/" name="external" />
|
||||||
|
<external-files-path path="/" name="external-files" />
|
||||||
|
<external-cache-path path="/" name="external-cache" />
|
||||||
|
</paths>
|
@@ -1,3 +1,3 @@
|
|||||||
#Tue Dec 11 13:55:09 CET 2018
|
#Thu Mar 05 15:29:10 UTC 2020
|
||||||
VERSION_NAME=1.3.0
|
VERSION_NAME=1.8.0
|
||||||
VERSION_CODE=17
|
VERSION_CODE=23
|
||||||
|
@@ -7,8 +7,8 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||||
classpath 'com.google.gms:google-services:4.2.0'
|
classpath 'com.google.gms:google-services:4.3.4'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#Wed Sep 26 22:10:14 CEST 2018
|
#Tue Nov 03 14:10:19 CET 2020
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
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
|
||||||
|
35
examples/scn_send.php
Normal file
35
examples/scn_send.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $title
|
||||||
|
* @param string $content
|
||||||
|
* @param int $priority
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function sendSCN($title, $content, $priority) {
|
||||||
|
global $config;
|
||||||
|
|
||||||
|
$data =
|
||||||
|
[
|
||||||
|
'user_id' => '', //TODO set your userid
|
||||||
|
'user_key' => '', //TODO set your userkey
|
||||||
|
'title' => $title,
|
||||||
|
'content' => $content,
|
||||||
|
'priority' => $priority,
|
||||||
|
];
|
||||||
|
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, "https://simplecloudnotifier.blackforestbytes.com/send.php");
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
if ($result === false) return false;
|
||||||
|
|
||||||
|
$json = json_decode($result, true);
|
||||||
|
return $json['success'];
|
||||||
|
}
|
@@ -166,6 +166,12 @@ function verifyOrderToken($tok)
|
|||||||
{
|
{
|
||||||
// https://developers.google.com/android-publisher/api-ref/purchases/products/get
|
// https://developers.google.com/android-publisher/api-ref/purchases/products/get
|
||||||
|
|
||||||
|
// if this does no longer work, you probably have to go through the initial OAuth process again
|
||||||
|
// 1. go to Postman do the [ https://accounts.google.com/o/oauth2/auth ] request (in browser) to get a new "code"
|
||||||
|
// 2. go to Postman do the [ Get Tokens ] request to get a new "access_token" and "access_token"
|
||||||
|
// 3. update these tokens in the server config.php
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$package = getConfig()['verify_api']['package_name'];
|
$package = getConfig()['verify_api']['package_name'];
|
||||||
|
@@ -24,17 +24,20 @@ if ($ispro)
|
|||||||
$pdo->rollBack();
|
$pdo->rollBack();
|
||||||
die(json_encode(['success' => false, 'message' => 'Purchase token could not be verified']));
|
die(json_encode(['success' => false, 'message' => 'Purchase token could not be verified']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $pdo->prepare('UPDATE users SET is_pro=0, pro_token=NULL WHERE user_id <> :uid AND pro_token = :ptk');
|
|
||||||
$stmt->execute(['uid' => $user_id, 'ptk' => $pro_token]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $pdo->prepare('INSERT INTO users (user_key, fcm_token, is_pro, pro_token, timestamp_accessed) VALUES (:key, :token, :bpro, :spro, NOW())');
|
$stmt = $pdo->prepare('INSERT INTO users (user_key, fcm_token, is_pro, pro_token, timestamp_accessed) VALUES (:key, :token, :bpro, :spro, NOW())');
|
||||||
$stmt->execute(['key' => $user_key, 'token' => $fcmtoken, 'bpro' => $ispro, 'spro' => $ispro ? $pro_token : null]);
|
$stmt->execute(['key' => $user_key, 'token' => $fcmtoken, 'bpro' => ($ispro ? 1 : 0), 'spro' => ($ispro ? $pro_token : null)]);
|
||||||
$user_id = $pdo->lastInsertId('user_id');
|
$user_id = $pdo->lastInsertId('user_id');
|
||||||
|
|
||||||
$stmt = $pdo->prepare('UPDATE users SET fcm_token=NULL WHERE user_id <> :uid AND fcm_token=:ft');
|
$stmt = $pdo->prepare('UPDATE users SET fcm_token=NULL WHERE user_id <> :uid AND fcm_token=:ft');
|
||||||
$stmt->execute(['uid' => $user_id, 'ft' => $fcm_token]);
|
$stmt->execute(['uid' => $user_id, 'ft' => $fcmtoken]);
|
||||||
|
|
||||||
|
if ($ispro)
|
||||||
|
{
|
||||||
|
$stmt = $pdo->prepare('UPDATE users SET is_pro=0, pro_token=NULL WHERE user_id <> :uid AND pro_token = :ptk');
|
||||||
|
$stmt->execute(['uid' => $user_id, 'ptk' => $pro_token]);
|
||||||
|
}
|
||||||
|
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
|
|
||||||
|
@@ -24,10 +24,10 @@ CREATE TABLE `messages`
|
|||||||
`sender_user_id` INT(11) NOT NULL,
|
`sender_user_id` INT(11) NOT NULL,
|
||||||
|
|
||||||
`timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`ack` BIT NOT NULL DEFAULT 0,
|
`ack` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
`title` VARCHAR(256) NOT NULL,
|
`title` VARCHAR(256) NOT NULL,
|
||||||
`content` VARCHAR(12288) NULL,
|
`content` LONGTEXT NULL,
|
||||||
`priority` INT(11) NOT NULL,
|
`priority` INT(11) NOT NULL,
|
||||||
`sendtime` BIGINT UNSIGNED NOT NULL,
|
`sendtime` BIGINT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ try
|
|||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
if (strlen($message) > 120) api_return(400, ['success' => false, 'error' => ERR::TITLE_TOO_LONG, 'errhighlight' => 103, 'message' => 'Title too long (120 characters)']);
|
if (strlen($message) > 120) api_return(400, ['success' => false, 'error' => ERR::TITLE_TOO_LONG, 'errhighlight' => 103, 'message' => 'Title too long (120 characters)']);
|
||||||
if (strlen($content) > Statics::contentlen_max($data['is_pro'])) api_return(400, ['success' => false, 'error' => ERR::CONTENT_TOO_LONG, 'errhighlight' => 104, 'message' => 'Content too long ('.Statics::contentlen_max($data['is_pro']).' characters)']);
|
if (strlen($content) > Statics::contentlen_max($data['is_pro'])) api_return(400, ['success' => false, 'error' => ERR::CONTENT_TOO_LONG, 'errhighlight' => 104, 'message' => 'Content too long ('.strlen($content).' characters; max := '.Statics::contentlen_max($data['is_pro']).' characters)']);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user