diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6393623..a5caf63 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,11 @@ + + + diff --git a/app/src/main/java/com/morristaedt/mirror/MirrorActivity.java b/app/src/main/java/com/morristaedt/mirror/MirrorActivity.java index a8af810..bd1597d 100644 --- a/app/src/main/java/com/morristaedt/mirror/MirrorActivity.java +++ b/app/src/main/java/com/morristaedt/mirror/MirrorActivity.java @@ -134,7 +134,7 @@ private void setViewState() { mWaterPlants.setVisibility(ChoresModule.waterPlantsToday() ? View.VISIBLE : View.GONE); mGroceryList.setVisibility(ChoresModule.makeGroceryListToday() ? View.VISIBLE : View.GONE); - ForecastModule.getHourlyForecast(getResources(), 40.681045, -73.9931749, mForecastListener); + ForecastModule.getHourlyForecast(getSharedPreferences(MirrorApplication.SHARED_PREF_NAME, MODE_PRIVATE), 40.681045, -73.9931749, mForecastListener); XKCDModule.getXKCDForToday(mXKCDListener); if (WeekUtil.isWeekday() && WeekUtil.afterFive()) { diff --git a/app/src/main/java/com/morristaedt/mirror/MirrorApplication.java b/app/src/main/java/com/morristaedt/mirror/MirrorApplication.java index 9f60ce2..ad7e9e8 100644 --- a/app/src/main/java/com/morristaedt/mirror/MirrorApplication.java +++ b/app/src/main/java/com/morristaedt/mirror/MirrorApplication.java @@ -8,6 +8,7 @@ import android.os.SystemClock; import com.morristaedt.mirror.receiver.AlarmReceiver; +import com.morristaedt.mirror.settings.ServerService; /** * Created by HannahMitt on 8/22/15. @@ -15,6 +16,7 @@ public class MirrorApplication extends Application { private static final long MINUTES_10 = 10 * 60 * 1000; + public static final String SHARED_PREF_NAME = "HomeMirrorPrefs"; @Override public void onCreate() { @@ -25,5 +27,8 @@ public void onCreate() { PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0); alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + MINUTES_10, MINUTES_10, alarmIntent); + + Intent serverIntent = new Intent(this, ServerService.class); + startService(serverIntent); } } diff --git a/app/src/main/java/com/morristaedt/mirror/modules/ForecastModule.java b/app/src/main/java/com/morristaedt/mirror/modules/ForecastModule.java index c909cdc..def0b47 100644 --- a/app/src/main/java/com/morristaedt/mirror/modules/ForecastModule.java +++ b/app/src/main/java/com/morristaedt/mirror/modules/ForecastModule.java @@ -1,5 +1,6 @@ package com.morristaedt.mirror.modules; +import android.content.SharedPreferences; import android.content.res.Resources; import android.os.AsyncTask; import android.util.Log; @@ -27,7 +28,7 @@ public interface ForecastListener { void onShouldBike(boolean showToday, boolean shouldBike); } - public static void getHourlyForecast(final Resources resources, final double lat, final double lon, final ForecastListener listener) { + public static void getHourlyForecast(final SharedPreferences sharedPreferences, final double lat, final double lon, final ForecastListener listener) { new AsyncTask() { @Override @@ -47,7 +48,13 @@ public Throwable handleError(RetrofitError cause) { String excludes = "minutely,daily,flags"; String units = "si"; Log.d("mirror", "backgrounddd"); - return service.getHourlyForecast(resources.getString(R.string.dark_sky_api_key), lat, lon, excludes, units); + String api_key = sharedPreferences.getString("dark_sky_api_key", "not_a_valid_key"); + if (!api_key.equals("not_a_valid_key")) { + return service.getHourlyForecast(api_key, lat, lon, excludes, units); + } else { + // null is well handled in onPostExecute + return null; + } } @Override diff --git a/app/src/main/java/com/morristaedt/mirror/settings/ServerService.java b/app/src/main/java/com/morristaedt/mirror/settings/ServerService.java new file mode 100644 index 0000000..afb216e --- /dev/null +++ b/app/src/main/java/com/morristaedt/mirror/settings/ServerService.java @@ -0,0 +1,31 @@ +package com.morristaedt.mirror.settings; + +import android.app.Service; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.IBinder; + +import com.morristaedt.mirror.MirrorApplication; + +public class ServerService extends Service { + private SettingsWebServer server; + + @Override + public void onCreate() { + super.onCreate(); + server = new SettingsWebServer(this); + server.startServer(); + } + + @Override + public void onDestroy() { + server.stopServer(); + super.onDestroy(); + } + + @Override + public IBinder onBind(Intent intent) { + // TODO: Return the communication channel to the service. + throw new UnsupportedOperationException("Not yet implemented"); + } +} diff --git a/app/src/main/java/com/morristaedt/mirror/settings/SettingsPageHandler.java b/app/src/main/java/com/morristaedt/mirror/settings/SettingsPageHandler.java new file mode 100644 index 0000000..dc3f3e3 --- /dev/null +++ b/app/src/main/java/com/morristaedt/mirror/settings/SettingsPageHandler.java @@ -0,0 +1,43 @@ +package com.morristaedt.mirror.settings; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.entity.ContentProducer; +import org.apache.http.entity.EntityTemplate; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpRequestHandler; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +/** + * Created by alex on 12/09/15. + */ +public class SettingsPageHandler implements HttpRequestHandler { + private static final String PAGE_HTML = "HomeMirror Settings" + + "" + + "
" + + "

Forecast.io API Key

" + + "
\n" + + "\n" + + "
" + + ""; + + + @Override + public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException { + HttpEntity entity = new EntityTemplate(new ContentProducer() { + public void writeTo(final OutputStream outstream) throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); + writer.write(PAGE_HTML); + writer.flush(); + } + }); + httpResponse.setHeader("Content-Type", "text/html"); + httpResponse.setEntity(entity); + + } +} diff --git a/app/src/main/java/com/morristaedt/mirror/settings/SettingsSaveHandler.java b/app/src/main/java/com/morristaedt/mirror/settings/SettingsSaveHandler.java new file mode 100644 index 0000000..b6fc331 --- /dev/null +++ b/app/src/main/java/com/morristaedt/mirror/settings/SettingsSaveHandler.java @@ -0,0 +1,66 @@ +package com.morristaedt.mirror.settings; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.util.Log; + +import com.morristaedt.mirror.MirrorActivity; +import com.morristaedt.mirror.MirrorApplication; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpRequestHandler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Created by alex on 13/09/15. + */ +public class SettingsSaveHandler implements HttpRequestHandler { + + public static final String DARK_SKY_API_KEY = "dark_sky_api_key"; + private Context context; + + public SettingsSaveHandler(Context context) { + this.context = context; + } + + @Override + public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException { + SharedPreferences sharedPreferences = context.getSharedPreferences(MirrorApplication.SHARED_PREF_NAME, Context.MODE_PRIVATE); + HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) httpRequest; + HttpEntity entity = request.getEntity(); + BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent())); + String out = reader.readLine(); + while (out != null && !out.equals("")) { + String[] splitOutput = out.split("="); + if (splitOutput.length == 2) { + if (splitOutput[0].equals(DARK_SKY_API_KEY)) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(DARK_SKY_API_KEY, splitOutput[1]); + editor.apply(); + } + } + + //Get the next line from the reader, will be null if empty and loop will terminate + out = reader.readLine(); + } + + // Return settings page again + new SettingsPageHandler().handle(httpRequest, httpResponse, httpContext); + + // Force refresh of main screen + Intent mainActivityIntent = new Intent(context, MirrorActivity.class); + mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(mainActivityIntent); + + } +} diff --git a/app/src/main/java/com/morristaedt/mirror/settings/SettingsWebServer.java b/app/src/main/java/com/morristaedt/mirror/settings/SettingsWebServer.java new file mode 100644 index 0000000..2bbab2b --- /dev/null +++ b/app/src/main/java/com/morristaedt/mirror/settings/SettingsWebServer.java @@ -0,0 +1,102 @@ +package com.morristaedt.mirror.settings; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +import org.apache.http.HttpException; +import org.apache.http.impl.DefaultConnectionReuseStrategy; +import org.apache.http.impl.DefaultHttpResponseFactory; +import org.apache.http.impl.DefaultHttpServerConnection; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.BasicHttpProcessor; +import org.apache.http.protocol.HttpRequestHandlerRegistry; +import org.apache.http.protocol.HttpService; +import org.apache.http.protocol.ResponseConnControl; +import org.apache.http.protocol.ResponseContent; +import org.apache.http.protocol.ResponseDate; +import org.apache.http.protocol.ResponseServer; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * Created by alex on 12/09/15. + */ +public class SettingsWebServer { + public static final int PORT = 8080; + + private boolean serverIsRunning = false; + private BasicHttpProcessor basicHttpProcessor; + private BasicHttpContext basicHttpContext; + private HttpService httpService ; + private HttpRequestHandlerRegistry handlerRegistry; + private ServerSocket serverSocket; + + private String settingsPagePath = "/"; + private String settingsSavePath = "/set_settings"; + + public SettingsWebServer(Context context) { + Log.d("SettingsWebServer", "Creating web server"); + basicHttpProcessor = new BasicHttpProcessor(); + basicHttpContext = new BasicHttpContext(); + + basicHttpProcessor.addInterceptor(new ResponseDate()); + basicHttpProcessor.addInterceptor(new ResponseServer()); + basicHttpProcessor.addInterceptor(new ResponseContent()); + basicHttpProcessor.addInterceptor(new ResponseConnControl()); + + httpService = new HttpService(basicHttpProcessor, new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory()); + + handlerRegistry = new HttpRequestHandlerRegistry(); + handlerRegistry.register(settingsPagePath, new SettingsPageHandler()); + handlerRegistry.register(settingsSavePath, new SettingsSaveHandler(context)); + + httpService.setHandlerResolver(handlerRegistry); + } + + public void handleRequests() { + try { + serverSocket = new ServerSocket(PORT); + serverSocket.setReuseAddress(true); + + while (serverIsRunning) { + final Socket clientSocket = serverSocket.accept(); + DefaultHttpServerConnection serverConnection = new DefaultHttpServerConnection(); + serverConnection.bind(clientSocket, new BasicHttpParams()); + httpService.handleRequest(serverConnection, basicHttpContext); + serverConnection.shutdown(); + } + + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } catch (HttpException e) { + e.printStackTrace(); + } + serverIsRunning = false; + } + + public synchronized void startServer() { + serverIsRunning = true; + new Thread(new Runnable() { + @Override + public void run() { + handleRequests(); + } + }).start(); + } + + public synchronized void stopServer() { + serverIsRunning = false; + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +}