ii
This commit is contained in:
parent
d2e60c858f
commit
39af7e815e
|
@ -36,7 +36,7 @@ android {
|
||||||
buildToolsVersion "25.0.2"
|
buildToolsVersion "25.0.2"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 16
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:label="@string/select_device"
|
android:label="@string/select_device"
|
||||||
android:theme="@android:style/Theme.Holo.Dialog"/>
|
android:theme="@android:style/Theme.Holo.Dialog"/>
|
||||||
|
<service android:name=".BluetoothChatService"></service>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -16,37 +16,33 @@
|
||||||
|
|
||||||
package org.surfsite.iconsole;
|
package org.surfsite.iconsole;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.NumberPicker;
|
import android.widget.NumberPicker;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import android.util.Log;
|
||||||
import org.surfsite.iconsole.R;
|
|
||||||
import org.surfsite.iconsole.common.logger.Log;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This fragment controls Bluetooth to communicate with other devices.
|
* This fragment controls Bluetooth to communicate with other devices.
|
||||||
|
@ -66,6 +62,13 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
private Button mStopButton;
|
private Button mStopButton;
|
||||||
private Button mDisconnectButton;
|
private Button mDisconnectButton;
|
||||||
private NumberPicker mLevel;
|
private NumberPicker mLevel;
|
||||||
|
private TextView mSpeedText;
|
||||||
|
private TextView mPowerText;
|
||||||
|
private TextView mRPMText;
|
||||||
|
private TextView mDistanceText;
|
||||||
|
private TextView mCaloriesText;
|
||||||
|
private TextView mHFText;
|
||||||
|
private TextView mTimeText;
|
||||||
/**
|
/**
|
||||||
* Name of the connected device
|
* Name of the connected device
|
||||||
*/
|
*/
|
||||||
|
@ -85,6 +88,7 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
* Member object for the chat services
|
* Member object for the chat services
|
||||||
*/
|
*/
|
||||||
private BluetoothChatService mChatService = null;
|
private BluetoothChatService mChatService = null;
|
||||||
|
private boolean mIsBound;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -118,10 +122,12 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
|
||||||
if (mChatService != null) {
|
if (mChatService != null) {
|
||||||
mChatService.stop();
|
mChatService.stopBT();
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "onDestroy()");
|
||||||
|
|
||||||
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -135,7 +141,7 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
// Only if the state is STATE_NONE, do we know that we haven't started already
|
// Only if the state is STATE_NONE, do we know that we haven't started already
|
||||||
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
|
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
|
||||||
// Start the Bluetooth chat services
|
// Start the Bluetooth chat services
|
||||||
mChatService.start();
|
mChatService.startBT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,6 +164,54 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
mLevel.setValue(5);
|
mLevel.setValue(5);
|
||||||
mLevel.setWrapSelectorWheel(false);
|
mLevel.setWrapSelectorWheel(false);
|
||||||
mLevel.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
|
mLevel.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
|
||||||
|
mSpeedText = (TextView) view.findViewById(R.id.Speed);
|
||||||
|
mPowerText = (TextView) view.findViewById(R.id.Power);
|
||||||
|
mRPMText = (TextView) view.findViewById(R.id.RPM);
|
||||||
|
mDistanceText = (TextView) view.findViewById(R.id.Distance);
|
||||||
|
mCaloriesText = (TextView) view.findViewById(R.id.Calories);
|
||||||
|
mHFText = (TextView) view.findViewById(R.id.Heart);
|
||||||
|
mTimeText = (TextView) view.findViewById(R.id.Time);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
// This is called when the connection with the service has been
|
||||||
|
// established, giving us the service object we can use to
|
||||||
|
// interact with the service. Because we have bound to a explicit
|
||||||
|
// service that we know is running in our own process, we can
|
||||||
|
// cast its IBinder to a concrete class and directly access it.
|
||||||
|
mChatService = ((BluetoothChatService.BluetoothChatServiceI)service).getService();
|
||||||
|
((BluetoothChatService.BluetoothChatServiceI)service).setHandler(mHandler);
|
||||||
|
Log.d(TAG, "onServiceConnected()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
// This is called when the connection with the service has been
|
||||||
|
// unexpectedly disconnected -- that is, its process crashed.
|
||||||
|
// Because it is running in our same process, we should never
|
||||||
|
// see this happen.
|
||||||
|
mChatService = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void doBindService() {
|
||||||
|
Log.d(TAG, "doBindService()");
|
||||||
|
|
||||||
|
// Establish a connection with the service. We use an explicit
|
||||||
|
// class name because we want a specific service implementation that
|
||||||
|
// we know will be running in our own process (and thus won't be
|
||||||
|
// supporting component replacement by other applications).
|
||||||
|
getActivity().bindService(new Intent(getActivity(), BluetoothChatService.class), mConnection , Context.BIND_AUTO_CREATE);
|
||||||
|
mIsBound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void doUnbindService() {
|
||||||
|
if (mIsBound) {
|
||||||
|
// Detach our existing connection.
|
||||||
|
getActivity().unbindService(mConnection);
|
||||||
|
mIsBound = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,37 +219,45 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
*/
|
*/
|
||||||
private void setupChat() {
|
private void setupChat() {
|
||||||
Log.d(TAG, "setupChat()");
|
Log.d(TAG, "setupChat()");
|
||||||
/*
|
|
||||||
// Initialize the array adapter for the conversation thread
|
|
||||||
mConversationArrayAdapter = new ArrayAdapter<>(getActivity(), R.layout.message);
|
|
||||||
|
|
||||||
mConversationView.setAdapter(mConversationArrayAdapter);
|
if (!mIsBound)
|
||||||
*/
|
doBindService();
|
||||||
|
|
||||||
// Initialize the BluetoothChatService to perform bluetooth connections
|
|
||||||
mChatService = new BluetoothChatService(getActivity(), mHandler);
|
|
||||||
|
|
||||||
mStartButton.setOnClickListener(new View.OnClickListener() {
|
mStartButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
if (mChatService != null)
|
||||||
mChatService.startIConsole();
|
mChatService.startIConsole();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mStopButton.setOnClickListener(new View.OnClickListener() {
|
mStopButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mChatService.stopIConsole();
|
if (mChatService != null)
|
||||||
|
mChatService.stopIConsole();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mDisconnectButton.setOnClickListener(new View.OnClickListener() {
|
mDisconnectButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mChatService.stop();
|
if (mChatService != null)
|
||||||
|
mChatService.stopBT();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mStartButton.setEnabled(false);
|
mStartButton.setEnabled(false);
|
||||||
mStopButton.setEnabled(false);
|
mStopButton.setEnabled(false);
|
||||||
mDisconnectButton.setEnabled(false);
|
mDisconnectButton.setEnabled(false);
|
||||||
|
mLevel.setEnabled(false);
|
||||||
|
mLevel.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mChatService != null)
|
||||||
|
mChatService.setLevel(mLevel.getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,7 +278,10 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
* @param message A string of text to send.
|
* @param message A string of text to send.
|
||||||
*/
|
*/
|
||||||
private void sendMessage(String message) {
|
private void sendMessage(String message) {
|
||||||
// Check that we're actually connected before trying anything
|
if (mChatService == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check that we're actually connected before trying anything
|
||||||
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
|
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
|
||||||
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
|
@ -263,6 +328,7 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
* The Handler that gets information back from the BluetoothChatService
|
* The Handler that gets information back from the BluetoothChatService
|
||||||
*/
|
*/
|
||||||
private final Handler mHandler = new Handler() {
|
private final Handler mHandler = new Handler() {
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
FragmentActivity activity = getActivity();
|
FragmentActivity activity = getActivity();
|
||||||
|
@ -275,12 +341,14 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
mStartButton.setEnabled(true);
|
mStartButton.setEnabled(true);
|
||||||
mStopButton.setEnabled(true);
|
mStopButton.setEnabled(true);
|
||||||
mDisconnectButton.setEnabled(true);
|
mDisconnectButton.setEnabled(true);
|
||||||
|
mLevel.setEnabled(true);
|
||||||
break;
|
break;
|
||||||
case BluetoothChatService.STATE_CONNECTING:
|
case BluetoothChatService.STATE_CONNECTING:
|
||||||
setStatus(R.string.title_connecting);
|
setStatus(R.string.title_connecting);
|
||||||
mStartButton.setEnabled(false);
|
mStartButton.setEnabled(false);
|
||||||
mStopButton.setEnabled(false);
|
mStopButton.setEnabled(false);
|
||||||
mDisconnectButton.setEnabled(false);
|
mDisconnectButton.setEnabled(false);
|
||||||
|
mLevel.setEnabled(false);
|
||||||
break;
|
break;
|
||||||
case BluetoothChatService.STATE_LISTEN:
|
case BluetoothChatService.STATE_LISTEN:
|
||||||
case BluetoothChatService.STATE_NONE:
|
case BluetoothChatService.STATE_NONE:
|
||||||
|
@ -288,19 +356,22 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
mStartButton.setEnabled(false);
|
mStartButton.setEnabled(false);
|
||||||
mStopButton.setEnabled(false);
|
mStopButton.setEnabled(false);
|
||||||
mDisconnectButton.setEnabled(false);
|
mDisconnectButton.setEnabled(false);
|
||||||
|
mLevel.setEnabled(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Constants.MESSAGE_DATA:
|
case Constants.MESSAGE_DATA:
|
||||||
|
if (!(msg.obj instanceof IConsole.Data))
|
||||||
|
return;
|
||||||
IConsole.Data data = (IConsole.Data) msg.obj;
|
IConsole.Data data = (IConsole.Data) msg.obj;
|
||||||
// FIXME
|
mSpeedText.setText(String.format("Speed\n% 3.1f", data.mSpeed10 / 10.0));
|
||||||
// insert text here
|
mPowerText.setText(String.format("Power\n% 3.1f", data.mPower10 / 10.0));
|
||||||
/*
|
mRPMText.setText(String.format("RPM\n%d", data.mRPM));
|
||||||
String dataMessage = String.format(Locale.US, "Time: %d Speed: %3.1f Power: %3.1f RPM: %d LVL: %d Dist: %4.1f Cal: %d HF: %d",
|
mDistanceText.setText(String.format("Distance\n% 3.1f", data.mDistance10 / 10.0));
|
||||||
data.mTime, data.mSpeed10 / 10.0, data.mPower10 / 10.0, data.mRPM,
|
mCaloriesText.setText(String.format("Calories\n% 3.1f", data.mSpeed10 / 10.0));
|
||||||
data.mLevel, data.mDistance10 / 10.0, data.mCalories, data.mHF);
|
mHFText.setText(String.format("Heart\n%d", data.mHF));
|
||||||
*/
|
mTimeText.setText(String.format("Time:\n%s",data.getTimeStr()));
|
||||||
//mConversationArrayAdapter.add(mConnectedDeviceName + ": " + dataMessage);
|
mLevel.setValue(data.mLevel);
|
||||||
break;
|
break;
|
||||||
case Constants.MESSAGE_WRITE:
|
case Constants.MESSAGE_WRITE:
|
||||||
//byte[] writeBuf = (byte[]) msg.obj;
|
//byte[] writeBuf = (byte[]) msg.obj;
|
||||||
|
@ -374,7 +445,8 @@ public class BluetoothChatFragment extends Fragment {
|
||||||
// Get the BluetoothDevice object
|
// Get the BluetoothDevice object
|
||||||
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
|
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
|
||||||
// Attempt to connect to the device
|
// Attempt to connect to the device
|
||||||
mChatService.connect(device);
|
if (mChatService != null)
|
||||||
|
mChatService.connect(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,20 +16,26 @@
|
||||||
|
|
||||||
package org.surfsite.iconsole;
|
package org.surfsite.iconsole;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.Service;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothSocket;
|
import android.bluetooth.BluetoothSocket;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
import org.surfsite.iconsole.common.logger.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,7 +44,7 @@ import java.util.UUID;
|
||||||
* incoming connections, a thread for connecting with a device, and a
|
* incoming connections, a thread for connecting with a device, and a
|
||||||
* thread for performing data transmissions when connected.
|
* thread for performing data transmissions when connected.
|
||||||
*/
|
*/
|
||||||
public class BluetoothChatService {
|
public class BluetoothChatService extends Service {
|
||||||
// Debugging
|
// Debugging
|
||||||
private static final String TAG = "BluetoothChatService";
|
private static final String TAG = "BluetoothChatService";
|
||||||
// Name for the SDP record when creating server socket
|
// Name for the SDP record when creating server socket
|
||||||
|
@ -49,7 +55,7 @@ public class BluetoothChatService {
|
||||||
private static final UUID SERIAL_PORT_CLASS = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
private static final UUID SERIAL_PORT_CLASS = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
||||||
// Member fields
|
// Member fields
|
||||||
private final BluetoothAdapter mAdapter;
|
private final BluetoothAdapter mAdapter;
|
||||||
private final Handler mHandler;
|
private Handler mHandler;
|
||||||
|
|
||||||
private ConnectThread mConnectThread;
|
private ConnectThread mConnectThread;
|
||||||
private ConnectedThread mConnectedThread;
|
private ConnectedThread mConnectedThread;
|
||||||
|
@ -61,60 +67,47 @@ public class BluetoothChatService {
|
||||||
public static final int STATE_LISTEN = 1; // now listening for incoming connections
|
public static final int STATE_LISTEN = 1; // now listening for incoming connections
|
||||||
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
|
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
|
||||||
public static final int STATE_CONNECTED = 3; // now connected to a remote device
|
public static final int STATE_CONNECTED = 3; // now connected to a remote device
|
||||||
|
private NotificationManager mNM;
|
||||||
|
|
||||||
/**
|
private int NOTIFICATION = R.string.local_service_started;
|
||||||
* Constructor. Prepares a new BluetoothChat session.
|
|
||||||
*
|
public BluetoothChatService() {
|
||||||
* @param context The UI Activity Context
|
super();
|
||||||
* @param handler A Handler to send messages back to the UI Activity
|
|
||||||
*/
|
|
||||||
public BluetoothChatService(Context context, Handler handler) {
|
|
||||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
mState = STATE_NONE;
|
mState = STATE_NONE;
|
||||||
mNewState = mState;
|
mNewState = mState;
|
||||||
mHandler = handler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public class BluetoothChatServiceI extends Binder {
|
||||||
* Update UI title according to the current state of the chat connection
|
BluetoothChatService getService() {
|
||||||
*/
|
return BluetoothChatService.this;
|
||||||
private synchronized void updateUserInterfaceTitle() {
|
|
||||||
mState = getState();
|
|
||||||
Log.d(TAG, "updateUserInterfaceTitle() " + mNewState + " -> " + mState);
|
|
||||||
mNewState = mState;
|
|
||||||
|
|
||||||
// Give the new state to the Handler so the UI Activity can update
|
|
||||||
mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mNewState, -1).sendToTarget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the current connection state.
|
|
||||||
*/
|
|
||||||
public synchronized int getState() {
|
|
||||||
return mState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the chat service. Specifically start AcceptThread to begin a
|
|
||||||
* session in listening (server) mode. Called by the Activity onResume()
|
|
||||||
*/
|
|
||||||
public synchronized void start() {
|
|
||||||
Log.d(TAG, "start");
|
|
||||||
|
|
||||||
// Cancel any thread attempting to make a connection
|
|
||||||
if (mConnectThread != null) {
|
|
||||||
mConnectThread.cancel();
|
|
||||||
mConnectThread = null;
|
|
||||||
}
|
}
|
||||||
|
void setHandler(Handler handler) {
|
||||||
// Cancel any thread currently running a connection
|
mHandler = handler;
|
||||||
if (mConnectedThread != null) {
|
|
||||||
mConnectedThread.cancel();
|
|
||||||
mConnectedThread = null;
|
|
||||||
}
|
}
|
||||||
// Update UI title
|
}
|
||||||
updateUserInterfaceTitle();
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
// Display a notification about us starting. We put an icon in the status bar.
|
||||||
|
showNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean startIConsole() {
|
||||||
|
return mConnectedThread.startIConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean stopIConsole() {
|
||||||
|
return mConnectedThread.stopIConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean setLevel(int level) {
|
||||||
|
return mConnectedThread.setLevel(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,6 +139,100 @@ public class BluetoothChatService {
|
||||||
updateUserInterfaceTitle();
|
updateUserInterfaceTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
Log.i(TAG, "onBind");
|
||||||
|
|
||||||
|
return mBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This is the object that receives interactions from clients. See
|
||||||
|
// RemoteService for a more complete example.
|
||||||
|
private final IBinder mBinder = new BluetoothChatServiceI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update UI title according to the current state of the chat connection
|
||||||
|
*/
|
||||||
|
private synchronized void updateUserInterfaceTitle() {
|
||||||
|
mState = getState();
|
||||||
|
Log.d(TAG, "updateUserInterfaceTitle() " + mNewState + " -> " + mState);
|
||||||
|
mNewState = mState;
|
||||||
|
|
||||||
|
// Give the new state to the Handler so the UI Activity can update
|
||||||
|
mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mNewState, -1).sendToTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current connection state.
|
||||||
|
*/
|
||||||
|
public synchronized int getState() {
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the chat service. Specifically startBT AcceptThread to begin a
|
||||||
|
* session in listening (server) mode. Called by the Activity onResume()
|
||||||
|
*/
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
Log.i(TAG, "Received onStartCommand() id " + startId + ": " + intent);
|
||||||
|
return START_NOT_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
stopBT();
|
||||||
|
// Cancel the persistent notification.
|
||||||
|
mNM.cancel(NOTIFICATION);
|
||||||
|
|
||||||
|
// Tell the user we stopped.
|
||||||
|
Log.i(TAG, "onDestroy");
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Show a notification while this service is running.
|
||||||
|
*/
|
||||||
|
private void showNotification() {
|
||||||
|
// In this sample, we'll use the same text for the ticker and the expanded notification
|
||||||
|
CharSequence text = getText(R.string.local_service_started);
|
||||||
|
|
||||||
|
// The PendingIntent to launch our activity if the user selects this notification
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||||
|
new Intent(this, MainActivity.class), 0);
|
||||||
|
|
||||||
|
// Set the info for the views that show in the notification panel.
|
||||||
|
Notification notification = new Notification.Builder(this)
|
||||||
|
.setSmallIcon(R.drawable.ic_action_device_access_bluetooth_searching) // the status icon
|
||||||
|
.setTicker(text) // the status text
|
||||||
|
.setWhen(System.currentTimeMillis()) // the time stamp
|
||||||
|
.setContentTitle(getText(R.string.local_service_label)) // the label of the entry
|
||||||
|
.setContentText(text) // the contents of the entry
|
||||||
|
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Send the notification.
|
||||||
|
mNM.notify(NOTIFICATION, notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startBT() {
|
||||||
|
Log.d(TAG, "startBT");
|
||||||
|
|
||||||
|
// Cancel any thread attempting to make a connection
|
||||||
|
if (mConnectThread != null) {
|
||||||
|
mConnectThread.cancel();
|
||||||
|
mConnectThread = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel any thread currently running a connection
|
||||||
|
if (mConnectedThread != null) {
|
||||||
|
mConnectedThread.cancel();
|
||||||
|
mConnectedThread = null;
|
||||||
|
}
|
||||||
|
// Update UI title
|
||||||
|
updateUserInterfaceTitle();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the ConnectedThread to begin managing a Bluetooth connection
|
* Start the ConnectedThread to begin managing a Bluetooth connection
|
||||||
*
|
*
|
||||||
|
@ -185,8 +272,8 @@ public class BluetoothChatService {
|
||||||
/**
|
/**
|
||||||
* Stop all threads
|
* Stop all threads
|
||||||
*/
|
*/
|
||||||
public synchronized void stop() {
|
public synchronized void stopBT() {
|
||||||
Log.d(TAG, "stop");
|
Log.d(TAG, "stopBT");
|
||||||
|
|
||||||
if (mConnectThread != null) {
|
if (mConnectThread != null) {
|
||||||
mConnectThread.cancel();
|
mConnectThread.cancel();
|
||||||
|
@ -203,13 +290,6 @@ public class BluetoothChatService {
|
||||||
updateUserInterfaceTitle();
|
updateUserInterfaceTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean startIConsole() {
|
|
||||||
return mConnectedThread.startIConsole();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean stopIConsole() {
|
|
||||||
return mConnectedThread.stopIConsole();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate that the connection attempt failed and notify the UI Activity.
|
* Indicate that the connection attempt failed and notify the UI Activity.
|
||||||
|
@ -227,7 +307,7 @@ public class BluetoothChatService {
|
||||||
updateUserInterfaceTitle();
|
updateUserInterfaceTitle();
|
||||||
|
|
||||||
// Start the service over to restart listening mode
|
// Start the service over to restart listening mode
|
||||||
BluetoothChatService.this.start();
|
BluetoothChatService.this.startBT();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,7 +326,7 @@ public class BluetoothChatService {
|
||||||
updateUserInterfaceTitle();
|
updateUserInterfaceTitle();
|
||||||
|
|
||||||
// Start the service over to restart listening mode
|
// Start the service over to restart listening mode
|
||||||
BluetoothChatService.this.start();
|
BluetoothChatService.this.startBT();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,7 +334,7 @@ public class BluetoothChatService {
|
||||||
* with a device. It runs straight through; the connection either
|
* with a device. It runs straight through; the connection either
|
||||||
* succeeds or fails.
|
* succeeds or fails.
|
||||||
*/
|
*/
|
||||||
private class ConnectThread extends Thread {
|
class ConnectThread extends Thread {
|
||||||
private final BluetoothSocket mmSocket;
|
private final BluetoothSocket mmSocket;
|
||||||
private final BluetoothDevice mmDevice;
|
private final BluetoothDevice mmDevice;
|
||||||
|
|
||||||
|
@ -318,7 +398,7 @@ public class BluetoothChatService {
|
||||||
* This thread runs during a connection with a remote device.
|
* This thread runs during a connection with a remote device.
|
||||||
* It handles all incoming and outgoing transmissions.
|
* It handles all incoming and outgoing transmissions.
|
||||||
*/
|
*/
|
||||||
private class ConnectedThread extends Thread {
|
class ConnectedThread extends Thread {
|
||||||
private final BluetoothSocket mmSocket;
|
private final BluetoothSocket mmSocket;
|
||||||
private final InputStream mmInStream;
|
private final InputStream mmInStream;
|
||||||
private final OutputStream mmOutStream;
|
private final OutputStream mmOutStream;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
|
@ -33,7 +34,6 @@ import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.surfsite.iconsole.R;
|
import org.surfsite.iconsole.R;
|
||||||
import org.surfsite.iconsole.common.logger.Log;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class DeviceListActivity extends Activity {
|
||||||
// Turn on sub-title for new devices
|
// Turn on sub-title for new devices
|
||||||
findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
|
findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// If we're already discovering, stop it
|
// If we're already discovering, stopBT it
|
||||||
if (mBtAdapter.isDiscovering()) {
|
if (mBtAdapter.isDiscovering()) {
|
||||||
mBtAdapter.cancelDiscovery();
|
mBtAdapter.cancelDiscovery();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package org.surfsite.iconsole;
|
package org.surfsite.iconsole;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import org.surfsite.iconsole.common.logger.Log;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by harald on 25.04.17.
|
* Created by harald on 25.04.17.
|
||||||
|
@ -52,7 +54,8 @@ class IConsole {
|
||||||
private final DataListener mDataListener;
|
private final DataListener mDataListener;
|
||||||
private final DebugListener mDebugListener;
|
private final DebugListener mDebugListener;
|
||||||
|
|
||||||
IConsole(InputStream inputStream, OutputStream outputStream, DataListener dataListener, DebugListener debugListener) {
|
IConsole(InputStream inputStream, OutputStream outputStream,
|
||||||
|
@Nullable DataListener dataListener, @Nullable DebugListener debugListener) {
|
||||||
this.mInputStream = inputStream;
|
this.mInputStream = inputStream;
|
||||||
this.mOutputStream = outputStream;
|
this.mOutputStream = outputStream;
|
||||||
this.mDataListener = dataListener;
|
this.mDataListener = dataListener;
|
||||||
|
@ -90,6 +93,25 @@ class IConsole {
|
||||||
this.mPower10 = 100 * (bytes[16] - 1) + bytes[17] - 1;
|
this.mPower10 = 100 * (bytes[16] - 1) + bytes[17] - 1;
|
||||||
this.mLevel = bytes[18] -1;
|
this.mLevel = bytes[18] -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getTimeStr() {
|
||||||
|
long day, hour, min, sec;
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
day = mTime / 60 / 60 / 24;
|
||||||
|
if (day > 0)
|
||||||
|
b.append(String.format(Locale.US, "%02d:", day));
|
||||||
|
hour = (mTime % (60 * 60 * 24)) / 60 / 60;
|
||||||
|
if (hour > 0)
|
||||||
|
if (day > 0)
|
||||||
|
b.append(String.format(Locale.US, "%02d:", hour));
|
||||||
|
else
|
||||||
|
b.append(String.format(Locale.US, "%d:", hour));
|
||||||
|
min = (mTime % (60 * 60)) / 60;
|
||||||
|
sec = mTime % 60;
|
||||||
|
b.append(String.format(Locale.US, "%02d:%02d", min, sec));
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DataListener {
|
interface DataListener {
|
||||||
|
@ -127,7 +149,7 @@ class IConsole {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean send(byte[] packet, byte expect, int plen) throws IOException {
|
private boolean send(byte[] packet, byte expect, int plen) throws IOException {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
if ((now - mTimesent) < ((mCurrentState == State.READ) ? 500 : 200)) {
|
if ((now - mTimesent) < ((mCurrentState == State.READ) ? 500 : 200)) {
|
||||||
|
@ -136,6 +158,7 @@ class IConsole {
|
||||||
|
|
||||||
// Flush input stream
|
// Flush input stream
|
||||||
try {
|
try {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
mInputStream.skip(mInputStream.available());
|
mInputStream.skip(mInputStream.available());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
; // ignore
|
; // ignore
|
||||||
|
@ -263,7 +286,8 @@ class IConsole {
|
||||||
//Log.d(TAG, "processIOAck next state");
|
//Log.d(TAG, "processIOAck next state");
|
||||||
|
|
||||||
if(mCurrentState == State.READ)
|
if(mCurrentState == State.READ)
|
||||||
mDataListener.onData(new Data(got));
|
if (null != mDataListener)
|
||||||
|
mDataListener.onData(new Data(got));
|
||||||
|
|
||||||
mCurrentState = mNextState;
|
mCurrentState = mNextState;
|
||||||
switch (mNextState) {
|
switch (mNextState) {
|
||||||
|
@ -318,7 +342,8 @@ class IConsole {
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "processIO", e);
|
Log.e(TAG, "processIO", e);
|
||||||
mDataListener.onError(e);
|
if (null != mDataListener)
|
||||||
|
mDataListener.onError(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,22 @@
|
||||||
|
|
||||||
package org.surfsite.iconsole;
|
package org.surfsite.iconsole;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.ViewAnimator;
|
import android.widget.ViewAnimator;
|
||||||
|
|
||||||
import org.surfsite.iconsole.R;
|
|
||||||
import org.surfsite.iconsole.common.activities.SampleActivityBase;
|
|
||||||
import org.surfsite.iconsole.common.logger.Log;
|
|
||||||
import org.surfsite.iconsole.common.logger.LogFragment;
|
|
||||||
import org.surfsite.iconsole.common.logger.LogWrapper;
|
|
||||||
import org.surfsite.iconsole.common.logger.MessageOnlyLogFilter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple launcher activity containing a summary sample description, sample log and a custom
|
* A simple launcher activity containing a summary sample description, sample log and a custom
|
||||||
|
@ -37,7 +41,7 @@ import org.surfsite.iconsole.common.logger.MessageOnlyLogFilter;
|
||||||
* For devices with displays with a width of 720dp or greater, the sample log is always visible,
|
* For devices with displays with a width of 720dp or greater, the sample log is always visible,
|
||||||
* on other devices it's visibility is controlled by an item on the Action Bar.
|
* on other devices it's visibility is controlled by an item on the Action Bar.
|
||||||
*/
|
*/
|
||||||
public class MainActivity extends SampleActivityBase {
|
public class MainActivity extends FragmentActivity {
|
||||||
|
|
||||||
public static final String TAG = "MainActivity";
|
public static final String TAG = "MainActivity";
|
||||||
|
|
||||||
|
@ -55,6 +59,12 @@ public class MainActivity extends SampleActivityBase {
|
||||||
transaction.replace(R.id.sample_content_fragment, fragment);
|
transaction.replace(R.id.sample_content_fragment, fragment);
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
}
|
}
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
ComponentName componentName = startService(new Intent(this, BluetoothChatService.class));
|
||||||
|
if (componentName == null)
|
||||||
|
Log.e(TAG, "componentName == null");
|
||||||
|
else
|
||||||
|
Log.i(TAG, "Service started");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,7 +76,7 @@ public class MainActivity extends SampleActivityBase {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
|
MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
|
||||||
logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
|
//logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
|
||||||
logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
|
logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
|
||||||
|
|
||||||
return super.onPrepareOptionsMenu(menu);
|
return super.onPrepareOptionsMenu(menu);
|
||||||
|
@ -90,9 +100,7 @@ public class MainActivity extends SampleActivityBase {
|
||||||
*/
|
*/
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/** Create a chain of targets that will receive log data */
|
|
||||||
@Override
|
|
||||||
public void initializeLogging() {
|
public void initializeLogging() {
|
||||||
// Wraps Android's native log framework.
|
// Wraps Android's native log framework.
|
||||||
LogWrapper logWrapper = new LogWrapper();
|
LogWrapper logWrapper = new LogWrapper();
|
||||||
|
@ -110,4 +118,5 @@ public class MainActivity extends SampleActivityBase {
|
||||||
|
|
||||||
Log.i(TAG, "Ready");
|
Log.i(TAG, "Ready");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2013 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.surfsite.iconsole.common.activities;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.FragmentActivity;
|
|
||||||
|
|
||||||
import org.surfsite.iconsole.common.logger.Log;
|
|
||||||
import org.surfsite.iconsole.common.logger.LogWrapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base launcher activity, to handle most of the common plumbing for samples.
|
|
||||||
*/
|
|
||||||
public class SampleActivityBase extends FragmentActivity {
|
|
||||||
|
|
||||||
public static final String TAG = "SampleActivityBase";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
initializeLogging();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set up targets to receive log data */
|
|
||||||
public void initializeLogging() {
|
|
||||||
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
|
|
||||||
// Wraps Android's native log framework
|
|
||||||
LogWrapper logWrapper = new LogWrapper();
|
|
||||||
Log.setLogNode(logWrapper);
|
|
||||||
|
|
||||||
Log.i(TAG, "Ready");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,236 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2013 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.surfsite.iconsole.common.logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class for a list (or tree) of LoggerNodes.
|
|
||||||
*
|
|
||||||
* <p>When this is set as the head of the list,
|
|
||||||
* an instance of it can function as a drop-in replacement for {@link android.util.Log}.
|
|
||||||
* Most of the methods in this class server only to map a method call in Log to its equivalent
|
|
||||||
* in LogNode.</p>
|
|
||||||
*/
|
|
||||||
public class Log {
|
|
||||||
// Grabbing the native values from Android's native logging facilities,
|
|
||||||
// to make for easy migration and interop.
|
|
||||||
public static final int NONE = -1;
|
|
||||||
public static final int VERBOSE = android.util.Log.VERBOSE;
|
|
||||||
public static final int DEBUG = android.util.Log.DEBUG;
|
|
||||||
public static final int INFO = android.util.Log.INFO;
|
|
||||||
public static final int WARN = android.util.Log.WARN;
|
|
||||||
public static final int ERROR = android.util.Log.ERROR;
|
|
||||||
public static final int ASSERT = android.util.Log.ASSERT;
|
|
||||||
|
|
||||||
// Stores the beginning of the LogNode topology.
|
|
||||||
private static LogNode mLogNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next LogNode in the linked list.
|
|
||||||
*/
|
|
||||||
public static LogNode getLogNode() {
|
|
||||||
return mLogNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the LogNode data will be sent to.
|
|
||||||
*/
|
|
||||||
public static void setLogNode(LogNode node) {
|
|
||||||
mLogNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
|
||||||
* be chained to the end of the LogNode as desired.
|
|
||||||
*
|
|
||||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void println(int priority, String tag, String msg, Throwable tr) {
|
|
||||||
if (mLogNode != null) {
|
|
||||||
mLogNode.println(priority, tag, msg, tr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructs the LogNode to print the log data provided. Other LogNodes can
|
|
||||||
* be chained to the end of the LogNode as desired.
|
|
||||||
*
|
|
||||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged. The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void println(int priority, String tag, String msg) {
|
|
||||||
println(priority, tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at VERBOSE priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void v(String tag, String msg, Throwable tr) {
|
|
||||||
println(VERBOSE, tag, msg, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at VERBOSE priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void v(String tag, String msg) {
|
|
||||||
v(tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at DEBUG priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void d(String tag, String msg, Throwable tr) {
|
|
||||||
println(DEBUG, tag, msg, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at DEBUG priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void d(String tag, String msg) {
|
|
||||||
d(tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at INFO priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void i(String tag, String msg, Throwable tr) {
|
|
||||||
println(INFO, tag, msg, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at INFO priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void i(String tag, String msg) {
|
|
||||||
i(tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at WARN priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void w(String tag, String msg, Throwable tr) {
|
|
||||||
println(WARN, tag, msg, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at WARN priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void w(String tag, String msg) {
|
|
||||||
w(tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at WARN priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void w(String tag, Throwable tr) {
|
|
||||||
w(tag, null, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at ERROR priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void e(String tag, String msg, Throwable tr) {
|
|
||||||
println(ERROR, tag, msg, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at ERROR priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void e(String tag, String msg) {
|
|
||||||
e(tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at ASSERT priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void wtf(String tag, String msg, Throwable tr) {
|
|
||||||
println(ASSERT, tag, msg, tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at ASSERT priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged.
|
|
||||||
*/
|
|
||||||
public static void wtf(String tag, String msg) {
|
|
||||||
wtf(tag, msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message at ASSERT priority.
|
|
||||||
*
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public static void wtf(String tag, Throwable tr) {
|
|
||||||
wtf(tag, null, tr);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2013 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Copyright 2013 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.surfsite.iconsole.common.logger;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ScrollView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple fraggment which contains a LogView and uses is to output log data it receives
|
|
||||||
* through the LogNode interface.
|
|
||||||
*/
|
|
||||||
public class LogFragment extends Fragment {
|
|
||||||
|
|
||||||
private LogView mLogView;
|
|
||||||
private ScrollView mScrollView;
|
|
||||||
|
|
||||||
public LogFragment() {}
|
|
||||||
|
|
||||||
public View inflateViews() {
|
|
||||||
mScrollView = new ScrollView(getActivity());
|
|
||||||
ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
|
||||||
mScrollView.setLayoutParams(scrollParams);
|
|
||||||
|
|
||||||
mLogView = new LogView(getActivity());
|
|
||||||
ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
|
|
||||||
logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
|
||||||
mLogView.setLayoutParams(logParams);
|
|
||||||
mLogView.setClickable(true);
|
|
||||||
mLogView.setFocusable(true);
|
|
||||||
mLogView.setTypeface(Typeface.MONOSPACE);
|
|
||||||
|
|
||||||
// Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
|
|
||||||
int paddingDips = 16;
|
|
||||||
double scale = getResources().getDisplayMetrics().density;
|
|
||||||
int paddingPixels = (int) ((paddingDips * (scale)) + .5);
|
|
||||||
mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
|
|
||||||
mLogView.setCompoundDrawablePadding(paddingPixels);
|
|
||||||
|
|
||||||
mLogView.setGravity(Gravity.BOTTOM);
|
|
||||||
mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
|
|
||||||
|
|
||||||
mScrollView.addView(mLogView);
|
|
||||||
return mScrollView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
View result = inflateViews();
|
|
||||||
|
|
||||||
mLogView.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogView getLogView() {
|
|
||||||
return mLogView;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.surfsite.iconsole.common.logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic interface for a logging system that can output to one or more targets.
|
|
||||||
* Note that in addition to classes that will output these logs in some format,
|
|
||||||
* one can also implement this interface over a filter and insert that in the chain,
|
|
||||||
* such that no targets further down see certain data, or see manipulated forms of the data.
|
|
||||||
* You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
|
|
||||||
* it received to HTML and sent it along to the next node in the chain, without printing it
|
|
||||||
* anywhere.
|
|
||||||
*/
|
|
||||||
public interface LogNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructs first LogNode in the list to print the log data provided.
|
|
||||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged. The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
public void println(int priority, String tag, String msg, Throwable tr);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,145 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2013 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.surfsite.iconsole.common.logger;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.*;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
/** Simple TextView which is used to output log data received through the LogNode interface.
|
|
||||||
*/
|
|
||||||
public class LogView extends TextView implements LogNode {
|
|
||||||
|
|
||||||
public LogView(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogView(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogView(Context context, AttributeSet attrs, int defStyle) {
|
|
||||||
super(context, attrs, defStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats the log data and prints it out to the LogView.
|
|
||||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged. The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
|
||||||
|
|
||||||
|
|
||||||
String priorityStr = null;
|
|
||||||
|
|
||||||
// For the purposes of this View, we want to print the priority as readable text.
|
|
||||||
switch(priority) {
|
|
||||||
case android.util.Log.VERBOSE:
|
|
||||||
priorityStr = "VERBOSE";
|
|
||||||
break;
|
|
||||||
case android.util.Log.DEBUG:
|
|
||||||
priorityStr = "DEBUG";
|
|
||||||
break;
|
|
||||||
case android.util.Log.INFO:
|
|
||||||
priorityStr = "INFO";
|
|
||||||
break;
|
|
||||||
case android.util.Log.WARN:
|
|
||||||
priorityStr = "WARN";
|
|
||||||
break;
|
|
||||||
case android.util.Log.ERROR:
|
|
||||||
priorityStr = "ERROR";
|
|
||||||
break;
|
|
||||||
case android.util.Log.ASSERT:
|
|
||||||
priorityStr = "ASSERT";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handily, the Log class has a facility for converting a stack trace into a usable string.
|
|
||||||
String exceptionStr = null;
|
|
||||||
if (tr != null) {
|
|
||||||
exceptionStr = android.util.Log.getStackTraceString(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take the priority, tag, message, and exception, and concatenate as necessary
|
|
||||||
// into one usable line of text.
|
|
||||||
final StringBuilder outputBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
String delimiter = "\t";
|
|
||||||
appendIfNotNull(outputBuilder, priorityStr, delimiter);
|
|
||||||
appendIfNotNull(outputBuilder, tag, delimiter);
|
|
||||||
appendIfNotNull(outputBuilder, msg, delimiter);
|
|
||||||
appendIfNotNull(outputBuilder, exceptionStr, delimiter);
|
|
||||||
|
|
||||||
// In case this was originally called from an AsyncTask or some other off-UI thread,
|
|
||||||
// make sure the update occurs within the UI thread.
|
|
||||||
((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Display the text we just generated within the LogView.
|
|
||||||
appendToLog(outputBuilder.toString());
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
|
|
||||||
if (mNext != null) {
|
|
||||||
mNext.println(priority, tag, msg, tr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogNode getNext() {
|
|
||||||
return mNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNext(LogNode node) {
|
|
||||||
mNext = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
|
|
||||||
* the logger takes so many arguments that might be null, this method helps cut out some of the
|
|
||||||
* agonizing tedium of writing the same 3 lines over and over.
|
|
||||||
* @param source StringBuilder containing the text to append to.
|
|
||||||
* @param addStr The String to append
|
|
||||||
* @param delimiter The String to separate the source and appended strings. A tab or comma,
|
|
||||||
* for instance.
|
|
||||||
* @return The fully concatenated String as a StringBuilder
|
|
||||||
*/
|
|
||||||
private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
|
|
||||||
if (addStr != null) {
|
|
||||||
if (addStr.length() == 0) {
|
|
||||||
delimiter = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return source.append(addStr).append(delimiter);
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The next LogNode in the chain.
|
|
||||||
LogNode mNext;
|
|
||||||
|
|
||||||
/** Outputs the string as a new line of log data in the LogView. */
|
|
||||||
public void appendToLog(String s) {
|
|
||||||
append("\n" + s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.surfsite.iconsole.common.logger;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class which wraps Android's native Log utility in the Logger interface. This way
|
|
||||||
* normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
|
|
||||||
*/
|
|
||||||
public class LogWrapper implements LogNode {
|
|
||||||
|
|
||||||
// For piping: The next node to receive Log data after this one has done its work.
|
|
||||||
private LogNode mNext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next LogNode in the linked list.
|
|
||||||
*/
|
|
||||||
public LogNode getNext() {
|
|
||||||
return mNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the LogNode data will be sent to..
|
|
||||||
*/
|
|
||||||
public void setNext(LogNode node) {
|
|
||||||
mNext = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints data out to the console using Android's native log mechanism.
|
|
||||||
* @param priority Log level of the data being logged. Verbose, Error, etc.
|
|
||||||
* @param tag Tag for for the log data. Can be used to organize log statements.
|
|
||||||
* @param msg The actual message to be logged. The actual message to be logged.
|
|
||||||
* @param tr If an exception was thrown, this can be sent along for the logging facilities
|
|
||||||
* to extract and print useful information.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
|
||||||
// There actually are log methods that don't take a msg parameter. For now,
|
|
||||||
// if that's the case, just convert null to the empty string and move on.
|
|
||||||
String useMsg = msg;
|
|
||||||
if (useMsg == null) {
|
|
||||||
useMsg = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// If an exeption was provided, convert that exception to a usable string and attach
|
|
||||||
// it to the end of the msg method.
|
|
||||||
if (tr != null) {
|
|
||||||
msg += "\n" + Log.getStackTraceString(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is functionally identical to Log.x(tag, useMsg);
|
|
||||||
// For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
|
|
||||||
Log.println(priority, tag, useMsg);
|
|
||||||
|
|
||||||
// If this isn't the last node in the chain, move things along.
|
|
||||||
if (mNext != null) {
|
|
||||||
mNext.println(priority, tag, msg, tr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2013 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.surfsite.iconsole.common.logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple {@link LogNode} filter, removes everything except the message.
|
|
||||||
* Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
|
|
||||||
* just easy-to-read message updates as they're happening.
|
|
||||||
*/
|
|
||||||
public class MessageOnlyLogFilter implements LogNode {
|
|
||||||
|
|
||||||
LogNode mNext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes the "next" LogNode as a parameter, to simplify chaining.
|
|
||||||
*
|
|
||||||
* @param next The next LogNode in the pipeline.
|
|
||||||
*/
|
|
||||||
public MessageOnlyLogFilter(LogNode next) {
|
|
||||||
mNext = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageOnlyLogFilter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void println(int priority, String tag, String msg, Throwable tr) {
|
|
||||||
if (mNext != null) {
|
|
||||||
getNext().println(Log.NONE, null, msg, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next LogNode in the chain.
|
|
||||||
*/
|
|
||||||
public LogNode getNext() {
|
|
||||||
return mNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the LogNode data will be sent to..
|
|
||||||
*/
|
|
||||||
public void setNext(LogNode node) {
|
|
||||||
mNext = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -20,48 +20,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/sample_main_layout">
|
android:id="@+id/sample_main_layout">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/sample_output"
|
|
||||||
android:layout_width="0px"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
style="@style/Widget.SampleMessageTile"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/Widget.SampleMessage"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingLeft="@dimen/margin_medium"
|
|
||||||
android:paddingRight="@dimen/margin_medium"
|
|
||||||
android:paddingTop="@dimen/margin_large"
|
|
||||||
android:paddingBottom="@dimen/margin_large"
|
|
||||||
android:text="@string/intro_message" />
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="@android:color/darker_gray" />
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:name="org.surfsite.iconsole.common.logger.LogFragment"
|
|
||||||
android:id="@+id/log_fragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0px"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="1dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@android:color/darker_gray" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/sample_content_fragment"
|
android:id="@+id/sample_content_fragment"
|
||||||
android:layout_weight="2"
|
android:layout_weight="2"
|
||||||
|
|
|
@ -20,28 +20,9 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/sample_main_layout">
|
android:id="@+id/sample_main_layout">
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/sample_output"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0px"
|
|
||||||
android:layout_weight="1">
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:name="org.surfsite.iconsole.common.logger.LogFragment"
|
|
||||||
android:id="@+id/log_fragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="@android:color/darker_gray" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/sample_content_fragment"
|
android:id="@+id/sample_content_fragment"
|
||||||
android:layout_weight="2"
|
android:layout_weight="4"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0px" />
|
android:layout_height="0px" />
|
||||||
|
|
||||||
|
|
|
@ -22,147 +22,272 @@
|
||||||
tools:layout_editor_absoluteY="0dp"
|
tools:layout_editor_absoluteY="0dp"
|
||||||
tools:layout_editor_absoluteX="0dp" >
|
tools:layout_editor_absoluteX="0dp" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView8"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="RPM"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/RPM"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline6"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView7"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Calories"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/Calories"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline6"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView6"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Heart"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/Heart"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView5"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Distance"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/Distance"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline5"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView4"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Speed"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/Speed"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Power"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/Power"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline5"
|
||||||
|
app:layout_constraintVertical_bias="0.333" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Time"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/Time"
|
||||||
|
app:layout_constraintHorizontal_bias="0.501"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/Level"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/guideline2"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/guideline"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
||||||
|
app:layout_constraintHorizontal_bias="0.484"
|
||||||
|
app:layout_constraintVertical_bias="0.671" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/Time"
|
android:id="@+id/Time"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/time_n00_00_00"
|
android:text="@string/time_n00_00_00"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline5"
|
app:layout_constraintBottom_toTopOf="@+id/guideline5"
|
||||||
|
app:layout_constraintHorizontal_bias="0.501"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="0.513"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
app:layout_constraintRight_toRightOf="parent" />
|
|
||||||
|
|
||||||
<NumberPicker
|
|
||||||
android:id="@+id/Level"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="@+id/guideline"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
android:layout_marginBottom="16dp"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline2"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
|
||||||
android:layout_marginTop="16dp" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/Speed"
|
android:id="@+id/Speed"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/speed_n0_0_km_h"
|
android:text="@string/speed_n0_0_km_h"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
android:layout_marginBottom="16dp"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline6"
|
app:layout_constraintBottom_toTopOf="@+id/guideline6"
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||||
android:layout_marginRight="16dp" />
|
app:layout_constraintTop_toTopOf="@+id/guideline4" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/Power"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/power_n0_0_w"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline5"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline4" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/RPM"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:text="@string/rpm_n0"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline6"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline2" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/Distance"
|
android:id="@+id/Power"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:text="@string/distance_n0_0_km"
|
android:layout_marginLeft="16dp"
|
||||||
android:textAlignment="center"
|
android:layout_marginRight="16dp"
|
||||||
android:gravity="center"
|
android:layout_marginStart="16dp"
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline5"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:fontFamily="monospace"
|
||||||
android:layout_marginLeft="16dp"
|
android:gravity="center"
|
||||||
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
android:text="@string/power_n0_0_w"
|
||||||
android:layout_marginBottom="16dp"
|
android:textAlignment="center"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
app:layout_constraintVertical_bias="0.538"
|
android:textStyle="bold"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||||
android:layout_marginRight="16dp" />
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline5" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/Calories"
|
android:id="@+id/RPM"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:text="@string/calories_n0_cal"
|
android:layout_marginStart="16dp"
|
||||||
android:textAlignment="center"
|
android:layout_marginTop="16dp"
|
||||||
android:gravity="center"
|
android:fontFamily="monospace"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
android:gravity="center"
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline6"
|
android:text="@string/rpm_n0"
|
||||||
android:layout_marginLeft="16dp"
|
android:textAlignment="center"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
app:layout_constraintHorizontal_bias="0.507"
|
android:textStyle="bold"
|
||||||
android:layout_marginBottom="16dp"
|
app:layout_constraintBottom_toTopOf="@+id/guideline2"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline2" />
|
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline6" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/Heart"
|
android:id="@+id/Distance"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:text="@string/heart_n0"
|
android:layout_marginLeft="16dp"
|
||||||
android:textAlignment="center"
|
android:layout_marginRight="16dp"
|
||||||
android:gravity="center"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginTop="16dp"
|
||||||
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
android:fontFamily="monospace"
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
android:gravity="center"
|
||||||
android:layout_marginTop="16dp"
|
android:text="@string/distance_n0_0_km"
|
||||||
android:layout_marginBottom="16dp"
|
android:textAlignment="center"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/guideline6"
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
app:layout_constraintVertical_bias="0.461"
|
android:textStyle="bold"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
app:layout_constraintBottom_toTopOf="@+id/guideline4"
|
||||||
android:layout_marginRight="16dp" />
|
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline5"
|
||||||
|
app:layout_constraintVertical_bias="0.538" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/Calories"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/calories_n0_cal"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/guideline2"
|
||||||
|
app:layout_constraintHorizontal_bias="0.507"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline6" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/Heart"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/heart_n0"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/guideline6"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/guideline3"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/guideline"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline4"
|
||||||
|
app:layout_constraintVertical_bias="0.461" />
|
||||||
|
|
||||||
<android.support.constraint.Guideline
|
<android.support.constraint.Guideline
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -235,58 +360,58 @@
|
||||||
tools:layout_editor_absoluteX="0dp" />
|
tools:layout_editor_absoluteX="0dp" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/guideline2">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:layout_weight="1" />
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/guideline2"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginEnd="16dp">
|
|
||||||
|
|
||||||
<Space
|
<Button
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/button_start"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="1" />
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/start" />
|
||||||
|
|
||||||
<Button
|
<Space
|
||||||
android:id="@+id/button_start"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="1" />
|
||||||
android:text="@string/start" />
|
|
||||||
|
|
||||||
<Space
|
<Button
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/button_stop"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="1" />
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/stop" />
|
||||||
|
|
||||||
<Button
|
<Space
|
||||||
android:id="@+id/button_stop"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="4" />
|
||||||
android:text="@string/stop" />
|
|
||||||
|
|
||||||
<Space
|
<Button
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/button_disconnect"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="1" />
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/disconnect" />
|
||||||
|
|
||||||
<Button
|
<Space
|
||||||
android:id="@+id/button_disconnect"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="1" />
|
||||||
android:text="@string/disconnect" />
|
</LinearLayout>
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
|
@ -39,14 +39,16 @@
|
||||||
<string name="start">Start</string>
|
<string name="start">Start</string>
|
||||||
<string name="stop">Stop</string>
|
<string name="stop">Stop</string>
|
||||||
<string name="disconnect">Disconnect</string>
|
<string name="disconnect">Disconnect</string>
|
||||||
<string name="time_n00_00_00">Time\n00:00:00</string>
|
<string name="time_n00_00_00">00:00:00</string>
|
||||||
<string name="speed_n0_0_km_h">Speed\n0.0 km/h</string>
|
<string name="speed_n0_0_km_h">0.0</string>
|
||||||
<string name="rpm_n0">RPM\n0</string>
|
<string name="rpm_n0">0</string>
|
||||||
<string name="level_n1">Level\n1</string>
|
<string name="level_n1">Level\n1</string>
|
||||||
<string name="distance_n0_0_km">Distance\n0.0 km</string>
|
<string name="distance_n0_0_km">0.0</string>
|
||||||
<string name="calories_n0_cal">Calories\n0 Cal</string>
|
<string name="calories_n0_cal">0</string>
|
||||||
<string name="heart_n0">Heart\n0</string>
|
<string name="heart_n0">0</string>
|
||||||
<string name="power_n0_0_w">Power\n0.0 W</string>
|
<string name="power_n0_0_w">0.0</string>
|
||||||
<string name="level">Level</string>
|
<string name="level">Level</string>
|
||||||
|
<string name="local_service_started">iConsole Bluetooth active</string>
|
||||||
|
<string name="local_service_label">OpeniConsole</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -38,5 +38,4 @@
|
||||||
<item name="android:shadowDy">-3.5</item>
|
<item name="android:shadowDy">-3.5</item>
|
||||||
<item name="android:shadowRadius">2</item>
|
<item name="android:shadowRadius">2</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue