Project commit

This commit is contained in:
2020-05-25 16:11:33 +02:00
commit fea1fbbad5
62 changed files with 1943 additions and 0 deletions

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

34
app/build.gradle Normal file
View File

@ -0,0 +1,34 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "org.bandie.yipanic"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.1"
testFunctionalTest = false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.android.volley:volley:1.1.1'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.security:security-crypto:1.0.0-rc02'
implementation 'com.google.android.material:material:1.1.0'
}

6
app/lint.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="IconLocation">
<ignore path="src/main/res/drawable/bandie.png" />
</issue>
</lint>

21
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

BIN
app/release/app-release.apk Normal file

Binary file not shown.

1
app/release/output.json Normal file
View File

@ -0,0 +1 @@
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.bandie.yipanic">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Design">
<activity android:name=".PasscodeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SettingsActivity"
android:label="@string/title_activity_settings">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".CommandActivity" />
</activity>
<activity android:name=".CommandActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".PasscodeActivity" />
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -0,0 +1,134 @@
package org.bandie.yipanic;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.security.crypto.EncryptedSharedPreferences;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.google.android.material.snackbar.Snackbar;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.security.GeneralSecurityException;
class Command {
private final Snackbar sbOk, sbNotSet, sbAccessDenied, sbFailed, sbNoServer;
private String server, k, s;
Command(View view, Context context) {
this.sbOk = Snackbar.make(view, "Sent. :)", 3000);
this.sbNotSet = Snackbar.make(view, "Command not set. :/", 3000);
this.sbAccessDenied = Snackbar.make(view, "Access denied. >:(", 3000);
this.sbFailed = Snackbar.make(view, "Failed. :C", 3000);
this.sbNoServer = Snackbar.make(view, "No server configured! :o", 3000);
try {
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
this.server = sharedPreferences.getString("server", null);
this.k = sharedPreferences.getString("key", null);
this.s = sharedPreferences.getString("secret", null);
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
}
}
private JsonObjectRequest requestHandler(String cmd) {
JSONObject json = new JSONObject();
try {
json.put("key", this.k);
json.put("secret", this.s);
json.put("cmd", cmd);
} catch (JSONException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
}
if (this.server == null) {
sbNoServer.show();
return null;
}
return new JsonObjectRequest
(Request.Method.POST, this.server, json, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
if (response.getBoolean("access")) {
switch (response.getInt("error")) {
case 0:
sbOk.show();
break;
case 1:
sbNotSet.show();
break;
case 2:
//Password required
break;
case 4:
//Password OK
break;
}
} else {
sbAccessDenied.show();
}
} catch (JSONException e) {
if (e.getMessage() != null)
Log.e("Yip", e.getMessage());
else
Log.e("Yip", "[ No exception message ]");
sbFailed.show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError e) {
if (e.getMessage() != null)
Log.e("Yip", e.getMessage());
else
Log.e("Yip", "[ No exception message ]");
sbFailed.show();
}
});
}
JsonObjectRequest lock() {
return requestHandler("lock");
}
JsonObjectRequest shutdown() {
return requestHandler("shutdown");
}
JsonObjectRequest panic() {
return requestHandler("panic");
}
JsonObjectRequest infraShutdown() {
return requestHandler("infraShutdown");
}
JsonObjectRequest infraPanic() {
return requestHandler("infraPanic");
}
}

View File

