does not really work

This commit is contained in:
Mike Schwörer 2018-09-23 20:00:10 +02:00
parent 63633de256
commit 7ea0572d79
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
21 changed files with 902 additions and 217 deletions

View File

@ -14,8 +14,8 @@
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="outputName" value="ic_bfb" />
<entry key="sourceFile" value="F:\Eigene Dateien\Dropbox\Work\BlackForestBytes\Daten\Images\Logo (BFB)\blackforestbytes_logo.svg" />
<entry key="outputName" value="ic_refresh" />
<entry key="sourceFile" value="C:\Users\Mike\Downloads\if_refresh_383083.svg" />
</map>
</option>
</PersistentState>

View File

@ -15,6 +15,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
targetCompatibility 1.8
sourceCompatibility 1.8
}
}
dependencies {
@ -29,6 +33,9 @@ dependencies {
implementation 'com.google.firebase:firebase-core:16.0.3'
implementation 'com.google.firebase:firebase-messaging:17.3.2'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.github.kenglxn.QRGen:android:2.5.0'
}
apply plugin: 'com.google.gms.google-services'

View File

@ -4,7 +4,9 @@ import android.app.Application;
import android.content.Context;
import android.widget.Toast;
import com.blackforestbytes.simplecloudnotifier.view.AccountFragment;
import com.blackforestbytes.simplecloudnotifier.view.MainActivity;
import com.blackforestbytes.simplecloudnotifier.view.TabAdapter;
import java.lang.ref.WeakReference;
@ -28,11 +30,7 @@ public class SCNApp extends Application
final MainActivity a = mainActivity.get();
if (a != null)
{
a.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(a, msg, duration).show();
}
});
a.runOnUiThread(() -> Toast.makeText(a, msg, duration).show());
}
}
@ -43,6 +41,23 @@ public class SCNApp extends Application
return false;
}
public static void refreshAccountTab()
{
runOnUiThread(() ->
{
MainActivity a = mainActivity.get();
if (a == null) return;
TabAdapter ta = a.adpTabs;
if (ta == null) return;
AccountFragment tf = ta.tab2;
if (tf == null) return;
tf.updateUI();
});
}
public static void register(MainActivity a)
{
mainActivity = new WeakReference<>(a);

View File

@ -65,7 +65,7 @@ public class CMessageList
{
MessageAdapter a = ref.get();
if (a == null) continue;
a.notifyItemInserted(count);
a.customNotifyItemInserted(count);
}
CleanUpListener();
}

View File

@ -0,0 +1,126 @@
package com.blackforestbytes.simplecloudnotifier.model;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.View;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
import com.google.firebase.iid.FirebaseInstanceId;
public class SCNSettings
{
private final static Object _lock = new Object();
private static SCNSettings _inst = null;
public static SCNSettings inst()
{
synchronized (_lock)
{
if (_inst != null) return _inst;
return _inst = new SCNSettings();
}
}
public int quota_curr;
public int quota_max;
public int user_id;
public String user_key;
public String fcm_token_local;
public String fcm_token_server;
public SCNSettings()
{
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE);
quota_curr = sharedPref.getInt("quota_curr", 0);
quota_max = sharedPref.getInt("quota_max", 0);
user_id = sharedPref.getInt("user_id", -1);
user_key = sharedPref.getString("user_key", "");
fcm_token_local = sharedPref.getString("fcm_token_local", "");
fcm_token_server = sharedPref.getString("fcm_token_server", "");
}
public void save()
{
SharedPreferences sharedPref = SCNApp.getContext().getSharedPreferences("Config", Context.MODE_PRIVATE);
SharedPreferences.Editor e = sharedPref.edit();
e.putInt("quota_curr", quota_curr);
e.putInt("quota_max", quota_max);
e.putInt("user_id", user_id);
e.putString("user_key", user_key);
e.putString("fcm_token_local", fcm_token_local);
e.putString("fcm_token_server", fcm_token_server);
e.apply();
}
public boolean isConnected()
{
return user_id>=0 && user_key != null && !user_key.isEmpty();
}
public String createOnlineURL()
{
if (!isConnected()) return ServerCommunication.BASE_URL + "index.php";
return ServerCommunication.BASE_URL + "index.php?preset_user_id="+user_id+"&preset_user_key="+user_key;
}
public void setServerToken(String token, View loader)
{
if (isConnected())
{
fcm_token_local = token;
save();
if (!fcm_token_local.equals(fcm_token_server)) ServerCommunication.update(user_id, user_key, fcm_token_local, loader);
}
else
{
fcm_token_local = token;
save();
ServerCommunication.register(fcm_token_local, loader);
}
}
public void work(Activity a)
{
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(a, instanceIdResult ->
{
String newToken = instanceIdResult.getToken();
Log.e("FB::GetInstanceId", newToken);
SCNSettings.inst().setServerToken(newToken, null);
}).addOnCompleteListener(r ->
{
if (isConnected()) ServerCommunication.info(user_id, user_key, null);
});
}
public void reset(View loader)
{
if (!isConnected()) return;
ServerCommunication.update(user_id, user_key, loader);
}
public void refresh(View loader, Activity a)
{
if (isConnected())
{
ServerCommunication.info(user_id, user_key, loader);
}
else
{
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(a, instanceIdResult ->
{
String newToken = instanceIdResult.getToken();
Log.e("FB::GetInstanceId", newToken);
SCNSettings.inst().setServerToken(newToken, loader);
}).addOnCompleteListener(r ->
{
if (isConnected()) ServerCommunication.info(user_id, user_key, null);
});
}
}
}

View File

@ -0,0 +1,276 @@
package com.blackforestbytes.simplecloudnotifier.model;
import android.os.Build;
import android.util.Log;
import android.view.View;
import com.blackforestbytes.simplecloudnotifier.BuildConfig;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class ServerCommunication
{
//public static final String BASE_URL = "https://simplecloudnotifier.blackforestbytes.com/";
public static final String BASE_URL = "http://10.0.2.2:1010/";
private static final OkHttpClient client = new OkHttpClient();
private ServerCommunication(){ throw new Error("no."); }
public static void register(String token, View loader)
{
try
{
Request request = new Request.Builder()
.url(BASE_URL + "register.php?fcm_token="+token)
.build();
client.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
}
@Override
public void onResponse(Call call, Response response)
{
try (ResponseBody responseBody = response.body())
{
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
if (responseBody == null) throw new IOException("No response");
String r = responseBody.string();
Log.d("Server::Response", r);
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
if (!json.getBoolean("success"))
{
SCNApp.showToast(json.getString("message"), 4000);
return;
}
SCNSettings.inst().user_id = json.getInt("user_id");
SCNSettings.inst().user_key = json.getString("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().save();
SCNApp.refreshAccountTab();
}
catch (Exception e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
finally
{
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
}
}
});
}
catch (Exception e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
}
public static void update(int id, String key, String token, View loader)
{
try
{
Request request = new Request.Builder()
.url(BASE_URL + "update.php?user_id="+id+"&user_key="+key+"&fcm_token="+token)
.build();
client.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
}
@Override
public void onResponse(Call call, Response response)
{
try (ResponseBody responseBody = response.body())
{
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
if (responseBody == null) throw new IOException("No response");
String r = responseBody.string();
Log.d("Server::Response", r);
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
if (!json.getBoolean("success"))
{
SCNApp.showToast(json.getString("message"), 4000);
return;
}
SCNSettings.inst().user_id = json.getInt("user_id");
SCNSettings.inst().user_key = json.getString("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().save();
SCNApp.refreshAccountTab();
}
catch (Exception e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
finally
{
SCNApp.runOnUiThread(() -> { if (loader!=null)loader.setVisibility(View.GONE); });
}
}
});
}
catch (Exception e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
}
public static void update(int id, String key, View loader)
{
try
{
Request request = new Request.Builder()
.url(BASE_URL + "update.php?user_id=" + id + "&user_key=" + key)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
@Override
public void onResponse(Call call, Response response) {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
if (responseBody == null) throw new IOException("No response");
String r = responseBody.string();
Log.d("Server::Response", r);
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
if (!json.getBoolean("success")) {
SCNApp.showToast(json.getString("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().save();
SCNApp.refreshAccountTab();
} catch (Exception e) {
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
} finally {
SCNApp.runOnUiThread(() -> {
if (loader != null) loader.setVisibility(View.GONE);
});
}
}
});
}
catch (Exception e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
}
public static void info(int id, String key, View loader)
{
try
{
Request request = new Request.Builder()
.url(BASE_URL + "info.php?user_id=" + id + "&user_key=" + key)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
SCNApp.runOnUiThread(() -> {
if (loader != null) loader.setVisibility(View.GONE);
});
}
@Override
public void onResponse(Call call, Response response) {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
if (responseBody == null) throw new IOException("No response");
String r = responseBody.string();
Log.d("Server::Response", r);
JSONObject json = (JSONObject) new JSONTokener(r).nextValue();
if (!json.getBoolean("success")) {
SCNApp.showToast(json.getString("message"), 4000);
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().save();
SCNApp.refreshAccountTab();
} catch (Exception e) {
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
} finally {
SCNApp.runOnUiThread(() -> {
if (loader != null) loader.setVisibility(View.GONE);
});
}
}
});
}
catch (Exception e)
{
e.printStackTrace();
SCNApp.showToast("Communication with server failed", 4000);
}
}
}

View File

@ -5,6 +5,7 @@ import android.widget.Toast;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
@ -14,6 +15,7 @@ public class FBMService extends FirebaseMessagingService
public void onNewToken(String token)
{
Log.i("Firebase::NewToken", token);
SCNSettings.inst().setServerToken(token, null);
}
@Override

View File

@ -1,13 +1,33 @@
package com.blackforestbytes.simplecloudnotifier.view;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.blackforestbytes.simplecloudnotifier.R;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
import net.glxn.qrgen.android.QRCode;
import net.glxn.qrgen.core.image.ImageType;
import static android.content.Context.CLIPBOARD_SERVICE;
public class AccountFragment extends Fragment
{
@ -19,7 +39,82 @@ public class AccountFragment extends Fragment
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_account, container, false);
View v = inflater.inflate(R.layout.fragment_account, container, false);
updateUI(v);
v.findViewById(R.id.btnCopyUserID).setOnClickListener(cv ->
{
ClipboardManager clipboard = (ClipboardManager) cv.getContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(ClipData.newPlainText("UserID", String.valueOf(SCNSettings.inst().user_id)));
SCNApp.showToast("Copied userID to clipboard", 1000);
});
v.findViewById(R.id.btnCopyUserKey).setOnClickListener(cv ->
{
ClipboardManager clipboard = (ClipboardManager) cv.getContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(ClipData.newPlainText("UserKey", String.valueOf(SCNSettings.inst().user_key)));
SCNApp.showToast("Copied key to clipboard", 1000);
});
v.findViewById(R.id.btnAccountReset).setOnClickListener(cv ->
{
View lpnl = v.findViewById(R.id.loadingPanel);
lpnl.setVisibility(View.VISIBLE);
SCNSettings.inst().reset(lpnl);
});
v.findViewById(R.id.btnClearLocalStorage).setOnClickListener(cv ->
{
CMessageList.inst().Messages.clear();
CMessageList.inst().fullSave();
SCNApp.showToast("Notifications cleared", 1000);
});
v.findViewById(R.id.btnQR).setOnClickListener(cv ->
{
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(SCNSettings.inst().createOnlineURL()));
startActivity(browserIntent);
});
v.findViewById(R.id.btnRefresh).setOnClickListener(cv ->
{
View lpnl = v.findViewById(R.id.loadingPanel);
lpnl.setVisibility(View.VISIBLE);
SCNSettings.inst().refresh(lpnl, getActivity());
});
return v;
}
public void updateUI()
{
updateUI(getView());
}
@SuppressLint("DefaultLocale")
public void updateUI(View v)
{
TextView tvUserID = v.findViewById(R.id.tvUserID);
TextView tvUserKey = v.findViewById(R.id.tvUserKey);
TextView tvQuota = v.findViewById(R.id.tvQuota);
ImageButton btnQR = v.findViewById(R.id.btnQR);
SCNSettings s = SCNSettings.inst();
if (s.isConnected())
{
tvUserID.setText(String.valueOf(s.user_id));
tvUserKey.setText(s.user_key);
tvQuota.setText(String.format("%d / %d", s.quota_curr, s.quota_max));
btnQR.setImageBitmap(QRCode.from(s.createOnlineURL()).to(ImageType.PNG).withSize(512, 512).bitmap());
}
else
{
tvUserID.setText(R.string.str_not_connected);
tvUserKey.setText(R.string.str_not_connected);
tvQuota.setText(R.string.str_not_connected);
btnQR.setImageResource(R.drawable.qr_default);
}
}
}

View File

@ -8,34 +8,40 @@ import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import com.blackforestbytes.simplecloudnotifier.R;
import com.blackforestbytes.simplecloudnotifier.SCNApp;
import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
import com.blackforestbytes.simplecloudnotifier.model.SCNSettings;
import com.blackforestbytes.simplecloudnotifier.model.ServerCommunication;
import com.google.firebase.iid.FirebaseInstanceId;
public class MainActivity extends AppCompatActivity
{
public TabAdapter adpTabs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Notifications"));
tabLayout.addTab(tabLayout.newTab().setText("Account"));
tabLayout.addTab(tabLayout.newTab().setText("Settings"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = findViewById(R.id.pager);
final PagerAdapter adapter = new TabAdapter(getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.pager);
PagerAdapter adapter = adpTabs = new TabAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
TabLayout tabLayout = findViewById(R.id.tab_layout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setupWithViewPager(viewPager);
SCNApp.register(this);
SCNSettings.inst().work(this);
}
@Override

View File

@ -15,8 +15,11 @@ import com.blackforestbytes.simplecloudnotifier.model.CMessageList;
public class MessageAdapter extends RecyclerView.Adapter
{
public MessageAdapter()
private final View vNoElements;
public MessageAdapter(View noElementsView)
{
vNoElements = noElementsView;
CMessageList.inst().register(this);
}
@ -42,6 +45,18 @@ public class MessageAdapter extends RecyclerView.Adapter
return CMessageList.inst().size();
}
public void customNotifyItemInserted(int idx)
{
notifyItemInserted(idx);
vNoElements.setVisibility(getItemCount()>0 ? View.VISIBLE : View.GONE);
}
public void customNotifyDataSetChanged()
{
notifyDataSetChanged();
vNoElements.setVisibility(getItemCount()>0 ? View.VISIBLE : View.GONE);
}
private class MessagePresenter extends RecyclerView.ViewHolder implements View.OnClickListener
{
private TextView tvTimestamp;

View File

@ -27,7 +27,7 @@ public class NotificationsFragment extends Fragment
RecyclerView rvMessages = v.findViewById(R.id.rvMessages);
rvMessages.setLayoutManager(new LinearLayoutManager(this.getContext(), RecyclerView.VERTICAL, true));
rvMessages.setAdapter(new MessageAdapter());
rvMessages.setAdapter(new MessageAdapter(v.findViewById(R.id.tvNoElements)));
return v;
}

View File

@ -6,6 +6,10 @@ import android.support.v4.app.FragmentStatePagerAdapter;
public class TabAdapter extends FragmentStatePagerAdapter {
public NotificationsFragment tab1 = new NotificationsFragment();
public AccountFragment tab2 = new AccountFragment();
public SettingsFragment tab3 = new SettingsFragment();
public TabAdapter(FragmentManager fm)
{
super(fm);
@ -16,16 +20,28 @@ public class TabAdapter extends FragmentStatePagerAdapter {
switch (position) {
case 0:
return new NotificationsFragment();
return tab1;
case 1:
return new AccountFragment();
return tab2;
case 2:
return new SettingsFragment();
return tab3;
default:
return null;
}
}
@Override
public CharSequence getPageTitle(int position)
{
switch (position)
{
case 0: return "Notifications";
case 1: return "Account";
case 2: return "Settings";
default: return null;
}
}
@Override
public int getCount() {
return 3;

View File

@ -0,0 +1,6 @@
<vector
android:width="24dp" android:height="24dp"
android:viewportWidth="16" android:viewportHeight="16"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#231F20" android:pathData="M14,8c-0.609,0-0.898,0.43-1,0.883C12.635,10.516,11.084,13,8,13c-0.757,0-1.473-0.172-2.114-0.474L6.414,12 C6.773,11.656,7,11.445,7,11c0-0.523-0.438-1-1-1H3c-0.609,0-1,0.492-1,1v3c0,0.541,0.428,1,1,1c0.484,0,0.688-0.273,1-0.594 l0.408-0.407C5.458,14.632,6.685,15,8,15c4.99,0,7-4.75,7-5.938C15,8.336,14.469,8,14,8z M3,7.117C3.365,5.485,4.916,3,8,3 c0.757,0,1.473,0.171,2.114,0.473L9.586,4C9.227,4.344,9,4.555,9,5c0,0.523,0.438,1,1,1h3c0.609,0,1-0.492,1-1V2 c0-0.541-0.428-1-1-1c-0.484,0-0.688,0.273-1,0.594l-0.408,0.407C10.542,1.368,9.315,1,8,1C3.01,1,1,5.75,1,6.938 C1,7.664,1.531,8,2,8C2.609,8,2.898,7.57,3,7.117z"/>
</vector>

View File

@ -1,5 +1,5 @@
<vector
android:width="256dp" android:height="256dp"
android:width="24dp" android:height="24dp"
android:viewportWidth="296" android:viewportHeight="296"
xmlns:android="http://schemas.android.com/apk/res/android">

View File

@ -1,197 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout 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:context=".view.AccountFragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
tools:context=".view.AccountFragment">
<ImageView
android:id="@+id/ic_img_user"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="92dp"
android:contentDescription="@string/ic_img_user_desc"
android:src="@drawable/ic_user"
android:tint="#888"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/lblUserID"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/str_userid"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_user"
app:layout_constraintTop_toTopOf="@+id/ic_img_user" />
<ImageView
android:id="@+id/ic_img_user"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="92dp"
android:contentDescription="@string/ic_img_user_desc"
android:src="@drawable/ic_user"
android:tint="#888"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<HorizontalScrollView
android:id="@+id/svUserID"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@+id/btnCopyUserID"
app:layout_constraintStart_toEndOf="@+id/ic_img_user"
app:layout_constraintTop_toBottomOf="@+id/lblUserID">
<TextView
android:id="@+id/tvUserID"
android:id="@+id/lblUserID"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/str_userid"
app:layout_constraintEnd_toStartOf="@+id/btnRefresh"
app:layout_constraintStart_toEndOf="@+id/ic_img_user"
app:layout_constraintTop_toTopOf="@+id/ic_img_user" />
<HorizontalScrollView
android:id="@+id/svUserID"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@+id/btnCopyUserID"
app:layout_constraintStart_toEndOf="@+id/ic_img_user"
app:layout_constraintTop_toBottomOf="@+id/lblUserID">
<TextView
android:id="@+id/tvUserID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</HorizontalScrollView>
<ImageButton
android:id="@+id/btnCopyUserID"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:background="@null"
android:contentDescription="@string/str_copy"
android:padding="2dp"
android:scaleType="fitXY"
android:src="?android:attr/actionModeCopyDrawable"
app:layout_constraintBottom_toBottomOf="@+id/svUserID"
app:layout_constraintEnd_toStartOf="@+id/btnRefresh"
app:layout_constraintTop_toTopOf="@+id/svUserID" />
<ImageButton
android:id="@+id/btnRefresh"
android:layout_width="42dp"
android:layout_height="0dp"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="16dp"
android:background="@null"
android:contentDescription="@string/str_reload"
android:padding="2dp"
android:src="@drawable/ic_refresh"
android:tint="#666"
app:layout_constraintBottom_toBottomOf="@+id/btnCopyUserID"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/lblUserID" />
<ImageView
android:id="@+id/ic_img_key"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="92dp"
android:contentDescription="@string/ic_img_key_desc"
android:src="@drawable/ic_key"
android:tint="#888"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ic_img_user" />
<TextView
android:id="@+id/lblUserKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/str_userkey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_key"
app:layout_constraintTop_toTopOf="@+id/ic_img_key" />
<HorizontalScrollView
android:id="@+id/svUserKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@+id/btnCopyUserKey"
app:layout_constraintStart_toEndOf="@+id/ic_img_key"
app:layout_constraintTop_toBottomOf="@+id/lblUserKey">
<TextView
android:id="@+id/tvUserKey"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</HorizontalScrollView>
<ImageButton
android:id="@+id/btnCopyUserKey"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:background="@null"
android:contentDescription="@string/str_copy"
android:padding="2dp"
android:scaleType="fitXY"
android:src="?android:attr/actionModeCopyDrawable"
app:layout_constraintBottom_toBottomOf="@+id/svUserKey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/svUserKey" />
<ImageView
android:id="@+id/ic_img_quota"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="92dp"
android:contentDescription="@string/ic_img_fuel_desc"
android:src="@drawable/ic_fuel"
android:tint="#888"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ic_img_key" />
<TextView
android:id="@+id/lblQuota"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/str_quota"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_quota"
app:layout_constraintTop_toTopOf="@+id/ic_img_quota" />
<HorizontalScrollView
android:id="@+id/svQuota"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_quota"
app:layout_constraintTop_toBottomOf="@+id/lblQuota">
<TextView
android:id="@+id/tvQuota"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</HorizontalScrollView>
<ImageButton
android:id="@+id/btnQR"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:background="@null"
android:contentDescription="@string/str_qr_code"
android:scaleType="fitCenter"
android:src="@drawable/qr_default"
app:layout_constraintBottom_toTopOf="@+id/btnAccountReset"
app:layout_constraintTop_toBottomOf="@+id/ic_img_quota" />
<Button
android:id="@+id/btnAccountReset"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/str_reset_account"
app:layout_constraintBottom_toTopOf="@+id/btnClearLocalStorage" />
<Button
android:id="@+id/btnClearLocalStorage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Clear Messages"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="352dp" />
</android.support.constraint.ConstraintLayout>
<RelativeLayout
android:id="@+id/loadingPanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#DD000000"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</HorizontalScrollView>
android:indeterminate="true"
android:indeterminateTint="#FFF"
tools:ignore="UnusedAttribute" />
</RelativeLayout>
<ImageButton
android:id="@+id/btnCopyUserID"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:background="@null"
android:padding="2dp"
android:scaleType="fitXY"
android:src="?android:attr/actionModeCopyDrawable"
app:layout_constraintBottom_toBottomOf="@+id/svUserID"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/svUserID"
android:contentDescription="@string/str_copy" />
<ImageView
android:id="@+id/ic_img_key"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="92dp"
android:contentDescription="@string/ic_img_key_desc"
android:src="@drawable/ic_key"
android:tint="#888"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ic_img_user" />
<TextView
android:id="@+id/lblUserKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/str_userkey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_key"
app:layout_constraintTop_toTopOf="@+id/ic_img_key" />
<HorizontalScrollView
android:id="@+id/svUserKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@+id/btnCopyUserKey"
app:layout_constraintStart_toEndOf="@+id/ic_img_key"
app:layout_constraintTop_toBottomOf="@+id/lblUserKey">
<TextView
android:id="@+id/tvUserKey"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</HorizontalScrollView>
<ImageButton
android:id="@+id/btnCopyUserKey"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:background="@null"
android:padding="2dp"
android:scaleType="fitXY"
android:src="?android:attr/actionModeCopyDrawable"
app:layout_constraintBottom_toBottomOf="@+id/svUserKey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/svUserKey"
android:contentDescription="@string/str_copy" />
<ImageView
android:id="@+id/ic_img_quota"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="92dp"
android:contentDescription="@string/ic_img_fuel_desc"
android:src="@drawable/ic_fuel"
android:tint="#888"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ic_img_key" />
<TextView
android:id="@+id/lblQuota"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="@string/str_quota"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_quota"
app:layout_constraintTop_toTopOf="@+id/ic_img_quota" />
<HorizontalScrollView
android:id="@+id/svQuota"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/ic_img_quota"
app:layout_constraintTop_toBottomOf="@+id/lblQuota">
<TextView
android:id="@+id/tvQuota"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</HorizontalScrollView>
<ImageButton
android:id="@+id/btnQR"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:background="@null"
android:contentDescription="@string/str_qr_code"
android:scaleType="center"
android:src="@drawable/qr_default"
app:layout_constraintTop_toBottomOf="@+id/ic_img_quota"
app:layout_constraintBottom_toTopOf="@+id/btnAccountReset" />
<Button
android:id="@+id/btnAccountReset"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/str_reset_account"
app:layout_constraintBottom_toTopOf="@+id/btnClearLocalStorage" />
<Button
android:id="@+id/btnClearLocalStorage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Clear Messages"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="352dp"
app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>
</RelativeLayout>

View File

@ -12,4 +12,11 @@
android:clipToPadding="false"
android:scrollbars="vertical" />
<TextView
android:id="@+id/tvNoElements"
android:textAlignment="center"
android:gravity="center"
android:text="@string/no_notifications"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

View File

@ -1,5 +1,5 @@
<resources>
<string name="app_name">SimpleCloudNotifier</string>
<string name="app_name">Simple Cloud Notifier</string>
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="ic_img_user_desc">Icon User</string>
@ -11,4 +11,7 @@
<string name="ic_img_fuel_desc">Icon Fuel</string>
<string name="str_qr_code">QR Code</string>
<string name="str_reset_account">Reset Account</string>
<string name="no_notifications">No notifications</string>
<string name="str_not_connected">not connected</string>
<string name="str_reload">reload</string>
</resources>

View File

@ -18,6 +18,7 @@ allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}

42
web/info.php Normal file
View File

@ -0,0 +1,42 @@
<?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]]']));
$user_id = $INPUT['user_id'];
$user_key = $INPUT['token'];
//----------------------
$pdo = getDatabase();
$stmt = $pdo->prepare('SELECT user_id, user_key, quota_today, quota_max, quota_day 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' => 'No User 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']));
$quota = $data['quota_today'];
$quota_max = $data['quota_max'];
if ($data['quota_day'] === null || $data['quota_day'] !== date("Y-m-d")) $quota=0;
echo json_encode(
[
'success' => true,
'user_id' => $user_id,
'quota' => $quota,
'quota_max'=> $quota_max,
'message' => 'ok'
]);
return 0;

View File

@ -15,5 +15,14 @@ $stmt = $pdo->prepare('INSERT INTO users (user_key, fcm_token, timestamp_accesse
$stmt->execute(['key' => $user_key, 'token' => $fcmtoken]);
$user_id = $pdo->lastInsertId('user_id');
echo json_encode(['success' => true, 'user_id' => $user_id, 'user_key' => $user_key, 'message' => 'new user registered']);
echo json_encode(
[
'success' => true,
'user_id' => $user_id,
'user_key' => $user_key,
'quota' => 0,
'quota_max'=> 100,
'message' => 'New user registered'
]);
return 0;

View File

@ -7,17 +7,16 @@ $INPUT = array_merge($_GET, $_POST);
if (!isset($INPUT['user_id'])) die(json_encode(['success' => false, 'message' => 'Missing parameter [[user_id]]']));
if (!isset($INPUT['user_key'])) die(json_encode(['success' => false, 'message' => 'Missing parameter [[user_key]]']));
if (!isset($INPUT['message'])) die(json_encode(['success' => false, 'message' => 'Missing parameter [[message]]']));
$user_id = $INPUT['user_id'];
$user_key = $INPUT['token'];
$fcm_token = isset($INPUT['token']) ? $INPUT['token'] : null;
$user_key = $INPUT['user_key'];
$fcm_token = isset($INPUT['fcm_token']) ? $INPUT['fcm_token'] : null;
//----------------------
$pdo = getDatabase();
$stmt = $pdo->prepare('SELECT user_id, user_key FROM users WHERE user_id = :uid LIMIT 1');
$stmt = $pdo->prepare('SELECT user_id, user_key, quota_today, quota_max, quota_day FROM users WHERE user_id = :uid LIMIT 1');
$stmt->execute(['uid' => $user_id]);
$datas = $stmt->fetchAll(PDO::FETCH_ASSOC);
@ -28,6 +27,9 @@ if ($data === null) die(json_encode(['success' => false, 'message' => 'User not
if ($data['user_id'] !== (int)$user_id) die(json_encode(['success' => false, 'message' => 'UserID not found']));
if ($data['user_key'] !== $user_key) die(json_encode(['success' => false, 'message' => 'Authentification failed']));
$quota = $data['quota_today'];
$quota_max = $data['quota_max'];
$new_userkey = generateRandomAuthKey();
if ($fcm_token === null)
@ -35,7 +37,15 @@ if ($fcm_token === null)
$stmt = $pdo->prepare('UPDATE users SET timestamp_accessed=NOW(), user_key=:at WHERE user_id = :uid');
$stmt->execute(['uid' => $user_id, 'at' => $new_userkey]);
echo json_encode(['success' => true, 'user_id' => $user_id, 'user_key' => $new_userkey, 'message' => 'user updated']);
echo json_encode(
[
'success' => true,
'user_id' => $user_id,
'user_key' => $new_userkey,
'quota' => $quota,
'quota_max'=> $quota_max,
'message' => 'user updated'
]);
return 0;
}
else
@ -43,6 +53,14 @@ else
$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]);
echo json_encode(['success' => true, 'user_id' => $user_id, 'user_key' => $new_userkey, 'message' => 'user updated']);
echo json_encode(
[
'success' => true,
'user_id' => $user_id,
'user_key' => $new_userkey,
'quota' => $quota,
'quota_max'=> $quota_max,
'message' => 'user updated'
]);
return 0;
}