close #26 - outputstream implementiert, welche kontinuirliche daten schreibt
close #24 - können jetzt ohne probleme kommentare schreiben close #22 - startet beim frischen start aber auch beim onResume die phone app close #18 - knallt nicht mehr wenn bei 0 gestartet wird. close #9 - verbinden sich wunderbar, nachrichten fliegen und daten werden übertragen close #8 - sensordaten werden in ein .csv files geschrieben inkl kommentare
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.tonifetzer.conductorswatch">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@@ -16,6 +19,7 @@
|
||||
<service android:name=".DataLayerListenerService">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
|
||||
<action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" />
|
||||
<data android:scheme="wear" android:host="*" android:pathPrefix="/start-activity"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package de.tonifetzer.conductorswatch;
|
||||
|
||||
/**
|
||||
* Created by toni on 12/01/18.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Class: DataFolder
|
||||
* Description: SDK save file class. Is able to open a folder on the device independent of the given
|
||||
* device and android skd version.
|
||||
*/
|
||||
public class DataFolder {
|
||||
|
||||
private File folder;
|
||||
private static final String TAG = "DataFolder";
|
||||
|
||||
public DataFolder(Context context, String folderName){
|
||||
|
||||
// 1) try external data folder
|
||||
folder = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), folderName);
|
||||
if (isOK(folder)) {return;}
|
||||
|
||||
// 2) try sd-card folder
|
||||
folder = new File(Environment.getExternalStorageDirectory() + "/" + folderName);
|
||||
if (isOK(folder)) {return;}
|
||||
|
||||
// 3) try internal data folder
|
||||
folder = new File(context.getApplicationInfo().dataDir);
|
||||
if (isOK(folder)) {return;}
|
||||
|
||||
// all failed
|
||||
throw new RuntimeException("failed to create/access storage folder");
|
||||
|
||||
}
|
||||
|
||||
/** ensure the given folder is OK */
|
||||
private static final boolean isOK(final File folder) {
|
||||
folder.mkdirs();
|
||||
final boolean ok = folder.exists() && folder.isDirectory();
|
||||
if (ok) {
|
||||
Log.d(TAG, "using: " + folder);
|
||||
} else {
|
||||
Log.d(TAG, "not OK: " + folder);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
public File getFolder(){
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,17 @@ package de.tonifetzer.conductorswatch;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.wearable.ChannelClient;
|
||||
import com.google.android.gms.wearable.MessageEvent;
|
||||
import com.google.android.gms.wearable.Wearable;
|
||||
import com.google.android.gms.wearable.WearableListenerService;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Listens to DataItems and Messages from the local node.
|
||||
*/
|
||||
@@ -14,6 +21,7 @@ public class DataLayerListenerService extends WearableListenerService {
|
||||
|
||||
private static final String TAG = "DataLayerService";
|
||||
private static final String START_ACTIVITY_PATH = "/start-activity";
|
||||
private static final String DATA_PATH ="/data";
|
||||
|
||||
GoogleApiClient mGoogleApiClient;
|
||||
|
||||
@@ -28,7 +36,7 @@ public class DataLayerListenerService extends WearableListenerService {
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(MessageEvent messageEvent) {
|
||||
//LOGD(TAG, "onMessageReceived: " + messageEvent);
|
||||
LOGD(TAG, "onMessageReceived: " + messageEvent);
|
||||
|
||||
// Check to see if the message is to start an activity
|
||||
if (messageEvent.getPath().equals(START_ACTIVITY_PATH)) {
|
||||
@@ -43,4 +51,40 @@ public class DataLayerListenerService extends WearableListenerService {
|
||||
Log.d(tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOutputClosed(ChannelClient.Channel openChannel, int i, int i1){
|
||||
|
||||
LOGD(TAG, "Channel successfully opened.");
|
||||
|
||||
//get the sensordata provided by the watch
|
||||
Wearable.getChannelClient(this).getInputStream(openChannel).addOnSuccessListener((InputStream stream) -> {
|
||||
|
||||
Log.d(TAG, "Channel successfully opened and ready to write file.");
|
||||
|
||||
byte[] data = null;
|
||||
try {
|
||||
stream.read(data);
|
||||
DataFolder folder = new DataFolder(this, "sensorOutFiles");
|
||||
File file = new File(folder.getFolder(), System.currentTimeMillis() + ".csv");
|
||||
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(data);
|
||||
fos.close();
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).addOnFailureListener((Exception e) -> {
|
||||
//Channel not open? couldn't receive inputstream?
|
||||
});
|
||||
|
||||
//we have what we wanted, so close the channel
|
||||
Wearable.getChannelClient(this).close(openChannel);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,25 @@
|
||||
package de.tonifetzer.conductorswatch;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaPlayer;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.SoundEffectConstants;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import com.google.android.gms.wearable.ChannelClient;
|
||||
import com.google.android.gms.wearable.MessageEvent;
|
||||
import com.google.android.gms.wearable.MessageClient;
|
||||
import com.google.android.gms.wearable.Wearable;
|
||||
|
||||
import java.util.Timer;
|
||||
|
||||
import de.tonifetzer.conductorswatch.network.SensorDataCallback;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements MessageClient.OnMessageReceivedListener{
|
||||
|
||||
private TextView mTextView;
|
||||
Timer mTimer;
|
||||
private EditText mEditView;
|
||||
private Timer mTimer;
|
||||
|
||||
private static final String TAG = "DataLayerService";
|
||||
private static final String START_ACTIVITY_PATH = "/start-activity";
|
||||
@@ -26,27 +29,34 @@ public class MainActivity extends AppCompatActivity implements MessageClient.OnM
|
||||
|
||||
private boolean mIsRecording = false;
|
||||
|
||||
private ChannelClient.ChannelCallback mChannelCallback;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
mTextView = (TextView) findViewById(R.id.bpmText);
|
||||
mTextView = findViewById(R.id.bpmText);
|
||||
mEditView = findViewById(R.id.comments);
|
||||
|
||||
// handels everything regarding sensor data delivered by the watch.
|
||||
mChannelCallback = new SensorDataCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Wearable.getMessageClient(this).addListener(this);
|
||||
Wearable.getChannelClient(this).registerChannelCallback(mChannelCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
Wearable.getMessageClient(this).removeListener(this);
|
||||
Wearable.getChannelClient(this).unregisterChannelCallback(mChannelCallback);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(MessageEvent messageEvent) {
|
||||
|
||||
@@ -67,6 +77,8 @@ public class MainActivity extends AppCompatActivity implements MessageClient.OnM
|
||||
mTimer = new Timer();
|
||||
mTimer.scheduleAtFixedRate(new Metronome(this) , 0, 60000 / Integer.parseInt(parts[1]));
|
||||
mTextView.setTextColor(Color.parseColor("#EE693F"));
|
||||
mEditView.setEnabled(false);
|
||||
mEditView.setFocusable(false);
|
||||
mIsRecording = true;
|
||||
}
|
||||
|
||||
@@ -75,6 +87,9 @@ public class MainActivity extends AppCompatActivity implements MessageClient.OnM
|
||||
|
||||
mTimer.cancel();
|
||||
mTextView.setTextColor(Color.parseColor("#158b69"));
|
||||
mEditView.setEnabled(true);
|
||||
mEditView.setFocusable(true);
|
||||
mEditView.setFocusableInTouchMode(true);
|
||||
mIsRecording = false;
|
||||
}
|
||||
else if (messageEvent.getPath().contains(UPDATE_PATH)){
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package de.tonifetzer.conductorswatch.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.wearable.ChannelClient;
|
||||
import com.google.android.gms.wearable.Wearable;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by toni on 14/01/18.
|
||||
*/
|
||||
|
||||
public class SensorDataCallback extends ChannelClient.ChannelCallback implements SensorDataFileReceiver.OnFileReceiveListener{
|
||||
|
||||
private static final String TAG = "SensorDataCallback";
|
||||
|
||||
private Context mContext;
|
||||
private SensorDataFileReceiver mFileReceiver;
|
||||
private ChannelClient.Channel mOpenChannel;
|
||||
|
||||
public SensorDataCallback(Context context) {
|
||||
mContext = context;
|
||||
mOpenChannel = null;
|
||||
|
||||
mFileReceiver = new SensorDataFileReceiver(mContext);
|
||||
mFileReceiver.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChannelOpened(@NonNull ChannelClient.Channel openChannel) {
|
||||
super.onChannelOpened(openChannel);
|
||||
|
||||
mOpenChannel = openChannel;
|
||||
Wearable.getChannelClient(mContext).getInputStream(mOpenChannel).addOnSuccessListener((InputStream stream) -> {
|
||||
|
||||
mFileReceiver.setOpenStream(stream);
|
||||
new Thread(mFileReceiver, "FileReceiverThread").start();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChannelClosed(@NonNull ChannelClient.Channel openChannel, int closeReason, int appSpecificErrorCode) {
|
||||
super.onChannelClosed(openChannel, closeReason, appSpecificErrorCode);
|
||||
|
||||
Log.d(TAG, "Channel is closed. Reason: " + closeReason + " - ErrorCode: " + appSpecificErrorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartSaveFile() {
|
||||
//TODO: runOnUIThread stuff
|
||||
|
||||
Log.d(TAG, "Start saving file. - " + Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishedSavingFile() {
|
||||
|
||||
//close the channel
|
||||
if(mOpenChannel != null){
|
||||
Wearable.getChannelClient(mContext).close(mOpenChannel);
|
||||
}
|
||||
|
||||
Log.d(TAG, "Finished saving file. - " + Thread.currentThread().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package de.tonifetzer.conductorswatch.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Created by toni on 14/01/18.
|
||||
*/
|
||||
|
||||
public class SensorDataFileReceiver implements Runnable {
|
||||
|
||||
private InputStream mOpenStream;
|
||||
private Context mContext;
|
||||
private static final String TAG = "SensorDataFileReceiver";
|
||||
|
||||
public SensorDataFileReceiver(Context context){
|
||||
mOpenStream = null;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setOpenStream(InputStream stream){
|
||||
mOpenStream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if(mOpenStream != null){
|
||||
|
||||
Log.d(TAG, "Opened InputStream in Thread: " + Thread.currentThread().getName());
|
||||
|
||||
for(SensorDataFileReceiver.OnFileReceiveListener listener : listeners){
|
||||
listener.onStartSaveFile();
|
||||
}
|
||||
|
||||
byte[] bytesTimestamp = new byte[Long.BYTES];
|
||||
byte[] bytesSensorID = new byte[Integer.BYTES];
|
||||
byte[] bytesX= new byte[Double.BYTES];
|
||||
byte[] bytesY= new byte[Double.BYTES];
|
||||
byte[] bytesZ= new byte[Double.BYTES];
|
||||
|
||||
long ts = 0;
|
||||
int id = 0;
|
||||
double x = 0, y = 0, z = 0;
|
||||
|
||||
int i = 0;
|
||||
SensorDataFileWriter fileWriter = new SensorDataFileWriter(mContext);
|
||||
|
||||
try {
|
||||
while(mOpenStream.read(bytesTimestamp) != -1) {
|
||||
ts = ByteBuffer.wrap(bytesTimestamp).getLong();
|
||||
|
||||
mOpenStream.read(bytesSensorID);
|
||||
id = ByteBuffer.wrap(bytesSensorID).getInt();
|
||||
|
||||
mOpenStream.read(bytesX);
|
||||
x = ByteBuffer.wrap(bytesX).getDouble();
|
||||
|
||||
mOpenStream.read(bytesY);
|
||||
y = ByteBuffer.wrap(bytesY).getDouble();
|
||||
|
||||
mOpenStream.read(bytesZ);
|
||||
z = ByteBuffer.wrap(bytesZ).getDouble();
|
||||
|
||||
++i;
|
||||
|
||||
if(id != 4 && id != 10){
|
||||
Log.d(TAG, "STOOOOOP");
|
||||
}
|
||||
|
||||
fileWriter.writeVector3D(ts, id, x, y, z);
|
||||
}
|
||||
|
||||
//we have what we wanted, so close the channel
|
||||
fileWriter.toDisk();
|
||||
Log.d(TAG, "Num Data transferred: " + i);
|
||||
|
||||
//finished callback
|
||||
for(SensorDataFileReceiver.OnFileReceiveListener listener : listeners){
|
||||
listener.onFinishedSavingFile();
|
||||
}
|
||||
|
||||
//close the stream, since this is recommended
|
||||
mOpenStream.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Channel is not valid, is it really open? Check connection to watch! - Thread: " + Thread.currentThread().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface for callback
|
||||
*/
|
||||
public interface OnFileReceiveListener {
|
||||
void onStartSaveFile();
|
||||
void onFinishedSavingFile();
|
||||
}
|
||||
|
||||
private List<OnFileReceiveListener> listeners = new CopyOnWriteArrayList<OnFileReceiveListener>();
|
||||
public void add(SensorDataFileReceiver.OnFileReceiveListener listener){listeners.add(listener);}
|
||||
public void remove(SensorDataFileReceiver.OnFileReceiveListener listener){listeners.remove(listener);}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package de.tonifetzer.conductorswatch.network;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import de.tonifetzer.conductorswatch.DataFolder;
|
||||
import de.tonifetzer.conductorswatch.R;
|
||||
|
||||
/**
|
||||
* Created by toni on 14/01/18.
|
||||
*/
|
||||
|
||||
public class SensorDataFileWriter {
|
||||
|
||||
private static final int FLUSH_LIMIT = 2*1024*1024;
|
||||
private static final String TAG = "SensorDataFileWriter";
|
||||
|
||||
private File mSensorDataFile;
|
||||
private FileOutputStream mFileOutputStream;
|
||||
private StringBuilder mStringBuilder = new StringBuilder();
|
||||
private final DataFolder mFolder;
|
||||
private boolean mStreamOpenend = false;
|
||||
|
||||
public SensorDataFileWriter(Context context) {
|
||||
|
||||
mFolder = new DataFolder(context, "sensorOutFiles");
|
||||
|
||||
//write some description for this file in the first line
|
||||
EditText editView = ((Activity) context).findViewById(R.id.comments);
|
||||
TextView textView = ((Activity) context).findViewById(R.id.bpmText);
|
||||
writeDescription("Kommentar: " + editView.getText().toString() + "\nMetronom: " + textView.getText().toString() + " bpm");
|
||||
|
||||
//open connection to file
|
||||
open();
|
||||
}
|
||||
|
||||
public final void writeVector3D(long ts, int id, double x, double y, double z){
|
||||
|
||||
synchronized (this) {
|
||||
|
||||
if (mStreamOpenend) {
|
||||
|
||||
mStringBuilder.append(ts).append(';').append(id).append(';').append(x).append(';').append(y).append(';').append(z).append('\n');
|
||||
|
||||
if (mStringBuilder.length() > FLUSH_LIMIT) {flush(false);}
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final void writeDescription(String str){
|
||||
synchronized (this) {
|
||||
mStringBuilder.append(str).append('\n').append('\n');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// flush data to disk
|
||||
public final void toDisk(){
|
||||
synchronized (this) {
|
||||
flush(true);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
/** helper method for exception-less writing. DO NOT CALL DIRECTLY! */
|
||||
private final void _write(final byte[] data) {
|
||||
try {
|
||||
mFileOutputStream.write(data);
|
||||
Log.d(TAG, "flushed " + data.length + " bytes to disk");
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("error while writing log-file", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** helper-class for background writing */
|
||||
class FlushAsync extends AsyncTask<byte[], Integer, Integer> {
|
||||
@Override
|
||||
protected final Integer doInBackground(byte[][] data) {
|
||||
_write(data[0]);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/** flush current buffer-contents to disk */
|
||||
private final void flush(boolean sync) {
|
||||
|
||||
// fetch current buffer contents to write and hereafter empty the buffer
|
||||
// this action MUST be atomic, just like the add-method
|
||||
byte[] data = null;
|
||||
synchronized (this) {
|
||||
data = mStringBuilder.toString().getBytes(); // fetch data to write
|
||||
mStringBuilder.setLength(0); // reset the buffer
|
||||
}
|
||||
|
||||
// write
|
||||
if (sync) {
|
||||
// write to disk using the current thread
|
||||
_write(data);
|
||||
} else {
|
||||
// write to disk using a background-thread
|
||||
new FlushAsync().execute(new byte[][] {data});
|
||||
}
|
||||
}
|
||||
|
||||
private final void open() {
|
||||
mSensorDataFile = new File(mFolder.getFolder(), System.currentTimeMillis() + ".csv");
|
||||
|
||||
try {
|
||||
mFileOutputStream = new FileOutputStream(mSensorDataFile);
|
||||
mStreamOpenend = true;
|
||||
|
||||
Log.d(TAG, "will write to: " + mSensorDataFile.toString());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
mStreamOpenend = false;
|
||||
}
|
||||
}
|
||||
|
||||
private final void close() {
|
||||
try {
|
||||
mFileOutputStream.close();
|
||||
mStreamOpenend = false;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,38 @@
|
||||
<?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"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="de.tonifetzer.conductorswatch.MainActivity">
|
||||
android:orientation="vertical"
|
||||
tools:context="de.tonifetzer.conductorswatch.MainActivity"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bpmText"
|
||||
android:soundEffectsEnabled="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:soundEffectsEnabled="true"
|
||||
android:text="80"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#158b69"
|
||||
android:textSize="100sp"/>
|
||||
android:textSize="100sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
<TextView
|
||||
android:id="@+id/Text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:soundEffectsEnabled="true"
|
||||
android:text="Kommentare zur Aufnahme:"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/comments"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textMultiLine"
|
||||
android:text=""
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
BIN
android/ConductorsPhone/app/src/main/res/raw/metronom.flac
Normal file
BIN
android/ConductorsPhone/app/src/main/res/raw/metronom.flac
Normal file
Binary file not shown.
BIN
android/ConductorsPhone/app/src/main/res/raw/metronom2.wav
Normal file
BIN
android/ConductorsPhone/app/src/main/res/raw/metronom2.wav
Normal file
Binary file not shown.
BIN
android/ConductorsPhone/app/src/main/res/raw/metronom3.wav
Normal file
BIN
android/ConductorsPhone/app/src/main/res/raw/metronom3.wav
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
|
||||
Reference in New Issue
Block a user