@ -0,0 +1,212 @@
package org.bandie.yipanic;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Switch;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
public class CommandActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.command_activity);
ImageButton b = findViewById(R.id.btnShutdown);
b.setEnabled(false);
b = findViewById(R.id.btnPanic);
b.setEnabled(false);
b = findViewById(R.id.btnInfraShutdown);
b.setEnabled(false);
b = findViewById(R.id.btnInfraPanic);
b.setEnabled(false);
Switch s = findViewById(R.id.swSecShutdown1);
s.setChecked(false);
s = findViewById(R.id.swSecShutdown2);
s.setChecked(false);
s = findViewById(R.id.swSecPanic1);
s.setChecked(false);
s = findViewById(R.id.swSecPanic2);
s.setChecked(false);
s = findViewById(R.id.swSecPanic3);
s.setChecked(false);
s = findViewById(R.id.swSecInfraShutdown1);
s.setChecked(false);
s = findViewById(R.id.swSecInfraShutdown2);
s.setChecked(false);
s = findViewById(R.id.swSecInfraPanic1);
s.setChecked(false);
s = findViewById(R.id.swSecInfraPanic2);
s.setChecked(false);
s = findViewById(R.id.swSecInfraPanic3);
s.setChecked(false);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
System.out.println(item.getItemId());
switch (item.getItemId()) {
case 16908332:
case R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onPause() {
super.onPause();
this.finish();
}
public void sendLockCmd(View view) {
Command c = new Command(view, getApplicationContext());
JsonObjectRequest send = c.lock();
if (send != null)
Volley.newRequestQueue(this).add(send);
}
public void sendShutdownCmd(View view) {
Command c = new Command(view, getApplicationContext());
JsonObjectRequest send = c.shutdown();
if (send != null)
Volley.newRequestQueue(this).add(send);
}
public void sendPanicCmd(View view) {
Command c = new Command(view, getApplicationContext());
JsonObjectRequest send = c.panic();
if (send != null)
Volley.newRequestQueue(this).add(send);
}
public void sendInfraShutdownCmd(View view) {
Command c = new Command(view, getApplicationContext());
JsonObjectRequest send = c.infraShutdown();
if (send != null)
Volley.newRequestQueue(this).add(send);
}
public void sendInfraPanicCmd(View view) {
Command c = new Command(view, getApplicationContext());
JsonObjectRequest send = c.infraPanic();
if (send != null)
Volley.newRequestQueue(this).add(send);
}
public void switchShutdown(View view) {
final Switch s = findViewById(view.getId());
Switch s1 = findViewById(R.id.swSecShutdown1);
Switch s2 = findViewById(R.id.swSecShutdown2);
ImageButton b = findViewById(R.id.btnShutdown);
if (s1.isChecked() && s2.isChecked())
b.setEnabled(true);
else
b.setEnabled(false);
if (s.isChecked()) {
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
ImageButton b = findViewById(R.id.btnShutdown);
s.setChecked(false);
b.setEnabled(false);
}
}, 10000);
}
}
public void switchPanic(View view) {
final Switch s = findViewById(view.getId());
Switch s1 = findViewById(R.id.swSecPanic1);
Switch s2 = findViewById(R.id.swSecPanic2);
Switch s3 = findViewById(R.id.swSecPanic3);
ImageButton b = findViewById(R.id.btnPanic);
if (s1.isChecked() && s2.isChecked() && s3.isChecked())
b.setEnabled(true);
else
b.setEnabled(false);
if (s.isChecked()) {
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
ImageButton b = findViewById(R.id.btnPanic);
s.setChecked(false);
b.setEnabled(false);
}
}, 10000);
}
}
public void switchInfraShutdown(View view) {
final Switch s = findViewById(view.getId());
Switch s1 = findViewById(R.id.swSecInfraShutdown1);
Switch s2 = findViewById(R.id.swSecInfraShutdown2);
ImageButton b = findViewById(R.id.btnInfraShutdown);
if (s1.isChecked() && s2.isChecked())
b.setEnabled(true);
else
b.setEnabled(false);
if (s.isChecked()) {
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
ImageButton b = findViewById(R.id.btnInfraShutdown);
s.setChecked(false);
b.setEnabled(false);
}
}, 10000);
}
}
public void switchInfraPanic(View view) {
final Switch s = findViewById(view.getId());
Switch s1 = findViewById(R.id.swSecInfraPanic1);
Switch s2 = findViewById(R.id.swSecInfraPanic2);
Switch s3 = findViewById(R.id.swSecInfraPanic3);
ImageButton b = findViewById(R.id.btnInfraPanic);
if (s1.isChecked() && s2.isChecked() && s3.isChecked())
b.setEnabled(true);
else
b.setEnabled(false);
if (s.isChecked()) {
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
ImageButton b = findViewById(R.id.btnInfraPanic);
s.setChecked(false);
b.setEnabled(false);
}
}, 10000);
}
}
public void startSettingsActivity(@SuppressWarnings("unused") View view) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
}

View File

@ -0,0 +1,120 @@
package org.bandie.yipanic;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import androidx.security.crypto.EncryptedSharedPreferences;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Random;
public class PasscodeActivity<RequestQueue, StringRequest> extends AppCompatActivity {
private String passcode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_passcode);
try {
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
getApplicationContext(),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
this.passcode = sharedPreferences.getString("passcode", null);
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
}
if (this.passcode == null) {
Intent intent = new Intent(this, CommandActivity.class);
startActivity(intent);
}
}
@Override
protected void onResume() {
super.onResume();
try {
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
getApplicationContext(),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
this.passcode = sharedPreferences.getString("passcode", null);
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yip", e.getMessage());
else
Log.e("Yip", "[ No exception message ]");
}
if (this.passcode == null) {
Intent intent = new Intent(this, CommandActivity.class);
startActivity(intent);
}
}
private void checkPasscode() {
EditText v = findViewById(R.id.pwPasscodeInput);
if (v.getText().toString().equals(this.passcode) || this.passcode == null) {
v.setText("");
Intent intent = new Intent(this, CommandActivity.class);
startActivity(intent);
} else {
v.setText("");
v.setError("Passcode wrong.");
}
}
public void yip(@SuppressWarnings("unused") View view) {
int audio;
switch (new Random().nextInt(4)) {
default:
case 0:
audio = R.raw.yip1;
break;
case 1:
audio = R.raw.yip2;
break;
case 2:
audio = R.raw.yip3;
break;
case 3:
audio = R.raw.yip4;
break;
}
MediaPlayer mp = MediaPlayer.create(this, audio);
mp.start();
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
this.checkPasscode();
return true;
}
return true;
}
}

View File

@ -0,0 +1,197 @@
package org.bandie.yipanic;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import androidx.security.crypto.EncryptedSharedPreferences;
import com.google.android.material.snackbar.Snackbar;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class SettingsActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 16908332:
case R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
ActionBar actionBar = getSupportActionBar();
EditText srv = findViewById(R.id.textServer);
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
try {
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
getApplicationContext(),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
String server = sharedPreferences.getString("server", null);
srv.setText(server);
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
}
}
@Override
protected void onPause() {
super.onPause();
this.finish();
}
public void saveServerSettings(View view) {
Snackbar sbSaved = Snackbar.make(view, "Server settings saved! <3", 3000);
Snackbar sbFailedToSave = Snackbar.make(view, "Couldn't save settings! :'(", 3000);
try {
EditText srv = findViewById(R.id.textServer);
EditText k = findViewById(R.id.pwKey);
EditText s = findViewById(R.id.pwSecret);
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
this,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
sharedPrefsEditor.putString("server", srv.getText().toString());
if (!k.getText().toString().equals(""))
sharedPrefsEditor.putString("key", k.getText().toString());
if (!s.getText().toString().equals(""))
sharedPrefsEditor.putString("secret", s.getText().toString());
sharedPrefsEditor.apply();
sbSaved.show();
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
sbFailedToSave.show();
}
}
public void savePasscode(View view) {
Snackbar sbSaved = Snackbar.make(view, "Passcode saved! <3", 3000);
Snackbar sbFailedToSave = Snackbar.make(view, "Couldn't save! :'(", 3000);
try {
EditText pc = findViewById(R.id.pwSetPasscode);
EditText pcc = findViewById(R.id.pwSetPasscodeConfirm);
String pcS = pc.getText().toString();
String pccS = pcc.getText().toString();
if (pcS.equals("") || pccS.equals("")) {
pc.setError("Passcode is empty. >;(");
pcc.setError("Passcode is empty. >;(");
sbFailedToSave.show();
return;
}
if (pcS.length() < 4) {
pc.setError("Passcode needs to have at least 4 digits.");
pcc.setError("Passcode needs to have at least 4 digits.");
sbFailedToSave.show();
return;
}
if (!pcS.equals(pccS)) {
pc.setError("Passcode didn't match. ;(");
pcc.setError("Passcode didn't match. ;(");
sbFailedToSave.show();
return;
}
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
this,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
sharedPrefsEditor.putString("passcode", pcS);
sharedPrefsEditor.apply();
sbSaved.show();
pc.setText("");
pcc.setText("");
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
sbFailedToSave.show();
}
}
public void deletePasscode(View view) {
Snackbar sbSaved = Snackbar.make(view, "Passcode deleted! D:", 3000);
Snackbar sbFailedToSave = Snackbar.make(view, "Couldn't delete passcode! :'(", 3000);
try {
EditText pc = findViewById(R.id.pwSetPasscode);
String pcS = pc.getText().toString();
EncryptedSharedPreferences sharedPreferences = (EncryptedSharedPreferences) EncryptedSharedPreferences
.create(
"Yipanic",
"Yipanic",
this,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
if (pcS.equals(sharedPreferences.getString("passcode", null))) {
sharedPrefsEditor.remove("passcode");
sharedPrefsEditor.apply();
sbSaved.show();
} else {
pc.setError("Wrong passcode.");
sbFailedToSave.show();
}
} catch (IOException | GeneralSecurityException e) {
if (e.getMessage() != null)
Log.e("Yipanic", e.getMessage());
else
Log.e("Yipanic", "[ No exception message ]");
sbFailedToSave.show();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".PasscodeActivity">
<EditText
android:id="@+id/pwPasscodeInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="240dp"
android:ems="10"
android:importantForAutofill="no"
android:inputType="numberPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:labelFor="@id/pwPasscodeInput"
android:text="@string/passcode"
app:layout_constraintBottom_toTopOf="@+id/pwPasscodeInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="157dp"
android:layout_height="155dp"
android:layout_marginTop="44dp"
android:contentDescription="@string/bandie_who_is_a_big_yip"
android:onClick="yip"
android:soundEffectsEnabled="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/bandie" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,295 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".CommandActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/labelLock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lock" />
<ImageButton
android:id="@+id/btnLock"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:backgroundTint="#246FA8"
android:contentDescription="@string/send_lock_command"
android:onClick="sendLockCmd"
app:srcCompat="@android:drawable/ic_lock_idle_lock" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="86dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="140dp"
android:layout_height="72dp"
android:gravity="top"
android:orientation="vertical">
<TextView
android:id="@+id/labelShutdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:text="@string/shutdown" />
<ImageButton
android:id="@+id/btnShutdown"
android:layout_width="110dp"
android:layout_height="45dp"
android:layout_marginTop="0dp"
android:backgroundTint="#734B1A"
android:contentDescription="@string/send_shutdown_command"
android:onClick="sendShutdownCmd"
app:srcCompat="@android:drawable/ic_lock_power_off" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Switch
android:id="@+id/swSecShutdown1"
android:layout_width="113dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="switchShutdown"
android:text="@string/shutdown" />
<Switch
android:id="@+id/swSecShutdown2"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:onClick="switchShutdown"
android:text="@string/shutdown" />
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/divider2"
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="113dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="140dp"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/labelPanic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/panic" />
<ImageButton
android:id="@+id/btnPanic"
android:layout_width="110dp"
android:layout_height="45dp"
android:backgroundTint="#880000"
android:contentDescription="@string/panic"
android:onClick="sendPanicCmd"
app:srcCompat="@android:drawable/ic_menu_delete" />
</LinearLayout>
<LinearLayout
android:layout_width="232dp"
android:layout_height="match_parent"
android:orientation="vertical">
<Switch
android:id="@+id/swSecPanic1"
android:layout_width="113dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="switchPanic"
android:text="@string/panic" />
<Switch
android:id="@+id/swSecPanic2"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:onClick="switchPanic"
android:text="@string/panic" />
<Switch
android:id="@+id/swSecPanic3"
android:layout_width="205dp"
android:layout_height="wrap_content"
android:onClick="switchPanic"
android:text="@string/panic" />
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/divider3"
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="85dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="140dp"
android:layout_height="match_parent"
android:gravity="top"
android:orientation="vertical">
<TextView
android:id="@+id/labelInfraShutdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/infra_shutdown" />
<ImageButton
android:id="@+id/btnInfraShutdown"
android:layout_width="110dp"
android:layout_height="45dp"
android:backgroundTint="#B36200"
android:contentDescription="@string/infra_shutdown"
android:onClick="sendInfraShutdownCmd"
app:srcCompat="?android:attr/alertDialogIcon" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Switch
android:id="@+id/swSecInfraShutdown1"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="switchInfraShutdown"
android:text="@string/infra_shutdown" />
<Switch
android:id="@+id/swSecInfraShutdown2"
android:layout_width="205dp"
android:layout_height="wrap_content"
android:onClick="switchInfraShutdown"
android:text="@string/infra_shutdown" />
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/divider4"
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="140dp"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/labelInfraPanic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/infra_panic" />
<ImageButton
android:id="@+id/btnInfraPanic"
android:layout_width="110dp"
android:layout_height="45dp"
android:backgroundTint="#9C0000"
android:contentDescription="@string/infra_panic"
android:onClick="sendInfraPanicCmd"
app:srcCompat="@android:drawable/ic_menu_close_clear_cancel" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Switch
android:id="@+id/swSecInfraPanic1"
android:layout_width="117dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="switchInfraPanic"
android:text="@string/infra_panic" />
<Switch
android:id="@+id/swSecInfraPanic2"
android:layout_width="159dp"
android:layout_height="wrap_content"
android:onClick="switchInfraPanic"
android:text="@string/infra_panic" />
<Switch
android:id="@+id/swSecInfraPanic3"
android:layout_width="206dp"
android:layout_height="wrap_content"
android:onClick="switchInfraPanic"
android:text="@string/infra_panic" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="24dp"
android:clickable="true"
android:focusable="true"
android:onClick="startSettingsActivity"
app:backgroundTint="@color/colorPrimaryDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@android:drawable/ic_menu_manage" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,154 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@id/textServer"
android:text="@string/server"
android:textColor="#999" />
<EditText
android:id="@+id/textServer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/editTextBackground"
android:backgroundTint="#999999"
android:contentDescription="@string/server"
android:ems="10"
android:foregroundTint="#FFFFFF"
android:importantForAutofill="no"
android:inputType="textPersonName"
android:singleLine="true"
android:textColor="#CCCCCC"
android:textColorHint="#444444" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@id/pwKey"
android:text="@string/key"
android:textColor="#999" />
<EditText
android:id="@+id/pwKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#999999"
android:contentDescription="@string/some_api_key"
android:ems="10"
android:foregroundTint="#FFFFFF"
android:importantForAutofill="no"
android:inputType="textPassword"
android:singleLine="true"
android:textColor="#CCCCCC"
android:textColorHint="#444444" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@id/pwSecret"
android:text="@string/secret"
android:textColor="#999" />
<EditText
android:id="@+id/pwSecret"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#999999"
android:contentDescription="@string/some_api_secret"
android:ems="10"
android:foregroundTint="#FFFFFF"
android:importantForAutofill="no"
android:inputType="textPassword"
android:singleLine="true"
android:textColor="#CCCCCC"
android:textColorHint="#444444" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="122dp">
<Button
android:layout_width="205dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:background="#777777"
android:onClick="saveServerSettings"
android:text="@string/save"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@id/pwSetPasscode"
android:text="@string/passcode" />
<EditText
android:id="@+id/pwSetPasscode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:importantForAutofill="no"
android:inputType="numberPassword" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:labelFor="@id/pwSetPasscodeConfirm"
android:text="@string/confirm_passcode" />
<EditText
android:id="@+id/pwSetPasscodeConfirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:importantForAutofill="no"
android:inputType="numberPassword" />
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="deletePasscode"
android:text="@string/delete" />
<Button
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="savePasscode"
android:text="@string/set" />
</LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="19dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/to_delete_your_passcode_type_in_the_passcode_in_the_first_field_and_press_delete" />
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
<resources>
<!-- Reply Preference -->
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimaryDark">#3700B3</color>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#2B2B2B</color>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View File

@ -0,0 +1,23 @@
<resources>
<string name="app_name">Yipanic</string>
<string name="title_activity_settings">Settings</string>
<string name="key">Key</string>
<string name="secret">Secret</string>
<string name="save">Save</string>
<string name="server">Server</string>
<string name="some_api_key">Some API key</string>
<string name="some_api_secret">Some API secret</string>
<string name="send_lock_command">Send lock command</string>
<string name="send_shutdown_command">Send shutdown command</string>
<string name="bandie_who_is_a_big_yip">Bandie who is a big yip</string>
<string name="passcode">Passcode</string>
<string name="confirm_passcode">Confirm Passcode</string>
<string name="delete">Delete</string>
<string name="set">Set</string>
<string name="to_delete_your_passcode_type_in_the_passcode_in_the_first_field_and_press_delete">To delete your passcode, type in the passcode in the first field and press delete.</string>
<string name="panic">Panic</string>
<string name="infra_shutdown">Infra-Shutdown</string>
<string name="infra_panic">Infra-Panic</string>
<string name="shutdown">Shutdown</string>
<string name="lock">Lock</string>
</resources>

View File

@ -0,0 +1,5 @@
<resources>
<!-- Base application theme. -->
</resources>