Browse Source

Project commit

master
Bandie 1 year ago
commit
fea1fbbad5
Signed by: Bandie GPG Key ID: 843D7FA93BA46312
62 changed files with 1943 additions and 0 deletions
  1. +14
    -0
      .gitignore
  2. +1
    -0
      .idea/.name
  3. +116
    -0
      .idea/codeStyles/Project.xml
  4. +5
    -0
      .idea/codeStyles/codeStyleConfig.xml
  5. +9
    -0
      .idea/dictionaries/bandie.xml
  6. +20
    -0
      .idea/gradle.xml
  7. +9
    -0
      .idea/misc.xml
  8. +12
    -0
      .idea/runConfigurations.xml
  9. +6
    -0
      .idea/vcs.xml
  10. +25
    -0
      LICENSE
  11. +44
    -0
      README.md
  12. +1
    -0
      app/.gitignore
  13. +34
    -0
      app/build.gradle
  14. +6
    -0
      app/lint.xml
  15. +21
    -0
      app/proguard-rules.pro
  16. BIN
      app/release/app-release.apk
  17. +1
    -0
      app/release/output.json
  18. +34
    -0
      app/src/main/AndroidManifest.xml
  19. BIN
      app/src/main/ic_launcher-playstore.png
  20. +134
    -0
      app/src/main/java/org/bandie/yipanic/Command.java
  21. +212
    -0
      app/src/main/java/org/bandie/yipanic/CommandActivity.java
  22. +120
    -0
      app/src/main/java/org/bandie/yipanic/PasscodeActivity.java
  23. +197
    -0
      app/src/main/java/org/bandie/yipanic/SettingsActivity.java
  24. BIN
      app/src/main/res/drawable/bandie.png
  25. +43
    -0
      app/src/main/res/layout/activity_passcode.xml
  26. +295
    -0
      app/src/main/res/layout/command_activity.xml
  27. +154
    -0
      app/src/main/res/layout/settings_activity.xml
  28. +5
    -0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  29. +5
    -0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  30. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  31. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
  32. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  33. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  34. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
  35. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  36. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  37. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
  38. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  39. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  40. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
  41. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  42. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  43. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
  44. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  45. BIN
      app/src/main/res/raw/yip1.mp3
  46. BIN
      app/src/main/res/raw/yip2.mp3
  47. BIN
      app/src/main/res/raw/yip3.mp3
  48. BIN
      app/src/main/res/raw/yip4.mp3
  49. +4
    -0
      app/src/main/res/values/arrays.xml
  50. +4
    -0
      app/src/main/res/values/colors.xml
  51. +4
    -0
      app/src/main/res/values/ic_launcher_background.xml
  52. +4
    -0
      app/src/main/res/values/ids.xml
  53. +23
    -0
      app/src/main/res/values/strings.xml
  54. +5
    -0
      app/src/main/res/values/styles.xml
  55. +29
    -0
      build.gradle
  56. +63
    -0
      example/index.php
  57. +20
    -0
      gradle.properties
  58. BIN
      gradle/wrapper/gradle-wrapper.jar
  59. +6
    -0
      gradle/wrapper/gradle-wrapper.properties
  60. +172
    -0
      gradlew
  61. +84
    -0
      gradlew.bat
  62. +2
    -0
      settings.gradle

+ 14
- 0
.gitignore View File

@ -0,0 +1,14 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx

+ 1
- 0
.idea/.name View File

@ -0,0 +1 @@
Yipanic

+ 116
- 0
.idea/codeStyles/Project.xml View File

@ -0,0 +1,116 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

+ 5
- 0
.idea/codeStyles/codeStyleConfig.xml View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

+ 9
- 0
.idea/dictionaries/bandie.xml View File

@ -0,0 +1,9 @@
<component name="ProjectDictionaryState">
<dictionary name="bandie">
<words>
<w>bandie</w>
<w>passcode</w>
<w>yipanic</w>
</words>
</dictionary>
</component>

+ 20
- 0
.idea/gradle.xml View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

+ 9
- 0
.idea/misc.xml View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<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>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

+ 12
- 0
.idea/runConfigurations.xml View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

+ 6
- 0
.idea/vcs.xml View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

+ 25
- 0
LICENSE View File

@ -0,0 +1,25 @@
BSD 2-Clause License
Copyright (c) 2017, Bandie <bandie@chaospott.de>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 44
- 0
README.md View File

@ -0,0 +1,44 @@
# Yipanic
This appilcation sends a JSON to an API with the intent to remote control your computer or infrastructure in terms of panic.
The app can be secured by a passcode.
## What the app sends
```json
{
"key": string,
"secret": string,
"cmd": "(lock|shutdown|panic|infraShutdown|infraPanic)"
}
```
`cmd` requires one of `lock`, `shutdown`, ...
## What answers the app expect
```json
{
"access": (true|false),
"error": int
}
```
At the moment the following error codes are defined:
```
0 - OK
1 - Command not set
```
## Example backend
See `example/index.php`.
### What is ding?
See [ding](https://git.chaospott.de/Bandie/ding/).

+ 1
- 0
app/.gitignore View File

@ -0,0 +1 @@
/build

+ 34
- 0
app/build.gradle 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
- 0
app/lint.xml 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
- 0
app/proguard-rules.pro 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 View File


+ 1
- 0
app/release/output.json 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":{}}]

+ 34
- 0
app/src/main/AndroidManifest.xml 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>

BIN
app/src/main/ic_launcher-playstore.png View File

Before After
Width: 512  |  Height: 512  |  Size: 72 KiB

+ 134
- 0
app/src/main/java/org/bandie/yipanic/Command.java 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");
}
}

+ 212
- 0
app/src/main/java/org/bandie/yipanic/CommandActivity.java 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);
}
}

+ 120
- 0
app/src/main/java/org/bandie/yipanic/PasscodeActivity.java 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;
}
}

+ 197
- 0
app/src/main/java/org/bandie/yipanic/SettingsActivity.java 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();
}
}
}

BIN
app/src/main/res/drawable/bandie.png View File

Before After
Width: 200  |  Height: 200  |  Size: 37 KiB

+ 43
- 0
app/src/main/res/layout/activity_passcode.xml 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>

+ 295
- 0
app/src/main/res/layout/command_activity.xml 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>

+ 154
- 0
app/src/main/res/layout/settings_activity.xml 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>

+ 5
- 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml 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>

+ 5
- 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml 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>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png View File

Before After
Width: 72  |  Height: 72  |  Size: 3.0 KiB

BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png View File

Before After
Width: 162  |  Height: 162  |  Size: 6.9 KiB

BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png View File

Before After
Width: 72  |  Height: 72  |  Size: 4.9 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.8 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png View File

Before After
Width: 108  |  Height: 108  |  Size: 3.8 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png View File

Before After
Width: 48  |  Height: 48  |  Size: 2.8 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png View File

Before After
Width: 96  |  Height: 96  |  Size: 4.5 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png View File

Before After
Width: 216  |  Height: 216  |  Size: 10 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png View File

Before After
Width: 96  |  Height: 96  |  Size: 7.3 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png View File

Before After
Width: 144  |  Height: 144  |  Size: 8.0 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png View File

Before After
Width: 324  |  Height: 324  |  Size: 19 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png View File

Before After
Width: 144  |  Height: 144  |  Size: 13 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png View File

Before After
Width: 192  |  Height: 192  |  Size: 12 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png View File

Before After
Width: 432  |  Height: 432  |  Size: 29 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png View File

Before After
Width: 192  |  Height: 192  |  Size: 19 KiB

BIN
app/src/main/res/raw/yip1.mp3 View File


BIN
app/src/main/res/raw/yip2.mp3 View File


BIN
app/src/main/res/raw/yip3.mp3 View File


BIN
app/src/main/res/raw/yip4.mp3 View File


+ 4
- 0
app/src/main/res/values/arrays.xml View File

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

+ 4
- 0
app/src/main/res/values/colors.xml View File

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

+ 4
- 0
app/src/main/res/values/ic_launcher_background.xml View File

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

+ 4
- 0
app/src/main/res/values/ids.xml View File

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

+ 23
- 0
app/src/main/res/values/strings.xml 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>

+ 5
- 0
app/src/main/res/values/styles.xml View File

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

+ 29
- 0
build.gradle View File

@ -0,0 +1,29 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

+ 63
- 0
example/index.php View File

@ -0,0 +1,63 @@
<?php
// Author: Bandie <bandie@chaospott.de>
// Project: Yipanic
// License: GNU-GPLv3
define("_KEY_", "somekey