diff --git a/app/build.gradle b/app/build.gradle
index 9895c17..b14403f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,10 +4,10 @@ android {
compileSdkVersion 28
defaultConfig {
applicationId "de.weseng.wifiweatherstation"
- minSdkVersion 16
+ minSdkVersion 26
targetSdkVersion 28
- versionCode 20190302
- versionName "2019.3.2"
+ versionCode 20190309
+ versionName "2019.3.9"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -22,6 +22,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ implementation 'com.android.support:support-annotations:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b7b63b8..2241dd7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,9 +3,13 @@
xmlns:tools="http://schemas.android.com/tools"
package="de.weseng.wifiweatherstation">
+
+
+
+
-
+
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/de/weseng/wifiweatherstation/HttpHandler.java b/app/src/main/java/de/weseng/wifiweatherstation/HttpHandler.java
new file mode 100644
index 0000000..2c91780
--- /dev/null
+++ b/app/src/main/java/de/weseng/wifiweatherstation/HttpHandler.java
@@ -0,0 +1,63 @@
+package de.weseng.wifiweatherstation;
+
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
+
+public class HttpHandler {
+
+ private static final String TAG = HttpHandler.class.getSimpleName();
+
+ public HttpHandler() {
+ }
+
+ public String makeServiceCall(String reqUrl) {
+ String response = null;
+ try {
+ URL url = new URL(reqUrl);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ // read the response
+ InputStream in = new BufferedInputStream(conn.getInputStream());
+ response = convertStreamToString(in);
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "MalformedURLException: " + e.getMessage());
+ } catch (ProtocolException e) {
+ Log.e(TAG, "ProtocolException: " + e.getMessage());
+ } catch (IOException e) {
+ Log.e(TAG, "IOException: " + e.getMessage());
+ } catch (Exception e) {
+ Log.e(TAG, "Exception: " + e.getMessage());
+ }
+ return response;
+ }
+
+ private String convertStreamToString(InputStream is) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ StringBuilder sb = new StringBuilder();
+
+ String line;
+ try {
+ while ((line = reader.readLine()) != null) {
+ sb.append(line).append('\n');
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/weseng/wifiweatherstation/LoginActivity.java b/app/src/main/java/de/weseng/wifiweatherstation/LoginActivity.java
new file mode 100644
index 0000000..a73f42b
--- /dev/null
+++ b/app/src/main/java/de/weseng/wifiweatherstation/LoginActivity.java
@@ -0,0 +1,363 @@
+package de.weseng.wifiweatherstation;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.support.annotation.NonNull;
+
+import android.app.Activity;
+import android.app.LoaderManager.LoaderCallbacks;
+
+import android.content.CursorLoader;
+import android.content.Loader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.EditorInfo;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.Manifest.permission.READ_CONTACTS;
+import static de.weseng.wifiweatherstation.SettingsActivity.PREFS_NAME;
+
+/**
+ * A login screen that offers login via email/password.
+ */
+public class LoginActivity extends Activity implements LoaderCallbacks {
+
+ /**
+ * Id to identity READ_CONTACTS permission request.
+ */
+ private static final int REQUEST_READ_CONTACTS = 0;
+
+ /**
+ * A dummy authentication store containing known user names and passwords.
+ * TODO: remove after connecting to a real authentication system.
+ */
+ private static final String[] DUMMY_CREDENTIALS = new String[]{
+ "foo@example.com:hello", "bar@example.com:world"
+ };
+ /**
+ * Keep track of the login task to ensure we can cancel it if requested.
+ */
+ private UserLoginTask mAuthTask = null;
+
+ // UI references.
+ private AutoCompleteTextView mEmailView;
+ private EditText mPasswordView;
+ private View mProgressView;
+ private View mLoginFormView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
+ boolean nativeView = settings.getBoolean("nativeView", true);
+
+ if(nativeView){
+ Intent intent = new Intent(this, MainNativeActivity.class);
+ startActivity(intent);
+ } else {
+ Intent intent = new Intent(this, MainActivity.class);
+ startActivity(intent);
+ }
+
+ //
+ // BEGIN Template Login Activity
+ //
+// setContentView(R.layout.activity_login);
+// // Set up the login form.
+// mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
+// populateAutoComplete();
+//
+// mPasswordView = (EditText) findViewById(R.id.password);
+// mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+// @Override
+// public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
+// if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
+// attemptLogin();
+// return true;
+// }
+// return false;
+// }
+// });
+//
+// Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
+// mEmailSignInButton.setOnClickListener(new OnClickListener() {
+// @Override
+// public void onClick(View view) {
+// attemptLogin();
+// }
+// });
+//
+// mLoginFormView = findViewById(R.id.login_form);
+// mProgressView = findViewById(R.id.login_progress);
+ }
+
+ private void populateAutoComplete() {
+ if (!mayRequestContacts()) {
+ return;
+ }
+
+ getLoaderManager().initLoader(0, null, this);
+ }
+
+ private boolean mayRequestContacts() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return true;
+ }
+ if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
+ // TODO: alert the user with a Snackbar/AlertDialog giving them the permission rationale
+ // To use the Snackbar from the design support library, ensure that the activity extends
+ // AppCompatActivity and uses the Theme.AppCompat theme.
+ } else {
+ requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
+ }
+ return false;
+ }
+
+ /**
+ * Callback received when a permissions request has been completed.
+ */
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ if (requestCode == REQUEST_READ_CONTACTS) {
+ if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ populateAutoComplete();
+ }
+ }
+ }
+
+
+ /**
+ * Attempts to sign in or register the account specified by the login form.
+ * If there are form errors (invalid email, missing fields, etc.), the
+ * errors are presented and no actual login attempt is made.
+ */
+ private void attemptLogin() {
+ if (mAuthTask != null) {
+ return;
+ }
+
+ // Reset errors.
+ mEmailView.setError(null);
+ mPasswordView.setError(null);
+
+ // Store values at the time of the login attempt.
+ String email = mEmailView.getText().toString();
+ String password = mPasswordView.getText().toString();
+
+ boolean cancel = false;
+ View focusView = null;
+
+ // Check for a valid password, if the user entered one.
+ if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
+ mPasswordView.setError(getString(R.string.error_invalid_password));
+ focusView = mPasswordView;
+ cancel = true;
+ }
+
+ // Check for a valid email address.
+ if (TextUtils.isEmpty(email)) {
+ mEmailView.setError(getString(R.string.error_field_required));
+ focusView = mEmailView;
+ cancel = true;
+ } else if (!isEmailValid(email)) {
+ mEmailView.setError(getString(R.string.error_invalid_email));
+ focusView = mEmailView;
+ cancel = true;
+ }
+
+ if (cancel) {
+ // There was an error; don't attempt login and focus the first
+ // form field with an error.
+ focusView.requestFocus();
+ } else {
+ // Show a progress spinner, and kick off a background task to
+ // perform the user login attempt.
+ showProgress(true);
+ mAuthTask = new UserLoginTask(email, password);
+ mAuthTask.execute((Void) null);
+ }
+ }
+
+ private boolean isEmailValid(String email) {
+ //TODO: Replace this with your own logic
+ return email.contains("@");
+ }
+
+ private boolean isPasswordValid(String password) {
+ //TODO: Replace this with your own logic
+ return password.length() > 4;
+ }
+
+ /**
+ * Shows the progress UI and hides the login form.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+ private void showProgress(final boolean show) {
+ // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
+ // for very easy animations. If available, use these APIs to fade-in
+ // the progress spinner.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
+
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ mLoginFormView.animate().setDuration(shortAnimTime).alpha(
+ show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ });
+
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mProgressView.animate().setDuration(shortAnimTime).alpha(
+ show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ });
+ } else {
+ // The ViewPropertyAnimator APIs are not available, so simply show
+ // and hide the relevant UI components.
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ @Override
+ public Loader onCreateLoader(int i, Bundle bundle) {
+ return new CursorLoader(this,
+ // Retrieve data rows for the device user's 'profile' contact.
+ Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
+ ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION,
+
+ // Select only email addresses.
+ ContactsContract.Contacts.Data.MIMETYPE +
+ " = ?", new String[]{ContactsContract.CommonDataKinds.Email
+ .CONTENT_ITEM_TYPE},
+
+ // Show primary email addresses first. Note that there won't be
+ // a primary email address if the user hasn't specified one.
+ ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
+ }
+
+ @Override
+ public void onLoadFinished(Loader cursorLoader, Cursor cursor) {
+ List emails = new ArrayList<>();
+ cursor.moveToFirst();
+ while (!cursor.isAfterLast()) {
+ emails.add(cursor.getString(ProfileQuery.ADDRESS));
+ cursor.moveToNext();
+ }
+
+ addEmailsToAutoComplete(emails);
+ }
+
+ @Override
+ public void onLoaderReset(Loader cursorLoader) {
+
+ }
+
+ private void addEmailsToAutoComplete(List emailAddressCollection) {
+ //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
+ ArrayAdapter adapter =
+ new ArrayAdapter<>(LoginActivity.this,
+ android.R.layout.simple_dropdown_item_1line, emailAddressCollection);
+
+ mEmailView.setAdapter(adapter);
+ }
+
+
+ private interface ProfileQuery {
+ String[] PROJECTION = {
+ ContactsContract.CommonDataKinds.Email.ADDRESS,
+ ContactsContract.CommonDataKinds.Email.IS_PRIMARY,
+ };
+
+ int ADDRESS = 0;
+ int IS_PRIMARY = 1;
+ }
+
+ /**
+ * Represents an asynchronous login/registration task used to authenticate
+ * the user.
+ */
+ public class UserLoginTask extends AsyncTask {
+
+ private final String mEmail;
+ private final String mPassword;
+
+ UserLoginTask(String email, String password) {
+ mEmail = email;
+ mPassword = password;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ // TODO: attempt authentication against a network service.
+
+ try {
+ // Simulate network access.
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ return false;
+ }
+
+ for (String credential : DUMMY_CREDENTIALS) {
+ String[] pieces = credential.split(":");
+ if (pieces[0].equals(mEmail)) {
+ // Account exists, return true if the password matches.
+ return pieces[1].equals(mPassword);
+ }
+ }
+
+ // TODO: register the new account here.
+ return true;
+ }
+
+ @Override
+ protected void onPostExecute(final Boolean success) {
+ mAuthTask = null;
+ showProgress(false);
+
+ if (success) {
+ finish();
+ } else {
+ mPasswordView.setError(getString(R.string.error_incorrect_password));
+ mPasswordView.requestFocus();
+ }
+ }
+
+ @Override
+ protected void onCancelled() {
+ mAuthTask = null;
+ showProgress(false);
+ }
+ }
+}
+
diff --git a/app/src/main/java/de/weseng/wifiweatherstation/MainActivity.java b/app/src/main/java/de/weseng/wifiweatherstation/MainActivity.java
index df1eb46..afbc223 100644
--- a/app/src/main/java/de/weseng/wifiweatherstation/MainActivity.java
+++ b/app/src/main/java/de/weseng/wifiweatherstation/MainActivity.java
@@ -2,17 +2,9 @@ package de.weseng.wifiweatherstation;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
-import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Color;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.wifi.SupplicantState;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
@@ -25,13 +17,9 @@ import android.webkit.WebViewClient;
import android.widget.Toast;
import java.io.InputStream;
-import java.util.List;
-
public class MainActivity extends AppCompatActivity {
- public static final String PREFS_NAME = "Settings";
WebView myWebView;
- public static String MESSAGE = "de.weseng.wifiweatherstation.MESSAGE";
@SuppressLint("SetJavaScriptEnabled")
@Override
@@ -62,11 +50,6 @@ public class MainActivity extends AppCompatActivity {
myWebView.setBackgroundColor(Color.TRANSPARENT);
myWebView.setPadding(0, 0, 0, 0);
- SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
- String ssidLocal = "\"" + settings.getString("ssidLocal", getString(R.string.ssid)) + "\"";
-
- MESSAGE = "";
-
myWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
@@ -75,16 +58,19 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onPageFinished(WebView view, String url) {
+ // Dismiss the progress dialog
+ pd.dismiss();
+
// Inject CSS when page is done loading
injectCSS();
- pd.dismiss();
//String webUrl = myWebView.getUrl();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
/* will open a new web page in webview*/
+ // loadUrl needs: AndroidManifest.xml listOfConfigurations = wifiManager.getConfiguredNetworks();
- for (int index = 0; index < listOfConfigurations.size(); index++) {
- WifiConfiguration configuration = listOfConfigurations.get(index);
- if (configuration.networkId == wifiInfo.getNetworkId()) {
- return configuration.SSID;
- }
- }
- return null;
- }
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
@@ -181,7 +138,6 @@ public class MainActivity extends AppCompatActivity {
myWebView.restoreState(savedInstanceState);
}
-
// Inject CSS method: read style.css from assets folder
// Append stylesheet to document head
private void injectCSS() {
@@ -208,9 +164,8 @@ public class MainActivity extends AppCompatActivity {
/** Called when the user taps the Send button */
public void settings() {
Intent intentSettings = new Intent(this, SettingsActivity.class);
- intentSettings.putExtra(MESSAGE, MESSAGE);
+ //intentSettings.putExtra(MESSAGE, MESSAGE);
startActivity(intentSettings);
}
-
}
diff --git a/app/src/main/java/de/weseng/wifiweatherstation/MainNativeActivity.java b/app/src/main/java/de/weseng/wifiweatherstation/MainNativeActivity.java
new file mode 100644
index 0000000..b9d7519
--- /dev/null
+++ b/app/src/main/java/de/weseng/wifiweatherstation/MainNativeActivity.java
@@ -0,0 +1,310 @@
+package de.weseng.wifiweatherstation;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.os.AsyncTask;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static de.weseng.wifiweatherstation.SettingsActivity.PREFS_NAME;
+
+public class MainNativeActivity extends AppCompatActivity {
+ private int pDialogLockCount = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main_native);
+
+ SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
+ String urlLocal = settings.getString("urlLocal", getString(R.string.url_local));
+ String urlGlobal = settings.getString("urlGlobal", getString(R.string.url_global));
+
+ if (savedInstanceState == null) {
+ String urlPre = "";
+ if (SettingsActivity.isLocal(getApplicationContext())) {
+ //Toast.makeText(getApplicationContext(), "intern", Toast.LENGTH_LONG).show();
+ if (urlLocal != null && urlLocal.length() > 0)
+ urlPre = urlLocal.substring(urlLocal.length() - 1).equals("/") ? urlLocal : urlLocal + "/";
+ } else {
+ //Toast.makeText(getApplicationContext(), "extern", Toast.LENGTH_LONG).show();
+ if (urlGlobal != null && urlGlobal.length() > 0)
+ urlPre = urlGlobal.substring(urlGlobal.length() - 1).equals("/") ? urlGlobal : urlGlobal + "/";
+ }
+ //Toast.makeText(getApplicationContext(), urlPre, Toast.LENGTH_LONG).show();
+ new GetData(R.id.textViewTemperatureValue1, R.id.textViewHumidityValue1).execute(
+ urlPre + "api.php?host=192.168.1.71&last");
+ new GetData(R.id.textViewTemperatureValue2, R.id.textViewHumidityValue2).execute(
+ urlPre + "api.php?host=192.168.1.72&last");
+ new GetData(R.id.textViewTemperatureValue3, R.id.textViewHumidityValue3).execute(
+ urlPre + "api.php?host=192.168.1.73&last");
+
+ }
+ }
+
+ /**
+ * Async task class to get json by making HTTP call
+ */
+ private class GetData extends AsyncTask {
+ String TAG = getClass().getSimpleName();
+ private ProgressBar pBar;
+
+ ArrayList> dataList = new ArrayList<>();
+
+ int v1, v2;
+
+ GetData(int v1, int v2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ pDialogLockCount += 1;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ // Showing progress bar
+// if (pBar == null) {
+// pBar= new ProgressBar(MainNativeActivity.this);
+// }
+ pBar = findViewById(R.id.progressBar);
+ if (pBar.getVisibility() == View.INVISIBLE) {
+ pBar.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ protected Void doInBackground(String... params) {
+ // URL to get contacts JSON
+ String url = params[0];
+
+ HttpHandler sh = new HttpHandler();
+
+ // Making a request to url and getting response
+ String jsonStr = sh.makeServiceCall(url);
+
+ Log.d(TAG, "Response from url: " + jsonStr);
+
+ if (jsonStr != null) {
+ try {
+ //JSONObject jsonObj = new JSONObject(jsonStr);
+
+ // Getting JSON Array node
+ //JSONArray data = jsonObj.getJSONArray("contacts");
+
+ JSONArray data = new JSONArray(jsonStr);
+
+ // looping through all data
+ for (int i = 0; i < data.length(); i++) {
+ JSONObject c = data.getJSONObject(i);
+
+ String dateandtime = c.getString("dateandtime");
+ String sensor = c.getString("sensor");
+ String temperature = c.getString("temperature");
+ String humidity = c.getString("humidity");
+
+ // tmp hash map for single datum
+ HashMap datum = new HashMap<>();
+
+ // adding each child node to HashMap key => value
+ datum.put("dateandtime", dateandtime);
+ datum.put("sensor", sensor);
+ datum.put("temperature", temperature);
+ datum.put("humidity", humidity);
+
+ // adding datum to data list
+ dataList.add(datum);
+ }
+ } catch (final JSONException e) {
+ Log.e(TAG, "Json parsing error: " + e.getMessage());
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(getApplicationContext(),
+ "Json parsing error: " + e.getMessage(),
+ Toast.LENGTH_LONG)
+ .show();
+ }
+ });
+
+ }
+ } else {
+ Log.e(TAG, "Couldn't get json from server.");
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(getApplicationContext(),
+ "Couldn't get json from server. Check LogCat for possible errors!",
+ Toast.LENGTH_LONG)
+ .show();
+ }
+ });
+
+ }
+
+ return null;
+ }
+
+ int interpolate(int pBegin, int pEnd, int pStep, int pMax) {
+ if (pBegin < pEnd) {
+ return ((pEnd - pBegin) * (pStep / pMax)) + pBegin;
+ } else {
+ return ((pBegin - pEnd) * (1 - (pStep / pMax))) + pEnd;
+ }
+ }
+
+ int interpolateColor(int theColorBegin, int theColorEnd,
+ int theNumStep, int theNumSteps) {
+ int theR0 = (theColorBegin & 0xff0000) >> 16;
+ int theG0 = (theColorBegin & 0x00ff00) >> 8;
+ int theB0 = (theColorBegin & 0x0000ff);
+ //int theB0 = (theColorBegin & 0x0000ff) >> 0;
+
+ int theR1 = (theColorEnd & 0xff0000) >> 16;
+ int theG1 = (theColorEnd & 0x00ff00) >> 8;
+ int theB1 = (theColorEnd & 0x0000ff);
+ //int theB1 = (theColorEnd & 0x0000ff) >> 0;
+
+ int theR = interpolate(theR0, theR1, theNumStep, theNumSteps);
+ int theG = interpolate(theG0, theG1, theNumStep, theNumSteps);
+ int theB = interpolate(theB0, theB1, theNumStep, theNumSteps);
+
+ return (((theR << 8) | theG) << 8) | theB;
+ }
+
+ Color valueToColor(float value, float lowMin, float lowMax, float highMin, float highMax,
+ Color below, Color ideal, Color above) {
+ return Color.valueOf(Color.parseColor(String.format("#%06X",
+ valueToColorRGB(value, lowMin, lowMax, highMin, highMax, below, ideal, above))));
+ }
+
+ int valueToColorRGB(float value, float lowMin, float lowMax, float highMin, float highMax,
+ Color below, Color ideal, Color above) {
+ int bel = Integer.parseInt(String.format("%06X", (0xFFFFFF & below.toArgb())), 16);
+ int ide = Integer.parseInt(String.format("%06X", (0xFFFFFF & ideal.toArgb())), 16);
+ int abo = Integer.parseInt(String.format("%06X", (0xFFFFFF & above.toArgb())), 16);
+
+ return valueToColorRGB(value, lowMin, lowMax, highMin, highMax, bel, ide, abo);
+ }
+
+ int valueToColorRGB(float value, float lowMin, float lowMax, float highMin, float highMax,
+ int below, int ideal, int above) {
+ /*
+ * lowMin < lowMax < highMin < highMax
+ *
+ * Example use for temperatures with color blue for too cold (below), green for ideal
+ * and red for too warm (above) temperatures:
+ * - Below lowMin the color is blue
+ * - Between lowMin and lowMax is color is linear interpolated between blue and green
+ * - Between lowMax and highMin the color is green
+ * - Between highMin and highMax the color is linear interpolated between green and red
+ * - Above highMax the color is red
+ */
+ int result = 0xFFFFFF; // white
+ int theNumSteps = 100;
+ int theColorBegin, theColorEnd, ratio;
+
+ if (value <= highMin && value >= lowMax)
+ result = ideal;
+ else if (value > highMax)
+ result = above;
+ else if (value > highMin) {
+ theColorBegin = ideal;
+ theColorEnd = above;
+ ratio = (int) ((value - highMin) / (highMax - highMin) * 100);
+ result = interpolateColor(theColorBegin, theColorEnd, ratio, theNumSteps);
+ } else if (value < lowMin)
+ result = below;
+ else if (value < lowMax) {
+ theColorBegin = ideal;
+ theColorEnd = below;
+ ratio = (int) ((lowMax - value) / (lowMax - lowMin) * 100);
+ result = interpolateColor(theColorBegin, theColorEnd, ratio, theNumSteps);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ pDialogLockCount -= 1;
+ // Dismiss the progress bar
+ if (pBar.getVisibility() == View.VISIBLE && pDialogLockCount == 0) {
+ pBar.setVisibility(View.GONE);
+ }
+ /*
+ * Updating parsed JSON data into Views
+ * */
+
+ int n = dataList.size();
+ if (n > 0) {
+ HashMap hm = dataList.get(n - 1);
+
+ float temp = Float.parseFloat(hm.get("temperature"));
+ String temperature = String.format("%.1f", temp);
+
+ float humi = Float.parseFloat(hm.get("humidity"));
+ String humidity = String.format("%.1f", humi);
+
+ Color green = Color.valueOf(0xff00ff00);
+ Color red = Color.valueOf(0xffd1655d);
+ Color blue = Color.valueOf(Color.rgb(113, 157, 195));
+
+ Color textColor;
+
+ textColor = valueToColor(temp, 17, 19, 23, 25, blue, green, red);
+ TextView tv1 = findViewById(v1);
+ tv1.setText(temperature);
+ tv1.setTextColor(textColor.toArgb());
+
+ textColor = valueToColor(humi, 25, 40, 60, 75, red, green, blue);
+ TextView tv2 = findViewById(v2);
+ tv2.setText(humidity);
+ tv2.setTextColor(textColor.toArgb());
+ }
+ }
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ switch (item.getItemId()) {
+ case R.id.settings:
+ settings();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ /**
+ * Called when the user taps the Send button
+ */
+ public void settings() {
+ Intent intentSettings = new Intent(this, SettingsActivity.class);
+ //intentSettings.putExtra(MESSAGE, MESSAGE);
+ startActivity(intentSettings);
+ }
+}
diff --git a/app/src/main/java/de/weseng/wifiweatherstation/SettingsActivity.java b/app/src/main/java/de/weseng/wifiweatherstation/SettingsActivity.java
index 9d49519..fa31a30 100644
--- a/app/src/main/java/de/weseng/wifiweatherstation/SettingsActivity.java
+++ b/app/src/main/java/de/weseng/wifiweatherstation/SettingsActivity.java
@@ -1,16 +1,29 @@
package de.weseng.wifiweatherstation;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
+import android.widget.CompoundButton;
import android.widget.EditText;
+import android.widget.Switch;
import android.widget.TextView;
+import java.util.List;
+
public class SettingsActivity extends AppCompatActivity {
public static final String PREFS_NAME = "Settings";
+ public static String MESSAGE;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -19,18 +32,36 @@ public class SettingsActivity extends AppCompatActivity {
// Get the Intent that started this activity and extract the string
Intent intent = getIntent();
- String message = intent.getStringExtra(MainActivity.MESSAGE);
-
+ String message = intent.getStringExtra(MESSAGE);
+ if (message == null) {
+ message = "";
+ }
+ message = getString(R.string.message) + message;
+ if (isLocal(getApplicationContext())) {
+ message += "\n" + getString(R.string.message_connection_internal);
+ } else {
+ message += "\n" + getString(R.string.message_connection_external);
+ }
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
String ssidLocal = settings.getString("ssidLocal", getString(R.string.ssid));
String urlLocal = settings.getString("urlLocal", getString(R.string.url_local));
String urlGlobal = settings.getString("urlGlobal", getString(R.string.url_global));
+ boolean nativeView = settings.getBoolean("nativeView", true);
//message = message.concat("\nSSIDLocal: " + ssidLocal);
// Capture the layout's TextView and set the string as its text
TextView textView = findViewById(R.id.textView);
textView.setText(message);
+ final Switch switchView = findViewById(R.id.switchView);
+ switchView.setChecked(nativeView);
+ switchView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ save("nativeView", isChecked);
+ }
+ });
+
final EditText editTextSsid = findViewById(R.id.editTextSsidLocal);
editTextSsid.setText(ssidLocal);
editTextSsid.setOnKeyListener(new View.OnKeyListener() {
@@ -94,15 +125,16 @@ public class SettingsActivity extends AppCompatActivity {
}
@Override
- protected void onStop(){
+ protected void onStop() {
super.onStop();
save_all();
}
public void save_all() {
- save("ssidLocal", ((EditText)findViewById(R.id.editTextSsidLocal)).getText().toString());
- save("urlLocal", ((EditText)findViewById(R.id.editTextUrlLocal)).getText().toString());
- save("urlGlobal", ((EditText)findViewById(R.id.editTextUrlGlobal)).getText().toString());
+ save("ssidLocal", ((EditText) findViewById(R.id.editTextSsidLocal)).getText().toString());
+ save("urlLocal", ((EditText) findViewById(R.id.editTextUrlLocal)).getText().toString());
+ save("urlGlobal", ((EditText) findViewById(R.id.editTextUrlGlobal)).getText().toString());
+ save("nativeView", ((Switch) findViewById(R.id.switchView)).isChecked());
}
public void save(String key, String value) {
@@ -115,4 +147,46 @@ public class SettingsActivity extends AppCompatActivity {
// Commit the edits!
editor.apply();
}
+
+ public void save(String key, Boolean value) {
+ // We need an Editor object to make preference changes.
+ // All objects are from android.context.Context
+ SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putBoolean(key, value);
+
+ // Commit the edits!
+ editor.apply();
+ }
+
+ public static String findSSIDForWifiInfo(WifiManager wifiManager, WifiInfo wifiInfo) {
+ List listOfConfigurations = wifiManager.getConfiguredNetworks();
+ for (int index = 0; index < listOfConfigurations.size(); index++) {
+ WifiConfiguration configuration = listOfConfigurations.get(index);
+ if (configuration.networkId == wifiInfo.getNetworkId()) {
+ return configuration.SSID;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isLocal(@NonNull Context context) {
+
+ SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
+ String ssidLocal = "\"" + settings.getString("ssidLocal", context.getString(R.string.ssid)) + "\"";
+
+ ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ //NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ NetworkInfo mWifi = connManager.getNetworkInfo(connManager.getActiveNetwork());
+ if (mWifi.isConnected()) {
+ WifiManager wifiMgr = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
+ if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
+ String ssid = findSSIDForWifiInfo(wifiMgr, wifiInfo);
+ if (ssid != null)
+ return ssid.equals(ssidLocal);
+ }
+ }
+ return false;
+ }
}
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..de31d62
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main_native.xml b/app/src/main/res/layout/activity_main_native.xml
new file mode 100644
index 0000000..40cd2ef
--- /dev/null
+++ b/app/src/main/res/layout/activity_main_native.xml
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 5b8850b..19faf81 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -10,21 +10,35 @@
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:text=""
+ android:layout_marginTop="@dimen/activity_vertical_margin"
+ android:text="@string/message"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
+
+
+ app:layout_constraintTop_toBottomOf="@+id/switchView">
WiFi-Wetter-Station
- Einstellungen
Bitte warten, die Ansicht wird geladen…
+
+ Temperatur
+ Feuchtigkeit
+
+ Einstellungen
+ Verbindung: intern
+ Verbindung: extern
+ Web oder native Ansicht
Lokale URL
Globale URL
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..c591852
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,7 @@
+
+
+ 16dp
+ 16dp
+ 8dp
+ 8dp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 527f9d7..5c1e2f4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,11 +1,33 @@
WiFi Weather Station
- Settings
Please wait, the view is loading…
+
+ Temperature
+ Humidity
+ _._
+
+ Settings
+ de.weseng.wifiweatherstation.MESSAGE
+ connection: internal
+ connection: external
+ Web or native view
NETGEAR26-5G-2
- http://192.168.1.5/site/wifi-weather-station/
- http://inetsrv.no-ip.org/site/wifi-weather-station/
SSID
+ http://192.168.1.5/site/wifi-weather-station/
Local URL
+ http://inetsrv.no-ip.org/site/wifi-weather-station/
Global URL
+
+ Sign in
+ Email
+ Password (optional)
+ Sign in or register
+ Sign in
+ This email address is invalid
+ This password is too short
+ This password is incorrect
+ This field is required
+ "Contacts permissions are needed for providing email
+ completions."
+
diff --git a/build.gradle b/build.gradle
index 3c23acc..e11a5b3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.1'
+ classpath 'com.android.tools.build:gradle:3.3.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files