android client almost ready

This commit is contained in:
Senad Uka
2016-11-18 08:33:46 +01:00
parent cbeaf566b7
commit 3af4a6d24a
26 changed files with 409 additions and 17 deletions

View File

@@ -30,4 +30,5 @@ dependencies {
compile 'com.android.support:support-v4:24.2.1' compile 'com.android.support:support-v4:24.2.1'
compile 'com.android.support:support-vector-drawable:24.2.1' compile 'com.android.support:support-vector-drawable:24.2.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.android.volley:volley:1.0.0'
} }

View File

@@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
@@ -14,11 +15,13 @@
<activity <activity
android:name=".MainScreen" android:name=".MainScreen"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
@@ -32,12 +35,17 @@
android:name=".AlarmPollingService" android:name=".AlarmPollingService"
android:exported="false" /> android:exported="false" />
<service
android:name=".SoundPlayingService"
android:exported="false" />
<receiver <receiver
android:name=".PeriodicalPingReceiver" android:name="PeriodicalPingReceiver"
android:enabled="true" android:enabled="true"
android:exported="true" /> android:exported="true" />
<activity <activity
android:screenOrientation="portrait"
android:name=".SettingsActivity" android:name=".SettingsActivity"
android:label="@string/title_activity_settings" android:label="@string/title_activity_settings"
android:parentActivityName=".MainScreen"> android:parentActivityName=".MainScreen">

View File

@@ -42,19 +42,18 @@ public class AlarmNotification {
* @see #cancel(Context) * @see #cancel(Context)
*/ */
public static void notify(final Context context, public static void notify(final Context context,
final String exampleString, final int number) { final String message, final int number) {
final Resources res = context.getResources(); final Resources res = context.getResources();
// This image is used as the notification's large icon (thumbnail). // This image is used as the notification's large icon (thumbnail).
// TODO: Remove this if your notification has no relevant thumbnail. // TODO: Remove this if your notification has no relevant thumbnail.
final Bitmap picture = BitmapFactory.decodeResource(res, R.drawable.example_picture); final Bitmap picture = BitmapFactory.decodeResource(res, R.drawable.ic_stat_zoblak);
final String ticker = exampleString; final String ticker = message;
final String title = res.getString( final String title = res.getString(
R.string.alarm_notification_title_template, exampleString); R.string.alarm_notification_title_template, message);
final String text = res.getString( final String text = message;
R.string.alarm_notification_placeholder_text_template, exampleString);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context) final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
@@ -64,7 +63,7 @@ public class AlarmNotification {
// Set required fields, including the small icon, the // Set required fields, including the small icon, the
// notification title, and text. // notification title, and text.
.setSmallIcon(R.drawable.ic_stat_alarm) .setSmallIcon(R.drawable.ic_stat_zoblak)
.setContentTitle(title) .setContentTitle(title)
.setContentText(text) .setContentText(text)
@@ -100,7 +99,7 @@ public class AlarmNotification {
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,
0, 0,
new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com")), new Intent(context, MainScreen.class),
PendingIntent.FLAG_UPDATE_CURRENT)) PendingIntent.FLAG_UPDATE_CURRENT))
// Automatically dismiss the notification when it is touched. // Automatically dismiss the notification when it is touched.
.setAutoCancel(true); .setAutoCancel(true);

View File

@@ -5,4 +5,96 @@ package com.zoblak.farmalarm;
*/ */
public class AlarmPingResponse { public class AlarmPingResponse {
private String controller;
public AlarmPingResponse(String controller) {
this.controller = controller;
}
private Boolean alarmTriggered = false;
private Boolean tooHot = false;
private Boolean tooCold = false;
private Boolean boxSilent = false;
private Boolean phoneSilent = false;
private Boolean serverError = false;
public Boolean getAlarmTriggered() {
return alarmTriggered;
}
public void setAlarmTriggered(Boolean alarmTriggered) {
this.alarmTriggered = alarmTriggered;
}
public Boolean getTooHot() {
return tooHot;
}
public void setTooHot(Boolean tooHot) {
this.tooHot = tooHot;
}
public Boolean getTooCold() {
return tooCold;
}
public void setTooCold(Boolean tooCold) {
this.tooCold = tooCold;
}
public Boolean getBoxSilent() {
return boxSilent;
}
public void setBoxSilent(Boolean boxSilent) {
this.boxSilent = boxSilent;
}
public Boolean getPhoneSilent() {
return phoneSilent;
}
public void setPhoneSilent(Boolean phoneSilent) {
this.phoneSilent = phoneSilent;
}
public Boolean getServerError() {
return serverError;
}
public void setServerError(Boolean serverError) {
this.serverError = serverError;
}
public String toNotificationMessage() {
String message = "Sve je OK!";
if(getAlarmTriggered()) {
if (getAlarmTriggered()) {
message = "Alarm pokrenut! ";
}
if (getTooHot()) {
message += "Temperatura previsoka!";
}
if (getTooCold()) {
message += "Temperatura preniska!";
}
if (getBoxSilent()) {
message += "Zoblak kutija se nije javila na vrijeme!";
}
if (getPhoneSilent()) {
message += "Ni jedan telefon se nije javio na vrijeme! ";
}
if (getServerError()) {
message += "Ne radi internet na telefonu! ";
}
}
return message;
}
} }

View File

@@ -3,6 +3,12 @@ package com.zoblak.farmalarm;
import android.app.IntentService; import android.app.IntentService;
import android.content.Intent; import android.content.Intent;
import android.content.Context; import android.content.Context;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.PowerManager;
import android.util.Log;
import android.widget.Toast;
/** /**
* An {@link IntentService} subclass for handling asynchronous task requests in * An {@link IntentService} subclass for handling asynchronous task requests in
@@ -15,10 +21,13 @@ public class AlarmPollingService extends IntentService {
// TODO: Rename actions, choose action names that describe tasks that this // TODO: Rename actions, choose action names that describe tasks that this
// IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
private static final String ACTION_PING = "com.zoblak.farmalarm.action.PING"; private static final String ACTION_PING = "com.zoblak.farmalarm.action.PING";
private static final String ACTION_STOP_ALARM = "com.zoblak.farmalarm.action.STOP_ALARM";
// TODO: Rename parameters // TODO: Rename parameters
private static final String CONTROLLERS = "com.zoblak.farmalarm.extra.CONTROLLLERS"; private static final String CONTROLLERS = "com.zoblak.farmalarm.extra.CONTROLLLERS";
private AlarmResponseHandler handler;
public AlarmPollingService() { public AlarmPollingService() {
super("AlarmPollingService"); super("AlarmPollingService");
@@ -30,7 +39,6 @@ public class AlarmPollingService extends IntentService {
* *
* @see IntentService * @see IntentService
*/ */
// TODO: Customize helper method
public static void startActionPing(Context context, String controllers) { public static void startActionPing(Context context, String controllers) {
Intent intent = new Intent(context, AlarmPollingService.class); Intent intent = new Intent(context, AlarmPollingService.class);
intent.setAction(ACTION_PING); intent.setAction(ACTION_PING);
@@ -55,7 +63,16 @@ public class AlarmPollingService extends IntentService {
* parameters. * parameters.
*/ */
private void handleActionPing(String controllers) { private void handleActionPing(String controllers) {
// do something
PowerManager powerManager = (PowerManager) this.getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"AlarmPingerWakeLock");
wakeLock.acquire();
ZoblakClient zc = new ZoblakClient(controllers);
handler = new AlarmResponseHandler(this,zc.PingServer());
handler.handle();
wakeLock.release();
} }

View File

@@ -1,8 +1,39 @@
package com.zoblak.farmalarm; package com.zoblak.farmalarm;
import android.annotation.TargetApi;
import android.content.Context;
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.util.Log;
/** /**
* Created by senadu on 11/15/16. * Created by senadu on 11/15/16.
*/ */
public class AlarmResponseHandler { public class AlarmResponseHandler {
AlarmPingResponse response;
Context context;
public AlarmResponseHandler(Context context, AlarmPingResponse response) {
this.response = response;
this.context = context;
}
public void handle() {
if (response.getAlarmTriggered()) {
AlarmNotification.notify(context, response.toNotificationMessage(), 1);
SoundPlayingService.startPlayingAlarm(context);
}
}
} }

View File

@@ -1,5 +1,12 @@
package com.zoblak.farmalarm; package com.zoblak.farmalarm;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
@@ -9,8 +16,13 @@ import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import java.lang.System;
public class MainScreen extends AppCompatActivity { public class MainScreen extends AppCompatActivity {
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -26,6 +38,27 @@ public class MainScreen extends AppCompatActivity {
.setAction("Action", null).show(); .setAction("Action", null).show();
} }
}); });
Intent intent = new Intent(this, PeriodicalPingReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
int PERIOD_IN_MS = 5 * 60 * 1000; // 5 minutes
alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(),
PERIOD_IN_MS, alarmIntent);
}
@Override
protected void onResume() {
super.onResume();
SoundPlayingService.stopPlayingAlarm(this);
} }
@Override @Override
@@ -44,9 +77,13 @@ public class MainScreen extends AppCompatActivity {
//noinspection SimplifiableIfStatement //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) { if (id == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
} }

View File

@@ -27,6 +27,7 @@ public class MainScreenFragment extends Fragment {
WebView webView = (WebView)view.findViewById(R.id.main_web_view); WebView webView = (WebView)view.findViewById(R.id.main_web_view);
WebSettings webSettings = webView.getSettings(); WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webView.loadUrl("http://agrar.zoblak.com/alarm"); webView.loadUrl("http://agrar.zoblak.com/alarm");
return view; return view;

View File

@@ -4,14 +4,19 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.PowerManager;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import static android.content.Context.POWER_SERVICE;
public class PeriodicalPingReceiver extends BroadcastReceiver { public class PeriodicalPingReceiver extends BroadcastReceiver {
public PeriodicalPingReceiver() { public PeriodicalPingReceiver() {
} }
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String controllers = prefs.getString("controllers", null); String controllers = prefs.getString("controllers", null);

View File

@@ -188,7 +188,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// to their values. When their values change, their summaries are // to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design // updated to reflect the new value, per the Android Design
// guidelines. // guidelines.
bindPreferenceSummaryToValue(findPreference("alarm_set"));
bindPreferenceSummaryToValue(findPreference("controllers")); bindPreferenceSummaryToValue(findPreference("controllers"));
bindPreferenceSummaryToValue(findPreference("period_minutes")); bindPreferenceSummaryToValue(findPreference("period_minutes"));
} }

View File

@@ -0,0 +1,73 @@
package com.zoblak.farmalarm;
import android.app.Service;
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.IBinder;
/**
* Created by senadu on 11/18/16.
*/
public class SoundPlayingService extends Service
{
private Ringtone ringtone;
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
startTheAlarm();
return START_NOT_STICKY;
}
@Override
public void onDestroy()
{
stopTheAlarm();
}
public static void startPlayingAlarm(Context context) {
Intent startIntent = new Intent(context, SoundPlayingService.class);
context.startService(startIntent);
}
public static void stopPlayingAlarm(Context context) {
Intent startIntent = new Intent(context, SoundPlayingService.class);
context.stopService(startIntent);
}
@SuppressWarnings("deprecation")
private void startTheAlarm() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
ringtone = RingtoneManager.getRingtone(this, notification);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
ringtone.setAudioAttributes(attributes);
} else {
ringtone.setStreamType(AudioManager.STREAM_ALARM);
}
ringtone.play();
}
public void stopTheAlarm() {
if(ringtone != null && ringtone.isPlaying()) {
ringtone.stop();
}
}
}

View File

@@ -1,8 +1,131 @@
package com.zoblak.farmalarm; package com.zoblak.farmalarm;
import android.util.JsonReader;
import android.util.JsonToken;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/** /**
* Created by senadu on 11/14/16. * Created by senadu on 11/14/16.
*/ */
public class ZoblakClient { public class ZoblakClient {
private String controllers;
public ZoblakClient(String controllers) {
this.controllers = controllers;
}
public AlarmPingResponse PingServer() {
HttpURLConnection urlConnection = null;
AlarmPingResponse result = new AlarmPingResponse(controllers);
URL url = null;
try {
url = new URL("http://agrar.zoblak.com/api/v1.0/alarm/" + controllers + "/phonePing");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000);
urlConnection.setConnectTimeout(15000);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
OutputStream os = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write("{}");
writer.flush();
writer.close();
os.close();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
String jsonString = convertStreamToString(in);
Log.e("JsonString", jsonString);
JsonReader jr = new JsonReader(new StringReader(jsonString));
result = readResponse(jr);
} catch (MalformedURLException e) {
Log.e("zoblakClient", "malformed: " + e.getLocalizedMessage());
} catch (IOException e) {
Log.e("zoblakClient", "ioexception: " + e.getLocalizedMessage());
result.setAlarmTriggered(true);
result.setServerError(true);
}
if (urlConnection != null) urlConnection.disconnect();
return result; // if no response then
}
private AlarmPingResponse readResponse(JsonReader reader) {
AlarmPingResponse result = new AlarmPingResponse(controllers);
try {
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("alarmTriggered") && reader.peek() != JsonToken.NULL) {
result.setAlarmTriggered(reader.nextBoolean());
} else if (name.equals("tooHot") && reader.peek() != JsonToken.NULL) {
result.setTooHot(reader.nextBoolean());
} else if (name.equals("tooCold") && reader.peek() != JsonToken.NULL) {
result.setTooCold(reader.nextBoolean());
} else if (name.equals("boxSilent") && reader.peek() != JsonToken.NULL) {
result.setBoxSilent(reader.nextBoolean());
} else {
reader.skipValue();
}
}
} catch (IOException e) {
Log.e("zoblakClient", "reading result: " + e.getLocalizedMessage());
}
return result;
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -15,7 +15,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/main_web_view" android:id="@+id/main_web_view"
android:partition="persist:browser"
></WebView> ></WebView>
</RelativeLayout> </RelativeLayout>

View File

@@ -1,6 +1,6 @@
<resources> <resources>
<string name="app_name">Farm Alarm</string> <string name="app_name">Farm Alarm</string>
<string name="action_settings">Settings</string> <string name="action_settings">Podešavanje</string>
<string name="title_activity_settings">Podešavanje</string> <string name="title_activity_settings">Podešavanje</string>
<!-- Strings related to Settings --> <!-- Strings related to Settings -->

View File

@@ -6,6 +6,7 @@
android:defaultValue="false" android:defaultValue="false"
android:title="Uključiti alram" android:title="Uključiti alram"
android:key="alarm_set" /> android:key="alarm_set" />
<EditTextPreference <EditTextPreference
android:selectAllOnFocus="true" android:selectAllOnFocus="true"
android:singleLine="true" android:singleLine="true"

View File

@@ -18,6 +18,12 @@ allprojects {
} }
} }
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }