Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e060f8505f | |||
| 84494ab68d | |||
| 844a78b041 | |||
| d754f67c77 | |||
| 37b43053a8 | |||
| 9b9e3a0d73 | |||
| 2b7dca8e2f | |||
| c2a14c5b66 | |||
| f44f77a493 |
12
.idea/dictionaries/weatherstation.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="weatherstation">
|
||||
<words>
|
||||
<w>appid</w>
|
||||
<w>dateandtime</w>
|
||||
<w>openweathermap</w>
|
||||
<w>ssid</w>
|
||||
<w>weseng</w>
|
||||
<w>wifiweatherstation</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
35
.idea/misc.xml
generated
@@ -1,5 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
||||
<option name="myDefaultNotNull" value="androidx.annotation.RecentlyNonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="10">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
|
||||
@@ -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 20190331
|
||||
versionName "2019.3.31"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
@@ -18,12 +18,18 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
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'
|
||||
implementation 'com.android.support:design:28.0.0'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha'
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="de.weseng.wifiweatherstation">
|
||||
|
||||
<!-- To auto-complete the email text field in the login form with the user's emails -->
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<!-- <uses-permission android:name="android.permission.READ_PROFILE" /> -->
|
||||
<!-- <uses-permission android:name="android.permission.READ_CONTACTS" /> --> <!-- for email completions -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- or ACCESS_FINE_LOCATION for SSID -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- or ACCESS_FINE_LOCATION for SSID -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
@@ -17,19 +20,36 @@
|
||||
android:theme="@style/DarkTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
|
||||
<activity android:name=".MainActivity">
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:label="@string/app_name"
|
||||
android:noHistory="true"> <!-- android:label="@string/title_activity_login" -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".SettingsActivity"
|
||||
android:parentActivityName=".MainActivity">
|
||||
<!-- The meta-data tag is required if you support API level 15 and lower -->
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity" />
|
||||
<activity
|
||||
android:name=".MainNativeActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".DetailActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,79 @@
|
||||
package de.weseng.wifiweatherstation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class CenteredImageSpan extends ImageSpan {
|
||||
private WeakReference<Drawable> mDrawableRef;
|
||||
|
||||
CenteredImageSpan(Context context, final int drawableRes) {
|
||||
super(context, drawableRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(@NonNull Paint paint, CharSequence text,
|
||||
int start, int end,
|
||||
Paint.FontMetricsInt fm) {
|
||||
Drawable d = getCachedDrawable();
|
||||
Rect rect = d.getBounds();
|
||||
|
||||
float drawableHeight = rect.height();
|
||||
if (fm != null) {
|
||||
Paint.FontMetricsInt pfm = paint.getFontMetricsInt();
|
||||
float fontHeight = pfm.descent - pfm.ascent;
|
||||
int paintOversizeHalf = (int) (drawableHeight/2-fontHeight*1.25);
|
||||
|
||||
// keep it the same as paint's fm plus some space
|
||||
fm.ascent = pfm.ascent - paintOversizeHalf;
|
||||
fm.descent = pfm.descent + paintOversizeHalf;
|
||||
fm.top = pfm.top;
|
||||
fm.bottom = pfm.bottom;
|
||||
}
|
||||
|
||||
return rect.right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas, CharSequence text,
|
||||
int start, int end, float x,
|
||||
int top, int y, int bottom, @NonNull Paint paint) {
|
||||
Drawable b = getCachedDrawable();
|
||||
canvas.save();
|
||||
|
||||
int drawableHeight = b.getIntrinsicHeight();
|
||||
int fontAscent = paint.getFontMetricsInt().ascent;
|
||||
int fontDescent = paint.getFontMetricsInt().descent;
|
||||
|
||||
Paint.FontMetricsInt pfm = paint.getFontMetricsInt();
|
||||
int fontHeightRelativeCorrection = (int) ((pfm.descent - pfm.ascent)/5.0);
|
||||
|
||||
int transY = bottom - b.getBounds().bottom + // align bottom to bottom
|
||||
(drawableHeight - fontDescent + fontAscent) / 2 - fontHeightRelativeCorrection; // align center to center
|
||||
canvas.translate(x, transY);
|
||||
b.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
// Redefined locally because it is a private member from DynamicDrawableSpan
|
||||
private Drawable getCachedDrawable() {
|
||||
WeakReference<Drawable> wr = mDrawableRef;
|
||||
Drawable d = null;
|
||||
|
||||
if (wr != null)
|
||||
d = wr.get();
|
||||
|
||||
if (d == null) {
|
||||
d = getDrawable();
|
||||
mDrawableRef = new WeakReference<>(d);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
package de.weseng.wifiweatherstation;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.Legend;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.formatter.IFillFormatter;
|
||||
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DetailActivity extends AppCompatActivity {
|
||||
private final String TAG = getClass().getSimpleName();
|
||||
private LineChart chart;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_detail);
|
||||
|
||||
Intent intent = getIntent();
|
||||
ArrayList<String> dataList1 = intent.getStringArrayListExtra("temperature");
|
||||
ArrayList<String> dataList2 = intent.getStringArrayListExtra("humidity");
|
||||
Log.d(TAG, "dataList1: " + dataList1);
|
||||
Log.d(TAG, "dataList2: " + dataList2);
|
||||
|
||||
chart = findViewById(R.id.chart1);
|
||||
|
||||
// background color for the whole view
|
||||
//chart.setBackgroundColor(Color.TRANSPARENT);
|
||||
|
||||
// background color for the chart area
|
||||
//chart.setDrawGridBackground(true);
|
||||
//chart.setGridBackgroundColor(Color.TRANSPARENT);
|
||||
|
||||
// disable description text
|
||||
chart.getDescription().setEnabled(false);
|
||||
|
||||
// enable touch gestures, default true
|
||||
//chart.setTouchEnabled(false);
|
||||
|
||||
// enable dragging (default true) and scaling (default true)
|
||||
//chart.setDragEnabled(false);
|
||||
//chart.setScaleEnabled(false);
|
||||
//chart.setScaleXEnabled(false);
|
||||
chart.setScaleYEnabled(false);
|
||||
|
||||
// force pinch zoom along both axis (default false)
|
||||
//chart.setPinchZoom(true);
|
||||
|
||||
// animates the rendering of the chart
|
||||
chart.animateX(1000);
|
||||
//chart.animateY(1500);
|
||||
//chart.animateXY(1500, 1500);
|
||||
|
||||
{ // x axis
|
||||
|
||||
XAxis xAxis = chart.getXAxis();
|
||||
//xAxis.setTypeface(tfLight);
|
||||
//xAxis.setTextSize(11f);
|
||||
xAxis.setDrawLabels(false);
|
||||
//xAxis.setTextColor(Color.LTGRAY);
|
||||
xAxis.setDrawGridLines(false);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
}
|
||||
|
||||
{ // y axis
|
||||
|
||||
//YAxis yAxis = chart.getAxisLeft();
|
||||
|
||||
// disable dual axis (only use LEFT axis)
|
||||
//chart.getAxisRight().setEnabled(false);
|
||||
|
||||
//leftAxis.setTypeface(tfLight);
|
||||
//yAxis.setTextColor(ColorTemplate.getHoloBlue());
|
||||
//yAxis.setAxisMinimum(12f);
|
||||
//yAxis.setAxisMaximum(30f);
|
||||
//yAxis.setDrawGridLines(true);
|
||||
|
||||
// horizontal grid lines
|
||||
//yAxis.enableGridDashedLine(10f, 10f, 0f);
|
||||
|
||||
//yAxis.setGranularityEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
{ // y axis left
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
leftAxis.setTextColor(MainNativeActivity.red.toArgb());
|
||||
leftAxis.setAxisMinimum(12);
|
||||
leftAxis.setAxisMaximum(30);
|
||||
leftAxis.setDrawGridLines(true);
|
||||
leftAxis.setGranularityEnabled(true);
|
||||
}
|
||||
|
||||
{ // y axis right
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
rightAxis.setTextColor(ColorTemplate.getHoloBlue());
|
||||
rightAxis.setAxisMinimum(20);
|
||||
rightAxis.setAxisMaximum(80);
|
||||
//rightAxis.setDrawGridLines(false);
|
||||
//rightAxis.setDrawZeroLine(false);
|
||||
//rightAxis.setGranularityEnabled(false);
|
||||
}
|
||||
|
||||
setData(dataList1, getString(R.string.temperature), dataList2, getString(R.string.humidity));
|
||||
|
||||
{ // ### Legend ###
|
||||
|
||||
// get the legend (only possible after setting data)
|
||||
Legend l = chart.getLegend();
|
||||
|
||||
// draw legend entries as lines, default square
|
||||
l.setForm(Legend.LegendForm.LINE);
|
||||
|
||||
l.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
//l.setTextSize(11f);
|
||||
l.setTextColor(Color.LTGRAY);
|
||||
|
||||
// position, default: bottom left
|
||||
//l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
|
||||
//l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
|
||||
|
||||
// default horizontal
|
||||
//l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
|
||||
|
||||
// default false
|
||||
//l.setDrawInside(true);
|
||||
|
||||
//l.setYOffset(11f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setData(ArrayList<String> dataList1, String label1,
|
||||
ArrayList<String> dataList2, String label2) {
|
||||
int n;
|
||||
|
||||
n = dataList1.size();
|
||||
ArrayList<Entry> values1 = new ArrayList<>();
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
float val = Float.parseFloat(dataList1.get(i));
|
||||
values1.add(new Entry(i, val));
|
||||
}
|
||||
}
|
||||
|
||||
n = dataList2.size();
|
||||
ArrayList<Entry> values2 = new ArrayList<>();
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
float val = Float.parseFloat(dataList2.get(i));
|
||||
values2.add(new Entry(i, val));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create a DataSet and give it a type
|
||||
LineDataSet set1 = new LineDataSet(values1, label1);
|
||||
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||
|
||||
{ // ### Lines ###
|
||||
|
||||
//set1.setColor(Color.BLACK);
|
||||
set1.setColor(MainNativeActivity.red.toArgb());
|
||||
//set1.setColor(ColorTemplate.getHoloBlue());
|
||||
|
||||
// line thickness (min = 0.2f, max = 10f, default 1f)
|
||||
//set1.setLineWidth(1f);
|
||||
|
||||
// draw dashed line, see also legend
|
||||
//set1.enableDashedLine(10f, 5f, 0f);
|
||||
|
||||
// set interpolation
|
||||
//set1.setMode(LineDataSet.Mode.STEPPED);
|
||||
//set1.setMode(LineDataSet.Mode.LINEAR);
|
||||
//set1.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
||||
//set1.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);
|
||||
}
|
||||
|
||||
{ // ### Points ###
|
||||
|
||||
// points, circles over the data point, def: true
|
||||
//set1.setDrawCircles(false);
|
||||
|
||||
//set1.setCircleColor(Color.BLACK);
|
||||
set1.setCircleColor(MainNativeActivity.red.toArgb());
|
||||
|
||||
// point size (default radius = 4f, min = 1f)
|
||||
//set1.setCircleRadius(3f);
|
||||
|
||||
// icons over the data point, def: false
|
||||
//set1.setDrawIcons(false);
|
||||
|
||||
// false to draw points as solid circles (default true)
|
||||
set1.setDrawCircleHole(false);
|
||||
}
|
||||
|
||||
{ // ### Values ###
|
||||
|
||||
// values over the data point, def: true
|
||||
set1.setDrawValues(false);
|
||||
|
||||
// text size of values
|
||||
//set1.setValueTextSize(9f);
|
||||
}
|
||||
|
||||
{ // ### Legend ###
|
||||
|
||||
//set1.setFormLineWidth(1f);
|
||||
//set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
|
||||
//set1.setFormSize(15.f);
|
||||
}
|
||||
|
||||
// draw selection line as dashed
|
||||
set1.setHighLightColor(Color.LTGRAY);
|
||||
//set1.enableDashedHighlightLine(10f, 5f, 0f);
|
||||
|
||||
{ // ### Filled area ###
|
||||
|
||||
// set the filled area
|
||||
//set1.setDrawFilled(true);
|
||||
set1.setFillFormatter(new IFillFormatter() {
|
||||
@Override
|
||||
public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) {
|
||||
return chart.getAxisLeft().getAxisMinimum();
|
||||
}
|
||||
});
|
||||
|
||||
// set color of filled area
|
||||
set1.setFillColor(MainNativeActivity.red.toArgb());
|
||||
//if (Utils.getSDKInt() >= 18) {
|
||||
// // drawables only supported on api level 18 and above
|
||||
// Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red);
|
||||
// set1.setFillDrawable(drawable);
|
||||
//} else {
|
||||
// set1.setFillColor(Color.BLACK);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
LineDataSet set2 = new LineDataSet(values2, label2);
|
||||
set2.setAxisDependency(YAxis.AxisDependency.RIGHT);
|
||||
set2.setColor(ColorTemplate.getHoloBlue());
|
||||
set2.setCircleColor(ColorTemplate.getHoloBlue());
|
||||
//set2.setCircleColor(MainNativeActivity.red.toArgb());
|
||||
set2.setDrawCircleHole(false);
|
||||
set2.setDrawValues(false);
|
||||
set2.setHighLightColor(Color.LTGRAY);
|
||||
//set2.setDrawFilled(true);
|
||||
set2.setFillFormatter(new IFillFormatter() {
|
||||
@Override
|
||||
public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) {
|
||||
return chart.getAxisRight().getAxisMinimum();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
|
||||
dataSets.add(set1); // add the data sets
|
||||
dataSets.add(set2); // add the data sets
|
||||
|
||||
// create a data object with the data sets
|
||||
LineData data = new LineData(dataSets);
|
||||
|
||||
//data.setValueTextColor(Color.WHITE);
|
||||
//data.setValueTextSize(9f);
|
||||
|
||||
// set data
|
||||
chart.setData(data);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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<Cursor> {
|
||||
|
||||
/**
|
||||
* 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<Cursor> 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<Cursor> cursorLoader, Cursor cursor) {
|
||||
List<String> emails = new ArrayList<>();
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
emails.add(cursor.getString(ProfileQuery.ADDRESS));
|
||||
cursor.moveToNext();
|
||||
}
|
||||
|
||||
addEmailsToAutoComplete(emails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> cursorLoader) {
|
||||
|
||||
}
|
||||
|
||||
private void addEmailsToAutoComplete(List<String> emailAddressCollection) {
|
||||
//Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
|
||||
ArrayAdapter<String> 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<Void, Void, Boolean> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <application android:usesCleartextTraffic="true"
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
@@ -99,45 +85,16 @@ public class MainActivity extends AppCompatActivity {
|
||||
});
|
||||
/* set URL site */
|
||||
if (savedInstanceState == null) {
|
||||
ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
//MESSAGE = MESSAGE.concat("\nmWifi: " + mWifi.toString());
|
||||
//MESSAGE = MESSAGE.concat("\nmWifi.isConnected(): " + mWifi.isConnected()); // is: true
|
||||
//MESSAGE = MESSAGE.concat("\nmWifi.getExtraInfo(): " + mWifi.getExtraInfo()); // is: null
|
||||
if (mWifi.isConnected()) {
|
||||
WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
|
||||
//MESSAGE = MESSAGE.concat("\nwifiInfo: " + wifiInfo.toString());
|
||||
if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
|
||||
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
WifiInfo info = wifiManager.getConnectionInfo();
|
||||
String ssid = findSSIDForWifiInfo(wifiManager, info);
|
||||
MESSAGE = MESSAGE.concat("\nSSID: " + ssid);
|
||||
// loadUrl needs: AndroidManifest.xml <application android:usesCleartextTraffic="true"
|
||||
//if (ssidIntern.contains(ssid)) {
|
||||
if (ssid.equals(ssidLocal)) {
|
||||
MESSAGE = MESSAGE.concat("\nconnection: internal");
|
||||
//Toast.makeText(getApplicationContext(), "intern", Toast.LENGTH_LONG).show();
|
||||
myWebView.loadUrl(getString(R.string.url_local));
|
||||
} else {
|
||||
MESSAGE = MESSAGE.concat("\nconnection: external");
|
||||
//Toast.makeText(getApplicationContext(), "extern", Toast.LENGTH_LONG).show();
|
||||
myWebView.loadUrl(getString(R.string.url_global));
|
||||
}
|
||||
}
|
||||
// loadUrl needs: AndroidManifest.xml <application android:usesCleartextTraffic="true"
|
||||
if (SettingsActivity.isLocal(getApplicationContext())) {
|
||||
//Toast.makeText(getApplicationContext(), "intern", Toast.LENGTH_LONG).show();
|
||||
myWebView.loadUrl(getString(R.string.url_local));
|
||||
} else {
|
||||
//Toast.makeText(getApplicationContext(), "extern", Toast.LENGTH_LONG).show();
|
||||
myWebView.loadUrl(getString(R.string.url_global));
|
||||
}
|
||||
}
|
||||
}
|
||||
public String findSSIDForWifiInfo(WifiManager wifiManager, WifiInfo wifiInfo) {
|
||||
List<WifiConfiguration> 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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<WifiConfiguration> 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;
|
||||
}
|
||||
}
|
||||
|
||||
168
app/src/main/java/de/weseng/wifiweatherstation/URLBuilder.java
Normal file
@@ -0,0 +1,168 @@
|
||||
package de.weseng.wifiweatherstation;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class: URLBuilder
|
||||
*
|
||||
* Utility that helps to build URL String
|
||||
*
|
||||
* Test functions in URLBuilderTest.java
|
||||
*
|
||||
* Source
|
||||
* - User: Gilad Tiram
|
||||
* - Date: 6/12/13
|
||||
* - Time: 4:02 PM
|
||||
*/
|
||||
class URLBuilder {
|
||||
|
||||
/**
|
||||
* Build URL string from Map of params. Nested Map and Collection is also supported
|
||||
*
|
||||
* @param params Map of params for constructing the URL Query String
|
||||
* @param encoding encoding type. If not set the "UTF-8" is selected by default
|
||||
* @return String of type key=value&...key=value
|
||||
*/
|
||||
static String httpBuildQuery(Map<String, Object> params, String encoding) {
|
||||
if (isEmpty(encoding)) {
|
||||
encoding = "UTF-8";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append('&');
|
||||
}
|
||||
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
|
||||
if (value instanceof Map) {
|
||||
List<String> baseParam = new ArrayList<>();
|
||||
baseParam.add(name);
|
||||
String str = buildUrlFromMap(baseParam, (Map) value, encoding);
|
||||
sb.append(str);
|
||||
|
||||
} else if (value instanceof Collection) {
|
||||
List<String> baseParam = new ArrayList<>();
|
||||
baseParam.add(name);
|
||||
String str = buildUrlFromCollection(baseParam, (Collection) value, encoding);
|
||||
sb.append(str);
|
||||
|
||||
} else {
|
||||
sb.append(encodeParam(name));
|
||||
sb.append("=");
|
||||
sb.append(encodeParam(value));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String buildUrlFromMap(List<String> baseParam, Map<Object, Object> map, String encoding) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String token;
|
||||
|
||||
//Build string of first level - related with params of provided Map
|
||||
for (Map.Entry<Object, Object> entry : map.entrySet()) {
|
||||
|
||||
if (sb.length() > 0) {
|
||||
sb.append('&');
|
||||
}
|
||||
|
||||
String name = String.valueOf(entry.getKey());
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof Map) {
|
||||
List<String> baseParam2 = new ArrayList<>(baseParam);
|
||||
baseParam2.add(name);
|
||||
String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
|
||||
sb.append(str);
|
||||
|
||||
} else if (value instanceof List) {
|
||||
List<String> baseParam2 = new ArrayList<>(baseParam);
|
||||
baseParam2.add(name);
|
||||
String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
|
||||
sb.append(str);
|
||||
} else {
|
||||
token = getBaseParamString(baseParam) + "[" + name + "]=" + encodeParam(value);
|
||||
sb.append(token);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String buildUrlFromCollection(List<String> baseParam, Collection coll, String encoding) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String token;
|
||||
if (!(coll instanceof List)) {
|
||||
coll = new ArrayList(coll);
|
||||
}
|
||||
List arrColl = (List) coll;
|
||||
|
||||
//Build string of first level - related with params of provided Map
|
||||
for (int i = 0; i < arrColl.size(); i++) {
|
||||
|
||||
if (sb.length() > 0) {
|
||||
sb.append('&');
|
||||
}
|
||||
|
||||
Object value = arrColl.get(i);
|
||||
if (value instanceof Map) {
|
||||
List<String> baseParam2 = new ArrayList<>(baseParam);
|
||||
baseParam2.add(String.valueOf(i));
|
||||
String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
|
||||
sb.append(str);
|
||||
|
||||
} else if (value instanceof List) {
|
||||
List<String> baseParam2 = new ArrayList<>(baseParam);
|
||||
baseParam2.add(String.valueOf(i));
|
||||
String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
|
||||
sb.append(str);
|
||||
} else {
|
||||
token = getBaseParamString(baseParam) + "[" + i + "]=" + encodeParam(value);
|
||||
sb.append(token);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
private static String getBaseParamString(List<String> baseParam) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < baseParam.size(); i++) {
|
||||
String s = baseParam.get(i);
|
||||
if (i == 0) {
|
||||
sb.append(s);
|
||||
} else {
|
||||
sb.append("[" + s + "]");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if String is either empty or null
|
||||
*
|
||||
* @param str string to check
|
||||
* @return true if string is empty. Else return false
|
||||
*/
|
||||
private static boolean isEmpty(String str) {
|
||||
return str == null || str.length() == 0;
|
||||
}
|
||||
|
||||
|
||||
private static String encodeParam(Object param) {
|
||||
try {
|
||||
// @throws java.io.UnsupportedEncodingException if encoding is not supported
|
||||
return URLEncoder.encode(String.valueOf(param), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return URLEncoder.encode(String.valueOf(param));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
app/src/main/res/drawable/openweathermap_01d.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable/openweathermap_01n.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/drawable/openweathermap_02d.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/drawable/openweathermap_02n.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/drawable/openweathermap_03d.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/drawable/openweathermap_03n.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/drawable/openweathermap_04d.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_04n.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_09d.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_09n.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_10d.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_10n.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_11d.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_11n.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/drawable/openweathermap_13d.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/drawable/openweathermap_13n.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/drawable/openweathermap_50d.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/drawable/openweathermap_50n.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
32
app/src/main/res/layout-land/activity_detail.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".DetailActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
tools:layout_editor_absoluteX="8dp"
|
||||
tools:layout_editor_absoluteY="58dp">
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/chart1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/activity_vertical_margin" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
526
app/src/main/res/layout-land/activity_main_native.xml
Normal file
@@ -0,0 +1,526 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainNativeActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="@dimen/activity_vertical_margin"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:layout_weight="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginBottom="-8dp"
|
||||
android:weightSum="6">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/temperature"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/humidity"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</TableRow>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableRow1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:paddingTop="@dimen/widget_vertical_margin"
|
||||
android:paddingBottom="@dimen/widget_vertical_margin">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureValue1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureUnit1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/temperature_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityValue1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityUnit1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/humidity_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMin1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMax1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureDelta1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMin1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMax1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityDelta1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableRow2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:paddingTop="@dimen/widget_vertical_margin"
|
||||
android:paddingBottom="@dimen/widget_vertical_margin">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureValue2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureUnit2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/temperature_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityValue2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityUnit2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/humidity_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMin2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMax2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureDelta2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMin2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMax2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityDelta2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableRow3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:paddingTop="@dimen/widget_vertical_margin"
|
||||
android:paddingBottom="@dimen/widget_vertical_margin">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureValue3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureUnit3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/temperature_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityValue3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityUnit3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/humidity_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMin3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMax3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureDelta3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMin3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMax3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityDelta3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewWeatherOutdoor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/widget_vertical_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/widget_vertical_margin"
|
||||
android:text="@string/weather_outdoor"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginBottom="80dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<!-- size 48x48 -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<!-- size 16x16 -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarSmall"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
32
app/src/main/res/layout/activity_detail.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".DetailActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:layout_editor_absoluteX="8dp"
|
||||
tools:layout_editor_absoluteY="58dp">
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/chart1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginBottom="@dimen/activity_vertical_margin" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
66
app/src/main/res/layout/activity_login.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
tools:context=".LoginActivity">
|
||||
|
||||
<!-- Login progress -->
|
||||
<ProgressBar
|
||||
android:id="@+id/login_progress"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/widget_vertical_margin"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/login_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/email_login_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/email"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/prompt_email"
|
||||
android:inputType="textEmailAddress"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/prompt_password"
|
||||
android:imeActionId="6"
|
||||
android:imeActionLabel="@string/action_sign_in_short"
|
||||
android:imeOptions="actionUnspecified"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/email_sign_in_button"
|
||||
style="?android:textAppearanceSmall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/action_sign_in"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
499
app/src/main/res/layout/activity_main_native.xml
Normal file
@@ -0,0 +1,499 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainNativeActivity">
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="-8dp"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/temperature"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/humidity"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</TableRow>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableRow1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/widget_vertical_margin"
|
||||
android:paddingBottom="@dimen/widget_vertical_margin"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureValue1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureUnit1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/temperature_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityValue1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityUnit1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/humidity_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMin1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMax1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureDelta1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMin1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMax1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityDelta1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableRow2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/widget_vertical_margin"
|
||||
android:paddingBottom="@dimen/widget_vertical_margin"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureValue2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureUnit2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/temperature_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityValue2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityUnit2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/humidity_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMin2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMax2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureDelta2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMin2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMax2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityDelta2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableRow3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/widget_vertical_margin"
|
||||
android:paddingBottom="@dimen/widget_vertical_margin"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureValue3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureUnit3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/temperature_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityValue3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/dummy_value"
|
||||
android:textSize="@dimen/value_main_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityUnit3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/humidity_unit"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:weightSum="6">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMin3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureMax3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTemperatureDelta3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_span="3"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMin3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityMax3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewHumidityDelta3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dummy_value2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewWeatherOutdoor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/widget_vertical_margin"
|
||||
android:layout_marginBottom="@dimen/widget_vertical_margin"
|
||||
android:layout_marginStart="@dimen/widget_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/widget_horizontal_margin"
|
||||
android:text="@string/weather_outdoor" />
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginBottom="80dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<!-- size 48x48 -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<!-- size 16x16 -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBarSmall"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
@@ -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" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/switchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/widget_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:text="@string/web_or_native"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/textView" />
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/textInputLayoutSsidLocal"
|
||||
android:layout_width="395dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="18dp"
|
||||
android:layout_marginTop="@dimen/widget_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
app:hintAnimationEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView">
|
||||
app:layout_constraintTop_toBottomOf="@+id/switchView">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/editTextSsidLocal"
|
||||
@@ -36,9 +50,11 @@
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/textInputLayoutUrlLocal"
|
||||
android:layout_width="395dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginTop="@dimen/widget_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
app:hintAnimationEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -54,9 +70,11 @@
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/textInputLayoutUrlGlobal"
|
||||
android:layout_width="395dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginTop="@dimen/widget_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
app:hintAnimationEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
||||
@@ -1,7 +1,49 @@
|
||||
<resources>
|
||||
<string name="app_name">WiFi-Wetter-Station</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="loading">Bitte warten, die Ansicht wird geladen…</string>
|
||||
<!-- Strings related to native view -->
|
||||
<string name="temperature">Temperatur</string>
|
||||
<string name="humidity">Feuchtigkeit</string>
|
||||
<string name="weather_outdoor"><![CDATA[<b>Wetterdaten für %s</b> %s
|
||||
<br/>{icon} %s (%s %%)
|
||||
<br/>Temperatur: %s °C — %s° / %s° gefühlt: %s°
|
||||
<br/>Feuchtigkeit: %s %%
|
||||
<br/>Druck: %s hPa
|
||||
<br/>Wind: %s km/h %s
|
||||
<br/>Sonnenaufgang / -untergang: %s / %s]]></string>
|
||||
<string name="weather_outdoor_rain"><![CDATA[<b>Wetterdaten für %s</b> %s
|
||||
<br/>{icon} %s, Bewölkung: %s %%
|
||||
<br/>Temperatur: %s °C — %s° / %s° gefühlt: %s°
|
||||
<br/>Feuchtigkeit: %s %%
|
||||
<br/>Druck: %s hPa
|
||||
<br/>Wind: %s km/h %s
|
||||
<br/>Sonnenaufgang / -untergang: %s / %s]]></string>
|
||||
<string name="weather_outdoor_rain_and_gust"><![CDATA[<b>Wetterdaten für %s</b> %s
|
||||
<br/>{icon} %s, Bewölkung: %s %%
|
||||
<br/>Temperatur: %s °C — %s° / %s° gefühlt: %s°
|
||||
<br/>Feuchtigkeit: %s %%
|
||||
<br/>Druck: %s hPa
|
||||
<br/>Wind: %s km/h %s Windböe %s km/h
|
||||
<br/>Sonnenaufgang / -untergang: %s / %s]]></string>
|
||||
<string name="weather_outdoor_gust"><![CDATA[<b>Wetterdaten für %s</b> %s
|
||||
<br/>{icon} %s (%s %%)
|
||||
<br/>Temperatur: %s °C — %s° / %s° gefühlt: %s°
|
||||
<br/>Feuchtigkeit: %s %%
|
||||
<br/>Druck: %s hPa
|
||||
<br/>Wind: %s km/h %s Windböe %s km/h
|
||||
<br/>Sonnenaufgang / -untergang: %s / %s]]></string>
|
||||
<string name="weather_outdoor_rainfall"><![CDATA[<b>Wetterdaten für %s</b> %s
|
||||
<br/>{icon} %s, Niederschlagsmenge: %s mm, Bewölkung: %s %%
|
||||
<br/>Temperatur: %s °C — %s° / %s° gefühlt: %s°
|
||||
<br/>Feuchtigkeit: %s %%
|
||||
<br/>Druck: %s hPa
|
||||
<br/>Wind: %s km/h %s
|
||||
<br/>Sonnenaufgang / -untergang: %s / %s]]></string>
|
||||
<!-- Strings related to settings -->
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="message_connection_internal">Verbindung: intern</string>
|
||||
<string name="message_connection_external">Verbindung: extern</string>
|
||||
<string name="web_or_native">Web oder native Ansicht</string>
|
||||
<string name="hint_url_local">Lokale URL</string>
|
||||
<string name="hint_url_global">Globale URL</string>
|
||||
</resources>
|
||||
|
||||
8
app/src/main/res/values/dimens.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="widget_horizontal_margin">8dp</dimen>
|
||||
<dimen name="widget_vertical_margin">8dp</dimen>
|
||||
<dimen name="value_main_size">40sp</dimen>
|
||||
</resources>
|
||||
@@ -1,11 +1,78 @@
|
||||
<resources>
|
||||
<string name="app_name">WiFi Weather Station</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="loading">Please wait, the view is loading…</string>
|
||||
<!-- Strings related to native view -->
|
||||
<string name="temperature">Temperature</string>
|
||||
<string name="temperature_unit" translatable="false">°C</string>
|
||||
<string name="humidity">Humidity</string>
|
||||
<string name="humidity_unit" translatable="false">%</string>
|
||||
<string name="dummy_value" translatable="false">__._</string>
|
||||
<string name="dummy_value2" translatable="false">o</string>
|
||||
<!-- name, dt; description, clouds; temp, tempMin, tempMax, apparent; humidity; pressure; speed, deg; sunrise, sunset -->
|
||||
<string name="weather_outdoor"><![CDATA[<b>Weather data for %s</b> %s
|
||||
<br/>{icon} %s (%s %%)
|
||||
<br/>Temperature: %s °C — %s° / %s° feels: %s°
|
||||
<br/>Humidity: %s %%
|
||||
<br/>Pressure: %s hPa
|
||||
<br/>Wind: %s km/h %s
|
||||
<br/>Sunrise / sunset: %s / %s]]></string>
|
||||
<!-- print clouds before clouds value if the description is about raining, so no misunderstanding applies -->
|
||||
<!-- name, dt; description, clouds; temp, tempMin, tempMax, apparent; humidity; pressure; speed, deg; sunrise, sunset -->
|
||||
<string name="weather_outdoor_rain"><![CDATA[<b>Weather data for %s</b> %s
|
||||
<br/>{icon} %s, clouds: %s %%
|
||||
<br/>Temperature: %s °C — %s° / %s° feels: %s°
|
||||
<br/>Humidity: %s %%
|
||||
<br/>Pressure: %s hPa
|
||||
<br/>Wind: %s km/h %s
|
||||
<br/>Sunrise / sunset: %s / %s]]></string>
|
||||
<string name="weather_outdoor_rain_and_gust"><![CDATA[<b>Weather data for %s</b> %s
|
||||
<br/>{icon} %s, clouds: %s %%
|
||||
<br/>Temperature: %s °C — %s° / %s° feels: %s°
|
||||
<br/>Humidity: %s %%
|
||||
<br/>Pressure: %s hPa
|
||||
<br/>Wind: %s km/h %s gust: %s km/h
|
||||
<br/>Sunrise / sunset: %s / %s]]></string>
|
||||
<string name="weather_outdoor_gust"><![CDATA[<b>Weather data for %s</b> %s
|
||||
<br/>{icon} %s (%s %%)
|
||||
<br/>Temperature: %s °C — %s° / %s° feels: %s°
|
||||
<br/>Humidity: %s %%
|
||||
<br/>Pressure: %s hPa
|
||||
<br/>Wind: %s km/h %s gust: %s km/h
|
||||
<br/>Sunrise / sunset: %s / %s]]></string>
|
||||
<!-- name, dt; description, rain, clouds; temp, tempMin, tempMax, apparent; humidity; pressure; speed, deg; sunrise, sunset -->
|
||||
<string name="weather_outdoor_rainfall"><![CDATA[<b>Weather data for %s</b> %s
|
||||
<br/>{icon} %s, rainfall: %s mm, clouds: %s %%
|
||||
<br/>Temperature: %s °C — %s° / %s° feels: %s°
|
||||
<br/>Humidity: %s %%
|
||||
<br/>Pressure: %s hPa
|
||||
<br/>Wind: %s km/h %s
|
||||
<br/>Sunrise / sunset: %s / %s]]></string>
|
||||
<!-- Strings related to settings -->
|
||||
<string name="settings">Settings</string>
|
||||
<string name="message" translatable="false">de.weseng.wifiweatherstation.MESSAGE</string>
|
||||
<string name="message_connection_internal">connection: internal</string>
|
||||
<string name="message_connection_external">connection: external</string>
|
||||
<string name="web_or_native">Web or native view</string>
|
||||
<string name="ssid" translatable="false">NETGEAR26-5G-2</string>
|
||||
<string name="url_local" translatable="false">http://192.168.1.5/site/wifi-weather-station/</string>
|
||||
<string name="url_global" translatable="false">http://inetsrv.no-ip.org/site/wifi-weather-station/</string>
|
||||
<string name="hint_ssid" translatable="false">SSID</string>
|
||||
<string name="url_local" translatable="false">http://192.168.1.5/site/wifi-weather-station/</string>
|
||||
<string name="hint_url_local">Local URL</string>
|
||||
<string name="url_global" translatable="false">http://inetsrv.no-ip.org/site/wifi-weather-station/</string>
|
||||
<string name="hint_url_global">Global URL</string>
|
||||
<string name="host_data_server_1" translatable="false">192.168.1.71</string>
|
||||
<string name="host_data_server_2" translatable="false">192.168.1.72</string>
|
||||
<string name="host_data_server_3" translatable="false">192.168.1.73</string>
|
||||
<!-- Strings related to login -->
|
||||
<string name="title_activity_login">Sign in</string>
|
||||
<string name="prompt_email">Email</string>
|
||||
<string name="prompt_password">Password (optional)</string>
|
||||
<string name="action_sign_in">Sign in or register</string>
|
||||
<string name="action_sign_in_short">Sign in</string>
|
||||
<string name="error_invalid_email">This email address is invalid</string>
|
||||
<string name="error_invalid_password">This password is too short</string>
|
||||
<string name="error_incorrect_password">This password is incorrect</string>
|
||||
<string name="error_field_required">This field is required</string>
|
||||
<string name="permission_rationale">"Contacts permissions are needed for providing email
|
||||
completions."
|
||||
</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package de.weseng.wifiweatherstation;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class MainNativeActivityTest {
|
||||
|
||||
@Test
|
||||
public void valueToColorRGB_below() {
|
||||
assertEquals(0x719dc3, new MainNativeActivity().valueToColorRGB(
|
||||
10, 17, 19, 23, 25,
|
||||
0x719dc3, 0xff00ff00, 0xffd1655d));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueToColorRGB_ideal() {
|
||||
assertEquals(0xff00ff00, new MainNativeActivity().valueToColorRGB(
|
||||
20, 17, 19, 23, 25,
|
||||
0x719DC3, 0xff00ff00, 0xffd1655d));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueToColorRGB_above() {
|
||||
assertEquals(0xffd1655d, new MainNativeActivity().valueToColorRGB(
|
||||
30, 17, 19, 23, 25,
|
||||
0x719DC3, 0xff00ff00, 0xffd1655d));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolate_0_255_0() {
|
||||
assertEquals(0, new MainNativeActivity().interpolate(
|
||||
0, 255, 0, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolate_0_255_50() {
|
||||
assertEquals(127, new MainNativeActivity().interpolate(
|
||||
0, 255, 50, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolate_0_255_100() {
|
||||
assertEquals(255, new MainNativeActivity().interpolate(
|
||||
0, 255, 100, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolateColor_00ff00_ff0000_0() {
|
||||
MainNativeActivity a = new MainNativeActivity();
|
||||
assertEquals(0xFFFFFF & 0xff00ff00,
|
||||
a.interpolateColor(0xff00ff00, 0xffff0000, 0, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolateColor_00ff00_ff0000_50() {
|
||||
MainNativeActivity a = new MainNativeActivity();
|
||||
assertEquals(0xFFFFFF & 0xff7f7f00,
|
||||
a.interpolateColor(0xff00ff00, 0xffff0000, 50, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolateColor_00ff00_ff0000_100() {
|
||||
MainNativeActivity a = new MainNativeActivity();
|
||||
assertEquals(0xFFFFFF & 0xffff0000,
|
||||
a.interpolateColor(0xff00ff00, 0xffff0000, 100, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueToColorRGB_between_ideal_and_above() {
|
||||
MainNativeActivity a = new MainNativeActivity();
|
||||
assertEquals(a.interpolateColor(0xff00ff00, 0xffd1655d, 50, 100),
|
||||
a.valueToColorRGB(
|
||||
24, 17, 19, 23, 25,
|
||||
0x719DC3, 0xff00ff00, 0xffd1655d));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package de.weseng.wifiweatherstation;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static de.weseng.wifiweatherstation.URLBuilder.httpBuildQuery;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class URLBuilderTest {
|
||||
|
||||
@Test
|
||||
public void basicTest() {
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("a", "1");
|
||||
params.put("b", "2");
|
||||
params.put("c", "3");
|
||||
|
||||
assertEquals("a=1&b=2&c=3",
|
||||
httpBuildQuery(params, "UTF-8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithMap() {
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("a", "1");
|
||||
params.put("b", "2");
|
||||
|
||||
Map<String, Object> cParams = new LinkedHashMap<>();
|
||||
cParams.put("c1", "c1val");
|
||||
cParams.put("c2", "c2val");
|
||||
params.put("c", cParams);
|
||||
|
||||
assertEquals("a=1&b=2&c[c1]=c1val&c[c2]=c2val",
|
||||
httpBuildQuery(params, "UTF-8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNestedMap() {
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("a", "1");
|
||||
params.put("b", "2");
|
||||
|
||||
Map<String, Object> cParamsLevel1 = new LinkedHashMap<>();
|
||||
cParamsLevel1.put("cL1-1", "cLevel1-1val");
|
||||
cParamsLevel1.put("cL1-2", "cLevel1-2val");
|
||||
|
||||
Map<String, Object> cParamsLevel2 = new LinkedHashMap<>();
|
||||
cParamsLevel2.put("cL2-1", "cLevel2-1val");
|
||||
cParamsLevel2.put("cL2-2", "cLevel2-2val");
|
||||
cParamsLevel1.put("cL1-3", cParamsLevel2);
|
||||
|
||||
params.put("c", cParamsLevel1);
|
||||
|
||||
assertEquals("a=1&b=2&c[cL1-1]=cLevel1-1val&c[cL1-2]=cLevel1-2val&c[cL1-3][cL2-1]=cLevel2-1val&c[cL1-3][cL2-2]=cLevel2-2val",
|
||||
httpBuildQuery(params, "UTF-8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithList() {
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("a", "1");
|
||||
params.put("b", "2");
|
||||
|
||||
List<Object> cParams = new ArrayList<>();
|
||||
cParams.add("c1val");
|
||||
cParams.add("c2val");
|
||||
params.put("c", cParams);
|
||||
|
||||
assertEquals("a=1&b=2&c[0]=c1val&c[1]=c2val",
|
||||
httpBuildQuery(params, "UTF-8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNestedList() {
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
params.put("a", "1");
|
||||
params.put("b", "2");
|
||||
|
||||
List<Object> cParamsLevel1 = new ArrayList<>();
|
||||
cParamsLevel1.add("cL1-val1");
|
||||
cParamsLevel1.add("cL12-val2");
|
||||
|
||||
List<Object> cParamsLevel2 = new ArrayList<>();
|
||||
cParamsLevel2.add("cL2-val1");
|
||||
cParamsLevel2.add("cL2-val2");
|
||||
cParamsLevel1.add(cParamsLevel2);
|
||||
|
||||
params.put("c", cParamsLevel1);
|
||||
|
||||
assertEquals("a=1&b=2&c[0]=cL1-val1&c[1]=cL12-val2&c[2][0]=cL2-val1&c[2][1]=cL2-val2",
|
||||
httpBuildQuery(params, "UTF-8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompound() {
|
||||
Map<String, Object> params = new LinkedHashMap<>();
|
||||
|
||||
//flat
|
||||
params.put("a", "1");
|
||||
params.put("b", "2");
|
||||
|
||||
//Map level 1
|
||||
Map<String, Object> cParamsLevel1 = new LinkedHashMap<>();
|
||||
cParamsLevel1.put("cL1-1", "cLevel1-1val");
|
||||
cParamsLevel1.put("cL1-2", "cLevel1-2val");
|
||||
|
||||
//Map level 2
|
||||
Map<String, Object> cParamsLevel2 = new LinkedHashMap<>();
|
||||
cParamsLevel2.put("cL2-1", "cLevel2-1val");
|
||||
cParamsLevel2.put("cL2-2", "cLevel2-2val");
|
||||
cParamsLevel1.put("cL1-3", cParamsLevel2);
|
||||
|
||||
params.put("c", cParamsLevel1);
|
||||
|
||||
//List level 1
|
||||
List<Object> dParamsLevel1 = new ArrayList<>();
|
||||
dParamsLevel1.add("dL1-val1");
|
||||
dParamsLevel1.add("dL12-val2");
|
||||
|
||||
//List level 2
|
||||
List<Object> dParamsLevel2 = new ArrayList<>();
|
||||
dParamsLevel2.add("dL2-val1");
|
||||
dParamsLevel2.add("dL2-val2");
|
||||
dParamsLevel1.add(dParamsLevel2);
|
||||
|
||||
params.put("d", dParamsLevel1);
|
||||
|
||||
assertEquals("a=1&b=2&c[cL1-1]=cLevel1-1val&c[cL1-2]=cLevel1-2val&c[cL1-3][cL2-1]=cLevel2-1val&c[cL1-3][cL2-2]=cLevel2-2val&d[0]=dL1-val1&d[1]=dL12-val2&d[2][0]=dL2-val1&d[2][1]=dL2-val2",
|
||||
httpBuildQuery(params, "UTF-8"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||