Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
66f82f26d5
|
|||
6cb2aa00fb
|
|||
96a236803e
|
|||
9d24044eb3
|
|||
90248bcb54
|
|||
a3b2a1b14f
|
|||
b21b159b95
|
|||
93ec261dc0
|
|||
ae246e9219
|
|||
3f18fdd35a
|
|||
faf5207478
|
|||
71f003dd66
|
|||
3f85ab514e
|
|||
9eb5a6b1b9
|
|||
8e26cd6078
|
|||
36b9263730
|
|||
3d29fecaec
|
|||
![]() |
92ac05f1e3 |
@@ -6,6 +6,7 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
|
||||
<application
|
||||
|
@@ -116,6 +116,10 @@ public class SCNApp extends Application implements LifecycleObserver
|
||||
|
||||
[X] - perhaps response codes in api (?)
|
||||
|
||||
[X] - verify recieve
|
||||
|
||||
[ ] - Android O repeat sound
|
||||
|
||||
[ ] - test notification channels
|
||||
|
||||
[ ] - publish (+ HN post ?)
|
||||
|
@@ -9,7 +9,8 @@ import java.util.TimeZone;
|
||||
|
||||
public class CMessage
|
||||
{
|
||||
public final long Timestamp ;
|
||||
public final long SCN_ID;
|
||||
public final long Timestamp;
|
||||
public final String Title;
|
||||
public final String Content;
|
||||
public final PriorityEnum Priority;
|
||||
@@ -21,8 +22,9 @@ public class CMessage
|
||||
_format.setTimeZone(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
public CMessage(long t, String mt, String mc, PriorityEnum p)
|
||||
public CMessage(long id, long t, String mt, String mc, PriorityEnum p)
|
||||
{
|
||||
SCN_ID = id;
|
||||
Timestamp = t;
|
||||
Title = mt;
|
||||
Content = mc;
|
||||
|
@@ -38,14 +38,15 @@ public class CMessageList
|
||||
String title = sharedPref.getString("message["+i+"].title", "");
|
||||
String content = sharedPref.getString("message["+i+"].content", "");
|
||||
PriorityEnum prio = PriorityEnum.parseAPI(sharedPref.getInt("message["+i+"].priority", 1));
|
||||
long scnid = sharedPref.getLong("message["+i+"].scnid", 0);
|
||||
|
||||
Messages.add(new CMessage(time, title, content, prio));
|
||||
Messages.add(new CMessage(scnid, time, title, content, prio));
|
||||
}
|
||||
}
|
||||
|
||||
public CMessage add(final long time, final String title, final String content, final PriorityEnum pe)
|
||||
public CMessage add(final long scnid, final long time, final String title, final String content, final PriorityEnum pe)
|
||||
{
|
||||
CMessage msg = new CMessage(time, title, content, pe);
|
||||
CMessage msg = new CMessage(scnid, time, title, content, pe);
|
||||
|
||||
boolean run = SCNApp.runOnUiThread(() ->
|
||||
{
|
||||
@@ -58,11 +59,12 @@ public class CMessageList
|
||||
|
||||
while (Messages.size()>SCNSettings.inst().LocalCacheSize) Messages.remove(0);
|
||||
|
||||
e.putInt("message_count", count+1);
|
||||
e.putLong("message["+count+"].timestamp", time);
|
||||
e.putInt( "message_count", count+1);
|
||||
e.putLong( "message["+count+"].timestamp", time);
|
||||
e.putString("message["+count+"].title", title);
|
||||
e.putString("message["+count+"].content", content);
|
||||
e.putInt("message["+count+"].priority", pe.ID);
|
||||
e.putInt( "message["+count+"].priority", pe.ID);
|
||||
e.putLong( "message["+count+"].scnid", scnid);
|
||||
|
||||
e.apply();
|
||||
|
||||
@@ -77,7 +79,7 @@ public class CMessageList
|
||||
|
||||
if (!run)
|
||||
{
|
||||
Messages.add(new CMessage(time, title, content, pe));
|
||||
Messages.add(new CMessage(scnid, time, title, content, pe));
|
||||
fullSave();
|
||||
}
|
||||
|
||||
@@ -109,10 +111,11 @@ public class CMessageList
|
||||
|
||||
for (int i = 0; i < Messages.size(); i++)
|
||||
{
|
||||
e.putLong("message["+i+"].timestamp", Messages.get(i).Timestamp);
|
||||
e.putLong( "message["+i+"].timestamp", Messages.get(i).Timestamp);
|
||||
e.putString("message["+i+"].title", Messages.get(i).Title);
|
||||
e.putString("message["+i+"].content", Messages.get(i).Content);
|
||||
e.putInt("message["+i+"].priority", Messages.get(i).Priority.ID);
|
||||
e.putInt( "message["+i+"].priority", Messages.get(i).Priority.ID);
|
||||
e.putLong( "message["+i+"].scnid", Messages.get(i).SCN_ID);
|
||||
}
|
||||
|
||||
e.apply();
|
||||
|
@@ -1,17 +1,29 @@
|
||||
package com.blackforestbytes.simplecloudnotifier.model;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
|
||||
public class NotificationSettings
|
||||
{
|
||||
public boolean EnableSound = false;
|
||||
public String SoundName = "";
|
||||
public String SoundSource = Uri.EMPTY.toString();
|
||||
public boolean RepeatSound = false;
|
||||
public boolean EnableSound;
|
||||
public String SoundName;
|
||||
public String SoundSource;
|
||||
public boolean RepeatSound;
|
||||
|
||||
public boolean EnableLED = false;
|
||||
public int LEDColor = Color.BLUE;
|
||||
public boolean EnableLED;
|
||||
public int LEDColor;
|
||||
|
||||
public boolean EnableVibration = false;
|
||||
public boolean EnableVibration;
|
||||
|
||||
public NotificationSettings(PriorityEnum p)
|
||||
{
|
||||
EnableSound = (p == PriorityEnum.HIGH);
|
||||
SoundName = (p == PriorityEnum.HIGH) ? "Default" : "";
|
||||
SoundSource = (p == PriorityEnum.HIGH) ? RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION).toString() : Uri.EMPTY.toString();
|
||||
RepeatSound = false;
|
||||
EnableLED = (p == PriorityEnum.HIGH) || (p == PriorityEnum.NORMAL);
|
||||
LEDColor = Color.BLUE;
|
||||
EnableVibration = (p == PriorityEnum.HIGH) || (p == PriorityEnum.NORMAL);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import android.view.View;
|
||||
|
||||
import com.android.billingclient.api.Purchase;
|
||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||
import com.blackforestbytes.simplecloudnotifier.service.IABService;
|
||||
import com.google.firebase.iid.FirebaseInstanceId;
|
||||
|
||||
@@ -47,9 +48,9 @@ public class SCNSettings
|
||||
public boolean Enabled = true;
|
||||
public int LocalCacheSize = 500;
|
||||
|
||||
public final NotificationSettings PriorityLow = new NotificationSettings();
|
||||
public final NotificationSettings PriorityNorm = new NotificationSettings();
|
||||
public final NotificationSettings PriorityHigh = new NotificationSettings();
|
||||
public final NotificationSettings PriorityLow = new NotificationSettings(PriorityEnum.LOW);
|
||||
public final NotificationSettings PriorityNorm = new NotificationSettings(PriorityEnum.NORMAL);
|
||||
public final NotificationSettings PriorityHigh = new NotificationSettings(PriorityEnum.HIGH);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
@@ -195,10 +196,10 @@ public class SCNSettings
|
||||
if (isConnected())
|
||||
{
|
||||
ServerCommunication.info(user_id, user_key, loader);
|
||||
if (promode_server != promode_local)
|
||||
{
|
||||
updateProState(loader);
|
||||
}
|
||||
|
||||
if (promode_server != promode_local) updateProState(loader);
|
||||
|
||||
if (!Str.equals(fcm_token_local, fcm_token_server)) work(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -4,7 +4,9 @@ import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.blackforestbytes.simplecloudnotifier.SCNApp;
|
||||
import com.blackforestbytes.simplecloudnotifier.lib.string.Str;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
@@ -39,7 +41,7 @@ public class ServerCommunication
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:register", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
|
||||
}
|
||||
@@ -57,25 +59,25 @@ public class ServerCommunication
|
||||
|
||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||
|
||||
if (!json.getBoolean("success"))
|
||||
if (!json_bool(json, "success"))
|
||||
{
|
||||
SCNApp.showToast(json.getString("message"), 4000);
|
||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||
return;
|
||||
}
|
||||
|
||||
SCNSettings.inst().user_id = json.getInt("user_id");
|
||||
SCNSettings.inst().user_key = json.getString("user_key");
|
||||
SCNSettings.inst().user_id = json_int(json, "user_id");
|
||||
SCNSettings.inst().user_key = json_str(json, "user_key");
|
||||
SCNSettings.inst().fcm_token_server = token;
|
||||
SCNSettings.inst().quota_curr = json.getInt("quota");
|
||||
SCNSettings.inst().quota_max = json.getInt("quota_max");
|
||||
SCNSettings.inst().promode_server = json.getBoolean("is_pro");
|
||||
SCNSettings.inst().quota_curr = json_int(json, "quota");
|
||||
SCNSettings.inst().quota_max = json_int(json, "quota_max");
|
||||
SCNSettings.inst().promode_server = json_bool(json, "is_pro");
|
||||
SCNSettings.inst().save();
|
||||
|
||||
SCNApp.refreshAccountTab();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:register", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
finally
|
||||
@@ -87,7 +89,7 @@ public class ServerCommunication
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:register", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +107,7 @@ public class ServerCommunication
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:update_1", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
|
||||
}
|
||||
@@ -123,25 +125,25 @@ public class ServerCommunication
|
||||
|
||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||
|
||||
if (!json.getBoolean("success"))
|
||||
if (!json_bool(json, "success"))
|
||||
{
|
||||
SCNApp.showToast(json.getString("message"), 4000);
|
||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||
return;
|
||||
}
|
||||
|
||||
SCNSettings.inst().user_id = json.getInt("user_id");
|
||||
SCNSettings.inst().user_key = json.getString("user_key");
|
||||
SCNSettings.inst().user_id = json_int(json, "user_id");
|
||||
SCNSettings.inst().user_key = json_str(json, "user_key");
|
||||
SCNSettings.inst().fcm_token_server = token;
|
||||
SCNSettings.inst().quota_curr = json.getInt("quota");
|
||||
SCNSettings.inst().quota_max = json.getInt("quota_max");
|
||||
SCNSettings.inst().promode_server = json.getBoolean("is_pro");
|
||||
SCNSettings.inst().quota_curr = json_int(json, "quota");
|
||||
SCNSettings.inst().quota_max = json_int(json, "quota_max");
|
||||
SCNSettings.inst().promode_server = json_bool(json, "is_pro");
|
||||
SCNSettings.inst().save();
|
||||
|
||||
SCNApp.refreshAccountTab();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:update_1", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
finally
|
||||
@@ -153,7 +155,7 @@ public class ServerCommunication
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:update_1", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
}
|
||||
@@ -169,7 +171,7 @@ public class ServerCommunication
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e("SC:update_2", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
|
||||
@@ -185,21 +187,21 @@ public class ServerCommunication
|
||||
|
||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||
|
||||
if (!json.getBoolean("success")) {
|
||||
SCNApp.showToast(json.getString("message"), 4000);
|
||||
if (!json_bool(json, "success")) {
|
||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||
return;
|
||||
}
|
||||
|
||||
SCNSettings.inst().user_id = json.getInt("user_id");
|
||||
SCNSettings.inst().user_key = json.getString("user_key");
|
||||
SCNSettings.inst().quota_curr = json.getInt("quota");
|
||||
SCNSettings.inst().quota_max = json.getInt("quota_max");
|
||||
SCNSettings.inst().promode_server = json.getBoolean("is_pro");
|
||||
SCNSettings.inst().user_id = json_int(json, "user_id");
|
||||
SCNSettings.inst().user_key = json_str(json, "user_key");
|
||||
SCNSettings.inst().quota_curr = json_int(json, "quota");
|
||||
SCNSettings.inst().quota_max = json_int(json, "quota_max");
|
||||
SCNSettings.inst().promode_server = json_bool(json, "is_pro");
|
||||
SCNSettings.inst().save();
|
||||
|
||||
SCNApp.refreshAccountTab();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("SC:update_2", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
} finally {
|
||||
SCNApp.runOnUiThread(() -> {
|
||||
@@ -211,7 +213,7 @@ public class ServerCommunication
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:update_2", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
}
|
||||
@@ -227,7 +229,7 @@ public class ServerCommunication
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e("SC:info", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
SCNApp.runOnUiThread(() -> {
|
||||
if (loader != null) loader.setVisibility(View.GONE);
|
||||
@@ -246,20 +248,40 @@ public class ServerCommunication
|
||||
|
||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||
|
||||
if (!json.getBoolean("success")) {
|
||||
SCNApp.showToast(json.getString("message"), 4000);
|
||||
if (!json_bool(json, "success"))
|
||||
{
|
||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||
|
||||
int errid = json.optInt("errid", 0);
|
||||
|
||||
if (errid == 201 || errid == 202 || errid == 203 || errid == 204)
|
||||
{
|
||||
// user not found or auth failed
|
||||
|
||||
SCNSettings.inst().user_id = -1;
|
||||
SCNSettings.inst().user_key = "";
|
||||
SCNSettings.inst().quota_curr = 0;
|
||||
SCNSettings.inst().quota_max = 0;
|
||||
SCNSettings.inst().promode_server = false;
|
||||
SCNSettings.inst().fcm_token_server = "";
|
||||
SCNSettings.inst().save();
|
||||
|
||||
SCNApp.refreshAccountTab();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SCNSettings.inst().user_id = json.getInt("user_id");
|
||||
SCNSettings.inst().quota_curr = json.getInt("quota");
|
||||
SCNSettings.inst().quota_max = json.getInt("quota_max");
|
||||
SCNSettings.inst().promode_server = json.getBoolean("is_pro");
|
||||
SCNSettings.inst().user_id = json_int(json, "user_id");
|
||||
SCNSettings.inst().quota_curr = json_int(json, "quota");
|
||||
SCNSettings.inst().quota_max = json_int(json, "quota_max");
|
||||
SCNSettings.inst().promode_server = json_bool(json, "is_pro");
|
||||
if (!json_bool(json, "fcm_token_set")) SCNSettings.inst().fcm_token_server = "";
|
||||
SCNSettings.inst().save();
|
||||
|
||||
SCNApp.refreshAccountTab();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("SC:info", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
} finally {
|
||||
SCNApp.runOnUiThread(() -> {
|
||||
@@ -271,7 +293,7 @@ public class ServerCommunication
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Log.e("SC:info", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
}
|
||||
@@ -289,7 +311,7 @@ public class ServerCommunication
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e("SC:upgrade", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
}
|
||||
|
||||
@@ -305,21 +327,20 @@ public class ServerCommunication
|
||||
|
||||
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
|
||||
|
||||
if (!json.getBoolean("success")) {
|
||||
SCNApp.showToast(json.getString("message"), 4000);
|
||||
if (!json_bool(json, "success")) {
|
||||
SCNApp.showToast(json_str(json, "message"), 4000);
|
||||
return;
|
||||
}
|
||||
|
||||
SCNSettings.inst().user_id = json.getInt("user_id");
|
||||
SCNSettings.inst().user_key = json.getString("user_key");
|
||||
SCNSettings.inst().quota_curr = json.getInt("quota");
|
||||
SCNSettings.inst().quota_max = json.getInt("quota_max");
|
||||
SCNSettings.inst().promode_server = json.getBoolean("is_pro");
|
||||
SCNSettings.inst().user_id = json_int(json, "user_id");
|
||||
SCNSettings.inst().quota_curr = json_int(json, "quota");
|
||||
SCNSettings.inst().quota_max = json_int(json, "quota_max");
|
||||
SCNSettings.inst().promode_server = json_bool(json, "is_pro");
|
||||
SCNSettings.inst().save();
|
||||
|
||||
SCNApp.refreshAccountTab();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("SC:upgrade", e.toString());
|
||||
SCNApp.showToast("Communication with server failed", 4000);
|
||||
} finally {
|
||||
SCNApp.runOnUiThread(() -> { if (loader != null) loader.setVisibility(View.GONE); });
|
||||
@@ -334,4 +355,49 @@ public class ServerCommunication
|
||||
}
|
||||
}
|
||||
|
||||
public static void ack(int id, String key, CMessage msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.url(BASE_URL + "ack.php?user_id=" + id + "&user_key=" + key + "&scn_msg_id=" + msg.SCN_ID)
|
||||
.build();
|
||||
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
Log.e("SC:ack", e.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {
|
||||
// ????
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e("SC:ack", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean json_bool(JSONObject o, String key) throws JSONException
|
||||
{
|
||||
Object v = o.get(key);
|
||||
if (v instanceof Integer) return ((int)v) != 0;
|
||||
if (v instanceof Boolean) return ((boolean)v);
|
||||
if (v instanceof String) return !Str.equals(((String)v), "0") && !Str.equals(((String)v), "false");
|
||||
|
||||
return o.getBoolean(key);
|
||||
}
|
||||
|
||||
private static int json_int(JSONObject o, String key) throws JSONException
|
||||
{
|
||||
return o.getInt(key);
|
||||
}
|
||||
|
||||
private static String json_str(JSONObject o, String key) throws JSONException
|
||||
{
|
||||
return o.getString(key);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import com.blackforestbytes.simplecloudnotifier.model.CMessage;
|
||||
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
|
||||
import com.blackforestbytes.simplecloudnotifier.model.PriorityEnum;
|
||||
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
|
||||
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
|
||||
@@ -36,9 +37,9 @@ public class FBMService extends FirebaseMessagingService
|
||||
String title = remoteMessage.getData().get("title");
|
||||
String content = remoteMessage.getData().get("body");
|
||||
PriorityEnum prio = PriorityEnum.parseAPI(remoteMessage.getData().get("priority"));
|
||||
long scn_id = Long.parseLong(remoteMessage.getData().get("scn_msg_id"));
|
||||
|
||||
CMessage msg = CMessageList.inst().add(time, title, content, prio);
|
||||
|
||||
CMessage msg = CMessageList.inst().add(scn_id, time, title, content, prio);
|
||||
|
||||
if (SCNApp.isBackground())
|
||||
{
|
||||
@@ -48,6 +49,8 @@ public class FBMService extends FirebaseMessagingService
|
||||
{
|
||||
NotificationService.inst().showForeground(msg);
|
||||
}
|
||||
|
||||
ServerCommunication.ack(SCNSettings.inst().user_id, SCNSettings.inst().user_key, msg);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@@ -6,9 +6,14 @@ import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.blackforestbytes.simplecloudnotifier.R;
|
||||
@@ -23,9 +28,7 @@ import androidx.core.app.NotificationCompat;
|
||||
|
||||
public class NotificationService
|
||||
{
|
||||
private final static String CHANNEL_ID_LOW = "CHAN_BFB_SCN_MESSAGES_LOW";
|
||||
private final static String CHANNEL_ID_NORM = "CHAN_BFB_SCN_MESSAGES_NORM";
|
||||
private final static String CHANNEL_ID_HIGH = "CHAN_BFB_SCN_MESSAGES_HIGH";
|
||||
private final static String CHANNEL_ID = "CHAN_BFB_SCN_MESSAGES";
|
||||
|
||||
private final static Object _lock = new Object();
|
||||
private static NotificationService _inst = null;
|
||||
@@ -51,72 +54,86 @@ public class NotificationService
|
||||
NotificationManager notifman = ctxt.getSystemService(NotificationManager.class);
|
||||
if (notifman == null) return;
|
||||
|
||||
NotificationChannel channelLow = notifman.getNotificationChannel(CHANNEL_ID_LOW);
|
||||
if (channelLow == null) notifman.createNotificationChannel(channelLow = new NotificationChannel(CHANNEL_ID_LOW, "Push notifications (low priority)", NotificationManager.IMPORTANCE_LOW));
|
||||
NotificationChannel channelNorm = notifman.getNotificationChannel(CHANNEL_ID_NORM);
|
||||
if (channelNorm == null) notifman.createNotificationChannel(channelNorm = new NotificationChannel(CHANNEL_ID_NORM, "Push notifications (normal priority)", NotificationManager.IMPORTANCE_DEFAULT));
|
||||
NotificationChannel channelHigh = notifman.getNotificationChannel(CHANNEL_ID_HIGH);
|
||||
if (channelHigh == null) notifman.createNotificationChannel(channelHigh = new NotificationChannel(CHANNEL_ID_HIGH, "Push notifications (high priority)", NotificationManager.IMPORTANCE_HIGH));
|
||||
|
||||
channelLow.setDescription("Messages from the API with priority set to low");
|
||||
channelLow.enableLights(SCNSettings.inst().PriorityLow.EnableLED);
|
||||
channelLow.setLightColor(SCNSettings.inst().PriorityLow.LEDColor);
|
||||
channelLow.enableVibration(SCNSettings.inst().PriorityLow.EnableVibration);
|
||||
channelLow.setVibrationPattern(new long[]{200});
|
||||
|
||||
channelNorm.setDescription("Messages from the API with priority set to normal");
|
||||
channelNorm.enableLights(SCNSettings.inst().PriorityNorm.EnableLED);
|
||||
channelNorm.setLightColor(SCNSettings.inst().PriorityNorm.LEDColor);
|
||||
channelNorm.enableVibration(SCNSettings.inst().PriorityNorm.EnableVibration);
|
||||
channelNorm.setVibrationPattern(new long[]{200});
|
||||
|
||||
channelHigh.setDescription("Messages from the API with priority set to high");
|
||||
channelHigh.enableLights(SCNSettings.inst().PriorityHigh.EnableLED);
|
||||
channelHigh.setLightColor(SCNSettings.inst().PriorityHigh.LEDColor);
|
||||
channelHigh.enableVibration(SCNSettings.inst().PriorityHigh.EnableVibration);
|
||||
channelHigh.setVibrationPattern(new long[]{200});
|
||||
channelLow.setBypassDnd(true);
|
||||
channelLow.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
||||
NotificationChannel channel = notifman.getNotificationChannel(CHANNEL_ID);
|
||||
if (channel == null)
|
||||
{
|
||||
channel = new NotificationChannel(CHANNEL_ID, "Push notifications", NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.setDescription("Push notifications from the server");
|
||||
channel.setSound(null, null);
|
||||
channel.setVibrationPattern(null);
|
||||
notifman.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public void showForeground(CMessage msg)
|
||||
{
|
||||
SCNApp.showToast("Message recieved: " + msg.Title, Toast.LENGTH_LONG);
|
||||
|
||||
try
|
||||
{
|
||||
NotificationSettings ns = SCNSettings.inst().PriorityNorm;
|
||||
switch (msg.Priority)
|
||||
{
|
||||
case LOW: ns = SCNSettings.inst().PriorityLow; break;
|
||||
case NORMAL: ns = SCNSettings.inst().PriorityNorm; break;
|
||||
case HIGH: ns = SCNSettings.inst().PriorityHigh; break;
|
||||
}
|
||||
|
||||
if (ns.EnableSound && !ns.SoundSource.isEmpty())
|
||||
{
|
||||
Ringtone rt = RingtoneManager.getRingtone(SCNApp.getContext(), Uri.parse(ns.SoundSource));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) rt.setLooping(false);
|
||||
rt.play();
|
||||
new Thread(() -> { try { Thread.sleep(5*1000); } catch (InterruptedException e) { /* */ } rt.stop(); }).start();
|
||||
}
|
||||
|
||||
if (ns.EnableVibration)
|
||||
{
|
||||
Vibrator v = (Vibrator) SCNApp.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
v.vibrate(VibrationEffect.createOneShot(1500, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||
} else {
|
||||
v.vibrate(1500);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void showBackground(CMessage msg)
|
||||
{
|
||||
Context ctxt = SCNApp.getContext();
|
||||
|
||||
String channel = CHANNEL_ID_NORM;
|
||||
NotificationSettings ns = SCNSettings.inst().PriorityNorm;
|
||||
switch (msg.Priority)
|
||||
{
|
||||
case LOW: ns = SCNSettings.inst().PriorityLow; channel = CHANNEL_ID_LOW; break;
|
||||
case NORMAL: ns = SCNSettings.inst().PriorityNorm; channel = CHANNEL_ID_NORM; break;
|
||||
case HIGH: ns = SCNSettings.inst().PriorityHigh; channel = CHANNEL_ID_HIGH; break;
|
||||
case LOW: ns = SCNSettings.inst().PriorityLow; break;
|
||||
case NORMAL: ns = SCNSettings.inst().PriorityNorm; break;
|
||||
case HIGH: ns = SCNSettings.inst().PriorityHigh; break;
|
||||
}
|
||||
|
||||
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctxt, channel);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
||||
{
|
||||
// old
|
||||
|
||||
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctxt, CHANNEL_ID);
|
||||
mBuilder.setSmallIcon(R.drawable.ic_bfb);
|
||||
mBuilder.setContentTitle(msg.Title);
|
||||
mBuilder.setContentText(msg.Content);
|
||||
mBuilder.setShowWhen(true);
|
||||
mBuilder.setWhen(msg.Timestamp);
|
||||
mBuilder.setWhen(msg.Timestamp * 1000);
|
||||
mBuilder.setAutoCancel(true);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
||||
{
|
||||
|
||||
if (msg.Priority == PriorityEnum.LOW) mBuilder.setPriority(NotificationCompat.PRIORITY_LOW);
|
||||
if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||
if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||
if (ns.EnableVibration) mBuilder.setVibrate(new long[]{200});
|
||||
if (ns.EnableVibration) mBuilder.setVibrate(new long[]{500});
|
||||
if (ns.EnableLED) mBuilder.setLights(ns.LEDColor, 500, 500);
|
||||
}
|
||||
|
||||
if (ns.EnableSound && !ns.SoundSource.isEmpty())
|
||||
{
|
||||
mBuilder.setSound(Uri.parse(ns.SoundSource), AudioManager.STREAM_ALARM);
|
||||
}
|
||||
if (ns.EnableSound && !ns.SoundSource.isEmpty()) mBuilder.setSound(Uri.parse(ns.SoundSource), AudioManager.STREAM_NOTIFICATION);
|
||||
|
||||
Intent intent = new Intent(ctxt, MainActivity.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(ctxt, 0, intent, 0);
|
||||
@@ -128,4 +145,48 @@ public class NotificationService
|
||||
|
||||
if (mNotificationManager != null) mNotificationManager.notify(0, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
// new
|
||||
|
||||
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctxt, CHANNEL_ID);
|
||||
mBuilder.setSmallIcon(R.drawable.ic_bfb);
|
||||
mBuilder.setContentTitle(msg.Title);
|
||||
mBuilder.setContentText(msg.Content);
|
||||
mBuilder.setShowWhen(true);
|
||||
mBuilder.setWhen(msg.Timestamp * 1000);
|
||||
mBuilder.setAutoCancel(true);
|
||||
|
||||
if (ns.EnableLED) mBuilder.setLights(ns.LEDColor, 500, 500);
|
||||
|
||||
if (msg.Priority == PriorityEnum.LOW) mBuilder.setPriority(NotificationCompat.PRIORITY_LOW);
|
||||
if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||
if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||
|
||||
Intent intent = new Intent(ctxt, MainActivity.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(ctxt, 0, intent, 0);
|
||||
mBuilder.setContentIntent(pi);
|
||||
NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (mNotificationManager == null) return;
|
||||
|
||||
Notification n = mBuilder.build();
|
||||
n.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||
|
||||
mNotificationManager.notify(0, n);
|
||||
|
||||
if (ns.EnableSound && !ns.SoundSource.isEmpty())
|
||||
{
|
||||
Ringtone rt = RingtoneManager.getRingtone(SCNApp.getContext(), Uri.parse(ns.SoundSource));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) rt.setLooping(false);
|
||||
rt.play();
|
||||
new Thread(() -> { try { Thread.sleep(5*1000); } catch (InterruptedException e) { /* */ } rt.stop(); }).start();
|
||||
}
|
||||
|
||||
if (ns.EnableVibration)
|
||||
{
|
||||
Vibrator v = (Vibrator) SCNApp.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
v.vibrate(VibrationEffect.createOneShot(1500, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
package com.blackforestbytes.simplecloudnotifier.view;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -21,6 +23,7 @@ import net.glxn.qrgen.android.QRCode;
|
||||
import net.glxn.qrgen.core.image.ImageType;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
@@ -55,15 +58,47 @@ public class AccountFragment extends Fragment
|
||||
|
||||
v.findViewById(R.id.btnAccountReset).setOnClickListener(cv ->
|
||||
{
|
||||
Activity a = getActivity();
|
||||
if (a == null) return;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(a);
|
||||
|
||||
builder.setTitle("Confirm");
|
||||
builder.setMessage("Reset account key?");
|
||||
|
||||
builder.setPositiveButton("YES", (dialog, which) -> {
|
||||
View lpnl = v.findViewById(R.id.loadingPanel);
|
||||
lpnl.setVisibility(View.VISIBLE);
|
||||
SCNSettings.inst().reset(lpnl);
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
builder.setNegativeButton("NO", (dialog, which) -> dialog.dismiss());
|
||||
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
});
|
||||
|
||||
v.findViewById(R.id.btnClearLocalStorage).setOnClickListener(cv ->
|
||||
{
|
||||
Activity a = getActivity();
|
||||
if (a == null) return;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(a);
|
||||
|
||||
builder.setTitle("Confirm");
|
||||
builder.setMessage("Clear local messages?");
|
||||
|
||||
builder.setPositiveButton("YES", (dialog, which) -> {
|
||||
CMessageList.inst().clear();
|
||||
SCNApp.showToast("Notifications cleared", 1000);
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
builder.setNegativeButton("NO", (dialog, which) -> dialog.dismiss());
|
||||
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
});
|
||||
|
||||
v.findViewById(R.id.btnQR).setOnClickListener(cv ->
|
||||
|
@@ -45,6 +45,6 @@ public class NotificationsFragment extends Fragment
|
||||
|
||||
public void updateProState()
|
||||
{
|
||||
adView.setVisibility(IABService.inst().getPurchaseCached(IABService.IAB_PRO_MODE) != null ? View.GONE : View.VISIBLE);
|
||||
if (adView != null) adView.setVisibility(IABService.inst().getPurchaseCached(IABService.IAB_PRO_MODE) != null ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
@@ -201,7 +201,6 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
||||
{
|
||||
SCNSettings.inst().save();
|
||||
updateUI();
|
||||
NotificationService.inst().updateChannels();
|
||||
}
|
||||
|
||||
private void onUpgradeAccount()
|
||||
@@ -213,9 +212,9 @@ public class SettingsFragment extends Fragment implements MusicPickerListener
|
||||
{
|
||||
Purchase p = IABService.inst().getPurchaseCached(IABService.IAB_PRO_MODE);
|
||||
|
||||
prefUpgradeAccount.setVisibility( p != null ? View.GONE : View.VISIBLE);
|
||||
prefUpgradeAccount_info.setVisibility(p != null ? View.GONE : View.VISIBLE);
|
||||
prefUpgradeAccount_msg.setVisibility( p != null ? View.VISIBLE : View.GONE );
|
||||
if (prefUpgradeAccount != null) prefUpgradeAccount.setVisibility( p != null ? View.GONE : View.VISIBLE);
|
||||
if (prefUpgradeAccount_info != null) prefUpgradeAccount_info.setVisibility(p != null ? View.GONE : View.VISIBLE);
|
||||
if (prefUpgradeAccount_msg != null) prefUpgradeAccount_msg.setVisibility( p != null ? View.VISIBLE : View.GONE );
|
||||
}
|
||||
|
||||
private int getCacheSizeIndex(int value)
|
||||
|
@@ -4,7 +4,6 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="TooManyViews"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".view.SettingsFragment">
|
||||
@@ -33,23 +32,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<Switch
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefAppEnabled"
|
||||
android:text="@string/str_enabled"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -102,6 +92,7 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center|center"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Button
|
||||
@@ -151,23 +142,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgLowEnableSound"
|
||||
android:text="@string/str_msg_enablesound"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -176,20 +158,15 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/prefMsgLowRingtone_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvMsgLowRingtone"
|
||||
@@ -206,9 +183,8 @@
|
||||
android:spinnerMode="dialog"
|
||||
android:text="Whatever"
|
||||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -217,23 +193,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgLowRepeatSound"
|
||||
android:text="@string/str_repeatnotificationsound"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -242,23 +209,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgLowEnableLED"
|
||||
android:text="@string/str_enable_led"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -308,23 +266,15 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgLowEnableVibrations"
|
||||
android:text="@string/str_enable_vibration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -349,23 +299,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgNormEnableSound"
|
||||
android:text="@string/str_msg_enablesound"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -374,20 +315,15 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/prefMsgNormRingtone_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvMsgNormRingtone"
|
||||
@@ -406,8 +342,6 @@
|
||||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
@@ -415,23 +349,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgNormRepeatSound"
|
||||
android:text="@string/str_repeatnotificationsound"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -440,23 +365,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgNormEnableLED"
|
||||
android:text="@string/str_enable_led"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -506,23 +422,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgNormEnableVibrations"
|
||||
android:text="@string/str_enable_vibration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -547,23 +454,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgHighEnableSound"
|
||||
android:text="@string/str_msg_enablesound"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -572,18 +470,15 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/prefMsgHighRingtone_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
@@ -604,8 +499,6 @@
|
||||
tools:ignore="HardcodedText" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
@@ -613,23 +506,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgHighRepeatSound"
|
||||
android:text="@string/str_repeatnotificationsound"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -638,23 +522,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgHighEnableLED"
|
||||
android:text="@string/str_enable_led"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@@ -704,23 +579,14 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#c0c0c0"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<Switch
|
||||
android:id="@+id/prefMsgHighEnableVibrations"
|
||||
android:text="@string/str_enable_vibration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@@ -18,9 +18,9 @@
|
||||
<string name="str_common_settings">Common Settings</string>
|
||||
<string name="str_enabled">Enabled</string>
|
||||
<string name="str_localcachesize">Remember the last x notifications locally</string>
|
||||
<string name="str_header_prio0">Notifications (low priority)</string>
|
||||
<string name="str_header_prio1">Notifications (normal priority)</string>
|
||||
<string name="str_header_prio2">Notifications (high priority)</string>
|
||||
<string name="str_header_prio0">Notifications (priority 0 - Low)</string>
|
||||
<string name="str_header_prio1">Notifications (priority 1 - Normal)</string>
|
||||
<string name="str_header_prio2">Notifications (priority 2 - High)</string>
|
||||
<string name="str_msg_enablesound">Enable notification sound</string>
|
||||
<string name="str_notificationsound">Notification sound</string>
|
||||
<string name="str_repeatnotificationsound">Repeat notification sound</string>
|
||||
|
@@ -1,3 +1,3 @@
|
||||
#Sun Nov 11 19:37:57 CET 2018
|
||||
VERSION_NAME=0.0.5
|
||||
VERSION_CODE=5
|
||||
#Mon Nov 12 13:06:09 CET 2018
|
||||
VERSION_NAME=0.0.6
|
||||
VERSION_CODE=6
|
||||
|
BIN
data/icon_web.pdn
Normal file
BIN
data/icon_web.pdn
Normal file
Binary file not shown.
47
web/ack.php
Normal file
47
web/ack.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
include_once 'model.php';
|
||||
|
||||
$INPUT = array_merge($_GET, $_POST);
|
||||
|
||||
|
||||
if (!isset($INPUT['user_id'])) die(json_encode(['success' => false, 'errid'=>101, 'message' => 'Missing parameter [[user_id]]']));
|
||||
if (!isset($INPUT['user_key'])) die(json_encode(['success' => false, 'errid'=>102, 'message' => 'Missing parameter [[user_key]]']));
|
||||
if (!isset($INPUT['scn_msg_id'])) die(json_encode(['success' => false, 'errid'=>103, 'message' => 'Missing parameter [[scn_msg_id]]']));
|
||||
|
||||
$user_id = $INPUT['user_id'];
|
||||
$user_key = $INPUT['user_key'];
|
||||
$scn_msg_id = $INPUT['scn_msg_id'];
|
||||
|
||||
//----------------------
|
||||
|
||||
$pdo = getDatabase();
|
||||
|
||||
$stmt = $pdo->prepare('SELECT user_id, user_key, quota_today, is_pro, quota_day, fcm_token FROM users WHERE user_id = :uid LIMIT 1');
|
||||
$stmt->execute(['uid' => $user_id]);
|
||||
$datas = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (count($datas)<=0) die(json_encode(['success' => false, 'errid'=>201, 'message' => 'User not found']));
|
||||
$data = $datas[0];
|
||||
|
||||
if ($data === null) die(json_encode(['success' => false, 'errid'=>202, 'message' => 'User not found']));
|
||||
if ($data['user_id'] !== (int)$user_id) die(json_encode(['success' => false, 'errid'=>203, 'message' => 'UserID not found']));
|
||||
if ($data['user_key'] !== $user_key) die(json_encode(['success' => false, 'errid'=>204, 'message' => 'Authentification failed']));
|
||||
|
||||
$stmt = $pdo->prepare('SELECT ack FROM messages WHERE scn_message_id=:smid AND sender_user_id=:uid LIMIT 1');
|
||||
$stmt->execute(['smid' => $scn_msg_id, 'uid' => $user_id]);
|
||||
$datas = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (count($datas)<=0) die(json_encode(['success' => false, 'errid'=>301, 'message' => 'Message not found']));
|
||||
|
||||
$stmt = $pdo->prepare('UPDATE messages SET ack=1 WHERE scn_message_id=:smid AND sender_user_id=:uid');
|
||||
$stmt->execute(['smid' => $scn_msg_id, 'uid' => $user_id]);
|
||||
|
||||
echo json_encode(
|
||||
[
|
||||
'success' => true,
|
||||
'prev_ack' => $datas[0]['ack'],
|
||||
'new_ack' => 1,
|
||||
'message' => 'ok'
|
||||
]);
|
||||
return 0;
|
@@ -193,6 +193,11 @@ input::-webkit-inner-spin-button {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.fullcenterflex .card
|
||||
{
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
a.card,
|
||||
a.card:active,
|
||||
a.card:visited,
|
||||
|
BIN
web/favicon.ico
Normal file
BIN
web/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
BIN
web/favicon.png
Normal file
BIN
web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
@@ -9,6 +9,8 @@
|
||||
<!--<link rel="stylesheet" href="/css/mini-dark.min.css">-->
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/png" href="/favicon.png"/>
|
||||
<link rel="icon" type="image/png" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<form id="mainpnl">
|
||||
|
@@ -8,6 +8,8 @@
|
||||
<!--<link rel="stylesheet" href="/css/mini-dark.min.css">-->
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/png" href="/favicon.png"/>
|
||||
<link rel="icon" type="image/png" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mainpnl">
|
||||
|
@@ -8,6 +8,8 @@
|
||||
<!--<link rel="stylesheet" href="/css/mini-dark.min.css">-->
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/png" href="/favicon.png"/>
|
||||
<link rel="icon" type="image/png" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mainpnl">
|
||||
@@ -100,6 +102,10 @@
|
||||
<td data-label="Statuscode">403 (Forbidden)</td>
|
||||
<td data-label="Explanation">The user has exceeded its daily quota - wait 24 hours or upgrade your account</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Statuscode">412 (Precondition Failed)</td>
|
||||
<td data-label="Explanation">There is no device connected with this account - open the app and press the refresh button in the account tab</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Statuscode">500 (Internal Server Error)</td>
|
||||
<td data-label="Explanation">There was an internal error while sending your data - try again later</td>
|
||||
|
@@ -8,6 +8,8 @@
|
||||
<!--<link rel="stylesheet" href="/css/mini-dark.min.css">-->
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/png" href="/favicon.png"/>
|
||||
<link rel="icon" type="image/png" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@@ -15,7 +15,7 @@ $user_key = $INPUT['user_key'];
|
||||
|
||||
$pdo = getDatabase();
|
||||
|
||||
$stmt = $pdo->prepare('SELECT user_id, user_key, quota_today, is_pro, quota_day FROM users WHERE user_id = :uid LIMIT 1');
|
||||
$stmt = $pdo->prepare('SELECT user_id, user_key, quota_today, is_pro, quota_day, fcm_token FROM users WHERE user_id = :uid LIMIT 1');
|
||||
$stmt->execute(['uid' => $user_id]);
|
||||
|
||||
$datas = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
@@ -38,6 +38,7 @@ echo json_encode(
|
||||
'quota' => $quota,
|
||||
'quota_max' => Statics::quota_max($is_pro),
|
||||
'is_pro' => $is_pro,
|
||||
'fcm_token_set' => ($data['fcm_token'] != null),
|
||||
'message' => 'ok'
|
||||
]);
|
||||
return 0;
|
@@ -123,7 +123,7 @@ function sendPOST($url, $body, $header)
|
||||
|
||||
if ($response->code != 200) throw new Exception("Repsponse code: " . $response->code);
|
||||
|
||||
return $response->body;
|
||||
return $response->raw_body;
|
||||
}
|
||||
|
||||
function verifyOrderToken($tok)
|
||||
@@ -136,26 +136,25 @@ function verifyOrderToken($tok)
|
||||
$product = getConfig()['verify_api']['product_id'];
|
||||
$acctoken = getConfig()['verify_api']['accesstoken'];
|
||||
|
||||
if ($acctoken == '') $acctoken = refreshVerifyToken();
|
||||
if ($acctoken == '' || $acctoken == null || $acctoken == false) $acctoken = refreshVerifyToken();
|
||||
|
||||
$url = 'https://www.googleapis.com/androidpublisher/v3/applications/'.$package.'/purchases/products/'.$product.'/tokens/'.$tok.'?access_token='.$acctoken;
|
||||
$response = $builder = \Httpful\Request::get($url)->send();
|
||||
$obj = json_decode($response->raw_body, true);
|
||||
|
||||
$json = sendPOST($url, "", []);
|
||||
$obj = json_decode($json);
|
||||
|
||||
if ($obj === null || $obj === false)
|
||||
if ($response->code != 401 && ($obj === null || $obj === false))
|
||||
{
|
||||
reportError('verify-token returned NULL');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($obj['error']) && isset($obj['error']['code']) && $obj['error']['code'] == 401) // "Invalid Credentials" -- refresh acces_token
|
||||
if ($response->code == 401 || isset($obj['error']) && isset($obj['error']['code']) && $obj['error']['code'] == 401) // "Invalid Credentials" -- refresh acces_token
|
||||
{
|
||||
$acctoken = refreshVerifyToken();
|
||||
|
||||
$url = 'https://www.googleapis.com/androidpublisher/v3/applications/'.$package.'/purchases/products/'.$product.'/tokens/'.$tok.'?access_token='.$acctoken;
|
||||
$json = sendPOST($url, "", []);
|
||||
$obj = json_decode($json);
|
||||
$response = $builder = \Httpful\Request::get($url)->send();
|
||||
$obj = json_decode($response->raw_body, true);
|
||||
|
||||
if ($obj === null || $obj === false)
|
||||
{
|
||||
@@ -185,10 +184,10 @@ function refreshVerifyToken()
|
||||
'&client_secret='.getConfig()['verify_api']['clientsecret'];
|
||||
|
||||
$json = sendPOST($url, "", []);
|
||||
$obj = json_decode($json);
|
||||
$obj = json_decode($json, true);
|
||||
file_put_contents('.verify_accesstoken', $obj['access_token']);
|
||||
|
||||
return $obj->access_token;
|
||||
return $obj['access_token'];
|
||||
}
|
||||
|
||||
function api_return($http_code, $message)
|
||||
@@ -201,12 +200,13 @@ function api_return($http_code, $message)
|
||||
/**
|
||||
* @param String $str
|
||||
* @param String[] $path
|
||||
* @return mixed|null
|
||||
*/
|
||||
function try_json($str, $path)
|
||||
{
|
||||
try
|
||||
{
|
||||
$o = json_decode($str);
|
||||
$o = json_decode($str, true);
|
||||
foreach ($path as $p) $o = $o[$p];
|
||||
return $o;
|
||||
}
|
||||
@@ -215,3 +215,15 @@ function try_json($str, $path)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//#################################################################################################################
|
||||
|
||||
if (getConfig()['global']['prod']) {
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
} else {
|
||||
error_reporting(E_STRICT);
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
|
||||
//#################################################################################################################
|
||||
|
@@ -15,15 +15,29 @@ $user_key = generateRandomAuthKey();
|
||||
|
||||
$pdo = getDatabase();
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
if ($ispro)
|
||||
{
|
||||
if (!verifyOrderToken($pro_token)) die(json_encode(['success' => false, 'message' => 'Purchase token could not be verified']));
|
||||
if (!verifyOrderToken($pro_token))
|
||||
{
|
||||
$pdo->rollBack();
|
||||
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->execute(['key' => $user_key, 'token' => $fcmtoken, 'bpro' => $ispro, 'spro' => $ispro ? $pro_token : null]);
|
||||
$user_id = $pdo->lastInsertId('user_id');
|
||||
|
||||
$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]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode(
|
||||
[
|
||||
'success' => true,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
DROP TABLE IF EXISTS `users`;
|
||||
CREATE TABLE `users`
|
||||
(
|
||||
`user_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
@@ -16,19 +17,21 @@ CREATE TABLE `users`
|
||||
PRIMARY KEY (`user_id`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `messages`;
|
||||
CREATE TABLE `messages`
|
||||
(
|
||||
`scn_message_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`sender_user_id` INT(11) NOT NULL,
|
||||
|
||||
`timestamp` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`ack` BIT NOT NULL DEFAULT 0,
|
||||
|
||||
`title` VARCHAR(256) NOT NULL,
|
||||
`content` VARCHAR(12288) NULL,
|
||||
`priority` INT(11) NOT NULL,
|
||||
|
||||
`fcn_message_id` VARCHAR(256) NOT NULL,
|
||||
`fcm_message_id` VARCHAR(256) NULL,
|
||||
`usr_message_id` VARCHAR(256) NULL,
|
||||
|
||||
PRIMARY KEY (`scn_message_id`)
|
||||
)
|
||||
);
|
46
web/send.php
46
web/send.php
@@ -32,6 +32,7 @@ try
|
||||
if (strlen(trim($message)) == 0) api_return(400, json_encode(['success' => false, 'error' => 1201, 'errhighlight' => 103, 'message' => 'No title specified']));
|
||||
if (strlen($message) > 120) api_return(400, json_encode(['success' => false, 'error' => 1202, 'errhighlight' => 103, 'message' => 'Title too long (120 characters)']));
|
||||
if (strlen($content) > 10000) api_return(400, json_encode(['success' => false, 'error' => 1203, 'errhighlight' => 104, 'message' => 'Content too long (10000 characters)']));
|
||||
if ($usrmsgid != null && strlen($usrmsgid) > 64) api_return(400, json_encode(['success' => false, 'error' => 1204, 'errhighlight' => -1, 'message' => 'MessageID too long (64 characters)']));
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
@@ -54,6 +55,11 @@ try
|
||||
if ($data['quota_day'] === null || $data['quota_day'] !== date("Y-m-d")) $new_quota=1;
|
||||
if ($new_quota > Statics::quota_max($data['is_pro'])) api_return(403, json_encode(['success' => false, 'error' => 2101, 'errhighlight' => -1, 'message' => 'Daily quota reached ('.Statics::quota_max($data['is_pro']).')']));
|
||||
|
||||
if ($fcm == null || $fcm == '' || $fcm == false)
|
||||
{
|
||||
api_return(412, json_encode(['success' => false, 'error' => 1401, 'errhighlight' => -1, 'message' => 'No device linked with this account']));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
if ($usrmsgid != null)
|
||||
@@ -79,6 +85,22 @@ try
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
|
||||
$stmt = $pdo->prepare('INSERT INTO messages (sender_user_id, title, content, priority, fcm_message_id, usr_message_id) VALUES (:suid, :t, :c, :p, :fmid, :umid)');
|
||||
$stmt->execute(
|
||||
[
|
||||
'suid' => $user_id,
|
||||
't' => $message,
|
||||
'c' => $content,
|
||||
'p' => $priority,
|
||||
'fmid' => null,
|
||||
'umid' => $usrmsgid,
|
||||
]);
|
||||
|
||||
$scn_msg_id = $pdo->lastInsertId();
|
||||
|
||||
$url = "https://fcm.googleapis.com/fcm/send";
|
||||
$payload = json_encode(
|
||||
[
|
||||
@@ -97,6 +119,7 @@ try
|
||||
'priority' => $priority,
|
||||
'timestamp' => time(),
|
||||
'usr_msg_id' => $usrmsgid,
|
||||
'scn_msg_id' => $scn_msg_id,
|
||||
]
|
||||
]);
|
||||
$header=
|
||||
@@ -112,28 +135,24 @@ try
|
||||
if (try_json($httpresult, ['success']) != 1)
|
||||
{
|
||||
reportError("FCM communication failed (success_1 <> true)\n\n".$httpresult);
|
||||
api_return(403, json_encode(['success' => false, 'error' => 9902, 'errhighlight' => -1, 'message' => 'Communication with firebase service failed.']));
|
||||
$pdo->rollBack();
|
||||
api_return(500, json_encode(['success' => false, 'error' => 9902, 'errhighlight' => -1, 'message' => 'Communication with firebase service failed.']));
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
reportError("FCM communication failed", $e);
|
||||
api_return(403, json_encode(['success' => false, 'error' => 9901, 'errhighlight' => -1, 'message' => 'Communication with firebase service failed.'."\n\n".'Exception: ' . $e->getMessage()]));
|
||||
$pdo->rollBack();
|
||||
api_return(500, json_encode(['success' => false, 'error' => 9901, 'errhighlight' => -1, 'message' => 'Communication with firebase service failed.'."\n\n".'Exception: ' . $e->getMessage()]));
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare('UPDATE users SET timestamp_accessed=NOW(), messages_sent=messages_sent+1, quota_today=:q, quota_day=NOW() WHERE user_id = :uid');
|
||||
$stmt->execute(['uid' => $user_id, 'q' => $new_quota]);
|
||||
|
||||
$stmt = $pdo->prepare('INSERT INTO messages (sender_user_id, title, content, priority, fcn_message_id, usr_message_id) VALUES (:suid, :t, :c, :p, :fmid, :umid)');
|
||||
$stmt->execute(
|
||||
[
|
||||
'suid' => $user_id,
|
||||
't' => $message,
|
||||
'c' => $content,
|
||||
'p' => $priority,
|
||||
'fmid' => try_json($httpresult, ['results', 'message_id']),
|
||||
'umid' => $usrmsgid,
|
||||
]);
|
||||
$stmt = $pdo->prepare('UPDATE messages SET fcm_message_id=:fmid WHERE scn_message_id=:smid');
|
||||
$stmt->execute([ 'fmid' => try_json($httpresult, ['results', 0, 'message_id']), 'smid' => $scn_msg_id ]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
api_return(200, json_encode(
|
||||
[
|
||||
@@ -145,9 +164,12 @@ try
|
||||
'quota' => $new_quota,
|
||||
'is_pro' => $data['is_pro'],
|
||||
'quota_max' => Statics::quota_max($data['is_pro']),
|
||||
'scn_msg_id' => $scn_msg_id,
|
||||
]));
|
||||
}
|
||||
catch (Exception $mex)
|
||||
{
|
||||
reportError("Root try-catch triggered", $mex);
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
api_return(500, json_encode(['success' => false, 'error' => 9903, 'errhighlight' => -1, 'message' => 'PHP script threw exception.'."\n\n".'Exception: ' . $e->getMessage()]));
|
||||
}
|
||||
|
@@ -34,6 +34,8 @@ $new_userkey = generateRandomAuthKey();
|
||||
|
||||
if ($fcm_token === null)
|
||||
{
|
||||
// only gen new user_secret
|
||||
|
||||
$stmt = $pdo->prepare('UPDATE users SET timestamp_accessed=NOW(), user_key=:at WHERE user_id = :uid');
|
||||
$stmt->execute(['uid' => $user_id, 'at' => $new_userkey]);
|
||||
|
||||
@@ -51,9 +53,14 @@ if ($fcm_token === null)
|
||||
}
|
||||
else
|
||||
{
|
||||
// update fcm and gen new user_secret
|
||||
|
||||
$stmt = $pdo->prepare('UPDATE users SET timestamp_accessed=NOW(), fcm_token=:ft, user_key=:at WHERE user_id = :uid');
|
||||
$stmt->execute(['uid' => $user_id, 'ft' => $fcm_token, 'at' => $new_userkey]);
|
||||
|
||||
$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]);
|
||||
|
||||
echo json_encode(
|
||||
[
|
||||
'success' => true,
|
||||
|
@@ -49,8 +49,7 @@ if ($ispro)
|
||||
[
|
||||
'success' => true,
|
||||
'user_id' => $user_id,
|
||||
'user_key' => $new_userkey,
|
||||
'quota' => $data['quota'],
|
||||
'quota' => $data['quota_today'],
|
||||
'quota_max'=> Statics::quota_max(true),
|
||||
'is_pro' => true,
|
||||
'message' => 'user updated'
|
||||
@@ -68,8 +67,7 @@ else
|
||||
[
|
||||
'success' => true,
|
||||
'user_id' => $user_id,
|
||||
'user_key' => $new_userkey,
|
||||
'quota' => $data['quota'],
|
||||
'quota' => $data['quota_today'],
|
||||
'quota_max'=> Statics::quota_max(false),
|
||||
'is_pro' => false,
|
||||
'message' => 'user updated'
|
||||
|
Reference in New Issue
Block a user