This commit is contained in:
mrbesen 2019-02-26 04:24:00 +01:00
commit bd54b7ddfb
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
29 changed files with 789 additions and 0 deletions

40
app/build.gradle Normal file
View File

@ -0,0 +1,40 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "de.mrbesen.runbin"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
/*externalNativeBuild {
cmake {
cppFlags ""
}
}*/
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/*
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}*/
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
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'
compile group: 'commons-io', name: 'commons-io', version: '2.0.1'
}

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

View File

@ -0,0 +1,26 @@
package de.mrbesen.runbin;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("de.mrbesen.runbin", appContext.getPackageName());
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="preferExternal"
package="de.mrbesen.runbin">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".RunService"/>
</application>
</manifest>

View File

@ -0,0 +1,78 @@
package de.mrbesen.runbin;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView logView;
private ScrollView logLayout;
// Used to load the 'native-lib' library on application startup.
/*static {
System.loadLibrary("native-lib");
}*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
logView = (TextView) findViewById(R.id.logView);
logLayout = (ScrollView) findViewById(R.id.logScrollView);
}
public void run(View v) {
logView.setText("");
Intent serviceIntent = new Intent(this, RunService.class);
serviceIntent.putExtra("binary", ((EditText) findViewById(R.id.binname)).getText().toString());
serviceIntent.putExtra("param", ((EditText) findViewById(R.id.param)).getText().toString());
serviceIntent.putExtra("path", ((EditText) findViewById(R.id.binpath)).getText().toString());
BroadcastReceiver callback = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
LocalBroadcastManager.getInstance(context).unregisterReceiver(this);
//process terminated
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(callback, new IntentFilter("callback"));
LocalBroadcastManager.getInstance(this).registerReceiver(addLog, new IntentFilter("addLog"));
startService(serviceIntent);
}
private BroadcastReceiver addLog = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
final ScrollView scrollView = (ScrollView) logView.getParent();
final int scrollY = scrollView.getScrollY();
logView.append(Html.fromHtml(message));
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
};
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
/*public native String stringFromJNI();*/
}

View File

@ -0,0 +1,209 @@
package de.mrbesen.runbin;
import android.app.IntentService;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.BitmapFactory;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.text.Html;
import android.util.Log;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
public class RunService extends IntentService {
private String log;
private static final String tag = "Service";
public RunService() {
super("RunService");
}
private void addLog(String string) {
String logLine = "";
String[] text = string.split("\\n");
for (String line : text) {
String curText = Html.escapeHtml(line);
if (curText.toLowerCase().startsWith("log: ")) {
curText = curText.replaceFirst("(?i)log: ", "");
} else if (curText.toLowerCase().startsWith("info:")) {
curText = curText.replaceFirst("(?i)info: ", "");
curText = "<font color= \"#FFA500\">" + curText + "</font>";
} else if (curText.toLowerCase().startsWith("warning: ")) {
curText = curText.replaceFirst("(?i)warning: ", "");
curText = "<font color= \"#FF0000\">" + curText + "</font>";
} else if (curText.toLowerCase().startsWith("error: ")) {
curText = curText.replaceFirst("(?i)error: ", "");
curText = "<font color=\"#8B0000\">" + curText + "</font>";
}
logLine += "<br>" + curText;
}
log += logLine;
Intent intent = new Intent("addLog");
intent.putExtra("message", logLine);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(tag, "Starting service...");
final String binarydl = intent.getStringExtra("binary");
final File execpath = new File(intent.getStringExtra("path"));
final String param = intent.getStringExtra("param");
final File binpath = getFilesDir();
execpath.mkdirs();
binpath.mkdirs();
final String binname = FilenameUtils.getName(binarydl);
CharSequence text = "Running...";
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setTicker(text)
.setContentTitle(text)
.setContentText(execpath + " " + binarydl)
.setContentIntent(contentIntent)
.build();
startForeground(1, notification);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
final PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
wakeLock.acquire();
try {
// Make sure we can execute the binary
//install binary
Log.d(tag, "Download " + binarydl + " into " + binpath + " called " + binname );
File bin = new File(binpath, binname);
download(binarydl, bin);
bin.setExecutable(true);
// Initiate ProcessBuilder with the command at the given location
ProcessBuilder processBuilder = new ProcessBuilder(bin.getAbsolutePath(), param);
processBuilder.directory(execpath.getAbsoluteFile());
processBuilder.redirectErrorStream(true);
addLog("Info: Process is starting...");
Log.d(tag, "Starting process. Folder: " + execpath + " with params: " + param);
final Process process = processBuilder.start();
// Open STDIN for the inputLine
final OutputStream cuberiteSTDIN = process.getOutputStream();
// Logging thread. This thread will check stdout (and stderr), color it and append it to the logView. This thread will wait only for next lines coming. if stdout is closed, this thread will exit
new Thread(new Runnable() {
@Override
public void run() {
Log.d(tag, "Starting logging thread...");
Scanner processScanner = new Scanner(process.getInputStream());
while (processScanner.hasNextLine()) {
String line = processScanner.nextLine();
Log.i("Process", line);
addLog(line);
}
processScanner.close();
}
}).start();
// Communication with the activity
BroadcastReceiver getLog = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Intent sendIntent = new Intent("fullLog");
sendIntent.putExtra("message", log);
LocalBroadcastManager.getInstance(context).sendBroadcast(sendIntent);
}
};
BroadcastReceiver kill = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
process.destroy();
}
};
BroadcastReceiver executeLine = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String line = intent.getStringExtra("message");
try {
cuberiteSTDIN.write((line + "\n").getBytes());
cuberiteSTDIN.flush();
} catch (Exception e) {
Log.e(tag, "An error occurred when writing " + line + " to the STDIN", e);}
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(getLog, new IntentFilter("getLog"));
LocalBroadcastManager.getInstance(this).registerReceiver(kill, new IntentFilter("kill"));
LocalBroadcastManager.getInstance(this).registerReceiver(executeLine, new IntentFilter("executeLine"));
// Wait for the process to end. Logic waits here until process has stopped. Everything after that is cleanup for the next run
process.waitFor();
Log.d(tag, "Stopped Process.");
LocalBroadcastManager.getInstance(this).unregisterReceiver(getLog);
LocalBroadcastManager.getInstance(this).unregisterReceiver(kill);
LocalBroadcastManager.getInstance(this).unregisterReceiver(executeLine);
cuberiteSTDIN.close();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("callback"));
stopSelf();
} catch (Exception e) {
Log.wtf(tag, "An error occurred when starting process", e);
addLog("error: Failed.");
} finally {
wakeLock.release();
}
}
private void download(String surl, final File file) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(surl);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
return;
// download the file
input = connection.getInputStream();
output = new FileOutputStream(file);
byte data[] = new byte[4096];
int count;
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
}
}

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeWidth="1"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,87 @@
<?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=".MainActivity">
<EditText
android:id="@+id/binname"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:ems="10"
android:hint="Binary Name"
android:inputType="text"
android:text="http://192.168.1.2/wget"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/binpath"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:ems="10"
android:hint="Binary Path"
android:inputType="textUri"
android:text="/sdcard/bin"
app:layout_constraintEnd_toStartOf="@+id/runbtn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/param" />
<ScrollView
android:id="@+id/logScrollView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:paddingBottom="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/binpath">
<TextView
android:id="@+id/logView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
<Button
android:id="@+id/runbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="20dp"
android:onClick="run"
android:text="Run"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/param" />
<EditText
android:id="@+id/param"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:ems="10"
android:hint="Parameter"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/binname" />
</android.support.constraint.ConstraintLayout>

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="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/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="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">RunBin</string>
</resources>

View File

@ -0,0 +1,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@ -0,0 +1,17 @@
package de.mrbesen.runbin;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

26
build.gradle Normal file
View File

@ -0,0 +1,26 @@
// 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.2.1'
// 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
}

15
gradle.properties Normal file
View File

@ -0,0 +1,15 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

1
settings.gradle Normal file
View File

@ -0,0 +1 @@
include ':app'