package com.example.focus; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Random; import java.util.TimeZone; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import android.app.Activity; import android.app.AlertDialog; import android.app.Application; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.preference.PreferenceManager; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.example.focus.circularPB.CircularProgressBar; import com.testflightapp.lib.TestFlight; public class MainActivity extends Activity implements OnClickListener { // **********************************************RotaryKnob********************************************** private ImageView ivGauge; private TextView tvValue; private TextView tvText; private RelativeLayout diagramLayout; private ImageView ivGaugeDiagram; private DrawDiagram dd; private ImageView ivKnob; // constants static final float initRotateAngle = 190f; static final float angleDiapazon = 340f; // measure of value = 10 seconds static final float minValue = 30f; // 5 minutes static final float maxValue = 240f; // 40 minutes static final long measure = 10000L; // 10 seconds = 10000 milliseconds // constants private static Bitmap imageOriginal, imageScaled; private static Matrix matrix; private int dialerHeight, dialerWidth; private double startAngle; private double currentAngle; // division of scale private float division; private float startValue = minValue; private float currentValue = minValue; private SimpleDateFormat dateFormat; private boolean knobOn = false; private float topY; private float bottomY; private float touchX; private float touchY; private float touchLayoutX; private float touchLayoutY; private boolean isRotate = false; // **********************************************RotaryKnob********************************************** private enum State { CONNECTED, DISCONNECTED, WORKING, WAITING, KNOB_ROTATING, BONDED, UNBONDED }; private State previousState; private State currentState = State.DISCONNECTED; public static final String TAG = "MainActivity"; private static final int REQUEST_ENABLE_BT = 2; ImageButton ibSettings; ImageButton ibBT; ImageButton ibChat; ImageView ivBattery; TextView device; Button discoverServices; Button connect; Button disconnect; Button unpair; private static boolean WITH_BUTTONS = true; // **********************************************Gauge // Start********************************************* private static final long SECOND = 1000; private static final int DEGREES_IN_CIRCLE = 360; private static final float ONE_HOUR = 360f; private static final int START_ANGLE = 109; private static final int END_ANGLE = 431; ImageView gauge; // **********************************************Gauge // Start********************************************* Timer timer; ChangeProgress task; Intent intent; private WorkableService mService = null; private BluetoothDevice mDevice = null; private BluetoothAdapter mBtAdapter = null; private SharedPreferences mSharedPreferences = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // **********************************************RotaryKnob********************************************** initializeRotatyKnob(); // **********************************************RotaryKnob********************************************** ibSettings = (ImageButton) findViewById(R.id.ibSettings); ibBT = (ImageButton) findViewById(R.id.ibBT); ibChat = (ImageButton) findViewById(R.id.ibChat); ivBattery = (ImageView) findViewById(R.id.ivBattery); device = (TextView) findViewById(R.id.textView2); discoverServices = (Button) findViewById(R.id.button1); connect = (Button) findViewById(R.id.button2); disconnect = (Button) findViewById(R.id.button3); unpair = (Button) findViewById(R.id.button4); if (WITH_BUTTONS) { connect.setOnClickListener(this); disconnect.setOnClickListener(this); discoverServices.setOnClickListener(this); unpair.setOnClickListener(this); } else { connect.setVisibility(View.INVISIBLE); discoverServices.setVisibility(View.INVISIBLE); device.setVisibility(View.INVISIBLE); disconnect.setVisibility(View.INVISIBLE); unpair.setVisibility(View.INVISIBLE); } // // -------------------------------------------------------------- ibSettings.setOnClickListener(this); ibBT.setOnClickListener(this); ibChat.setOnClickListener(this); final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBtAdapter = bluetoothManager.getAdapter(); if (mBtAdapter == null) { Toast.makeText(this, "OnCreate() >>>> Bluetooth is not available", Toast.LENGTH_LONG).show(); finish(); return; } init(); setState(State.DISCONNECTED); if (Debugger.TESTFLIGHT) { // initialize the TestFlight Application app = getApplication(); TestFlight.takeOff(app, Debugger.TESTFLIGHT_TOKEN); } } /** * Do actions when knob turn on or turn off */ private void knobStateChange() { // Debug.startMethodTracing("focus"); if (knobOn == true) { Debugger.d(TAG, "KnobStateChange() >>>> KnobOn"); // displayImageView(); // Convert time to byte array and write into array short time = (short) (currentValue * 10); byte[] value = ByteBuffer.allocate(2).putShort(time).array(); // putInt(progress).array(); byte temp = value[0]; value[0] = value[1]; value[1] = temp; mService.writeCharacteristic(WorkableService.TIME_IN_ACTIVE_MODE, value); setState(State.WORKING); // changeOrangeGauge(false); // knob is turned on; final CircularProgressBar progress; progress = createProgressBar(); // this should be placed here. without it, displays incorrect gauge.setImageDrawable(getApplicationContext().getResources() .getDrawable(R.drawable.gauge_blue_empty)); timer = new Timer(); final int delay = (int) (currentValue * measure / (END_ANGLE - START_ANGLE)); if (timer != null) { runOnUiThread(new Runnable() { @Override public void run() { timer.schedule(new ReadActualLevelCharacteristic(), CommonValues.READ_TIME, CommonValues.READ_TIME); task = new ChangeProgress(gauge, progress, START_ANGLE, END_ANGLE, true); timer.scheduleAtFixedRate(task, delay, delay); // change timer label every second timer.scheduleAtFixedRate(new ChangeTimeLabel(tvValue, (long) currentValue * measure), SECOND, SECOND); gauge.setVisibility(View.VISIBLE); } }); if (mSharedPreferences != null) { int mode = mSharedPreferences.getInt( CommonValues.ACTIVE_MODE, 0); if (mode >= 0) mService.writeCharacteristic(WorkableService.MODE, (byte) (mode + 2)); } } // startDrawingDiagram(); } else { Debugger.d(TAG, "KnobStateChange() >>>> KnobOff"); if (timer != null) { task.setCanceled(true); // timer.cancel(); // will do in setState. Debugger.d(TAG, "KnobStateChange() >>>> timer.Cancel()"); } setState(State.CONNECTED); // resetTime(); if (mService != null) { Debugger.d(TAG, "KnobStateChange() >>>> Set device mode to PAIRED(1)"); mService.writeCharacteristic(WorkableService.MODE, (byte) CommonValues.PAIRED); } else { Debugger.e(TAG, "KnobStateChange() >>>> KnobOff() - mService == null"); } // stopDrawingDiagram(); } } // two methods to emulate diagram drawing // private void stopDrawingDiagram() { // // TODO Auto-generated method stub // if (timer2 != null) // timer2.cancel(); // } // // Timer timer2 = null; // // private void startDrawingDiagram() { // // TODO Auto-generated method stub // if (timer2 == null) // timer2 = new Timer(); // timer2.scheduleAtFixedRate(new TimerTask() { // // @Override // public void run() { // // TODO Auto-generated method stub // Random rand = new Random(); // short value = (short) rand.nextInt(150); // dd.drawLine(value); // } // }, 0, 100); // } protected CircularProgressBar createProgressBar() { final CircularProgressBar progress; Drawable d = gauge.getDrawable(); int width = gauge.getWidth(); int height = gauge.getHeight(); d.setBounds(0, 0, width, height); Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); d.draw(c); progress = new CircularProgressBar(b, (int) width / 2, (int) height / 2, (int) width / 2, (int) (width * 0.5 * 0.6)); return progress; // return null; } private void init() { Intent bindIntent = new Intent(this, WorkableService.class); startService(bindIntent); bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE); IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); this.registerReceiver(proximityStatusChangeReceiver, filter); mSharedPreferences = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.ibSettings: // Button Settings intent = new Intent(this, SettingsActivity.class); if (mDevice != null) { intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice.getAddress()); } startActivity(intent); break; case R.id.ibBT: // Button BT if (!mBtAdapter.isEnabled()) { Debugger.e(TAG, "onClick() >>>> BT not enabled yet"); intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(intent, REQUEST_ENABLE_BT); } else { if (mDevice == null) { Intent newIntent = new Intent(this, DevicesActivity.class); startActivityForResult(newIntent, CommonValues.REQUEST_SELECT_DEVICE); } else { if (currentState == State.CONNECTED && mService != null) { Debugger.d(TAG, "onClick() >>>> Bluetooth Button. state - Connected. Disconnecting..."); mService.disconnect(); mDevice = null; } if (mDevice != null && mService != null && currentState != State.CONNECTED) { mService.connect(mDevice); } } } break; case R.id.ibChat: // Button Chat break; case R.id.button1: mService.discoverServices(); break; case R.id.button2: mService.connect(mDevice); break; case R.id.button3: mService.disconnect(); break; case R.id.button4: removeBond(mDevice); default: break; } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case CommonValues.REQUEST_SELECT_DEVICE: if (resultCode == Activity.RESULT_OK && data != null) { String deviceAddress = data .getStringExtra(BluetoothDevice.EXTRA_DEVICE); if (mBtAdapter != null) { mDevice = mBtAdapter.getRemoteDevice(deviceAddress); // mService.connect(mDevice); int state = mDevice.getBondState(); if (state == BluetoothDevice.BOND_NONE) { Debugger.d(TAG, "onActivityResult() >>>> Device is not BONDED.. PAIRING..."); pairDevice(mDevice); } else if (state == BluetoothDevice.BOND_BONDED) { Debugger.d(TAG, "onActivityResult() >>>> Device is already bonded. Trying to connect"); if (mService.connect(mDevice)) Debugger.d(TAG, "onActivityResult() >>>> Connecting to device successful. "); } } else { Debugger.e(TAG, "onActivityResult() >>>> BluetoothAdapter = null."); finish(); } Debugger.d(TAG, "onActivityResult() >>>> ... onActivityResultdevice.address==" + mDevice + "mserviceValue" + mService); // setUiState(); } break; case REQUEST_ENABLE_BT: // When the request to enable Bluetooth returns if (resultCode == Activity.RESULT_OK) { Toast.makeText(this, "Bluetooth has turned on ", Toast.LENGTH_SHORT).show(); } else { // User did not enable Bluetooth or an error occurred Debugger.d(TAG, "onActivityResult() >>>> BT not enabled"); Toast.makeText(this, "Problem in BT Turning ON ", Toast.LENGTH_SHORT).show(); finish(); } break; case CommonValues.REQUEST_PAIRING: Debugger.d(TAG, " onActivityResult() >>>> REQUEST_PAIRING. ResultCode = " + resultCode); break; default: Debugger.e(TAG, " onActivityResult() >>>> wrong request code"); break; } } private ServiceConnection mServiceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder rawBinder) { mService = ((WorkableService.LocalBinder) rawBinder).getService(); Debugger.d(TAG, "onServiceConnected() >>>> mService= " + mService); if (!mService.initialize()) { Debugger.e(TAG, "onServiceConnected() >>>> Unable to initialize Bluetooth"); finish(); } mService.setActivityHandler(mHandler); } public void onServiceDisconnected(ComponentName classname) { mService.disconnect(); mService = null; } }; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { final Bundle data = msg.getData(); switch (msg.what) { case WorkableService.CONNECT_MSG: setState(State.CONNECTED); mService.readSpecificChar(WorkableService.BATTERY_LEVEL); // String text = data.getString(BluetoothDevice.EXTRA_NAME); // device.setText("Device: " + text); // pairDevice(mDevice); // initialize Knob for rotating and touching // ivKnob.setOnTouchListener(new MyOnTouchListener()); break; case WorkableService.READY_MSG: setState(State.CONNECTED); mService.readSpecificChar(WorkableService.BATTERY_LEVEL); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } mService.readSpecificChar(WorkableService.ACTUAL_LEVEL); break; case WorkableService.DISCONNECT_MSG: if (timer != null) timer.cancel(); // setState(States.DISCONNECTED); String message = data.getString(BluetoothDevice.EXTRA_NAME); if (message != null) { Toast.makeText(getApplicationContext(), R.string.device_disconnected + ":" + message, Toast.LENGTH_SHORT).show(); } else Toast.makeText(getApplicationContext(), R.string.device_disconnected, Toast.LENGTH_SHORT) .show(); break; case WorkableService.VALUE_MSG: UUID name = UUID.fromString(data .getString(WorkableService.EXTRA_CHARACTERISTIC)); if (name.equals(WorkableService.BATTERY_LEVEL)) { byte value = data.getByte(name.toString()); if (value >= CommonValues.BATTERY_ALMOST_FULL) // set image baterry_full ivBattery.setImageResource(R.drawable.battery_full); else if (value < CommonValues.BATTERY_ALMOST_FULL && value > CommonValues.BATTERY_MORE_HALF) // set image battery_80 ivBattery.setImageResource(R.drawable.battery_80); else if (value < CommonValues.BATTERY_MORE_HALF && value > CommonValues.BATTERY_HALF) // set image baterry_60; ivBattery.setImageResource(R.drawable.battery_60); else if (value < CommonValues.BATTERY_HALF && value > CommonValues.BATTERY_LESS_HALF) // set image battery_40 ivBattery.setImageResource(R.drawable.battery_40); else if (value < CommonValues.BATTERY_LESS_HALF && value > CommonValues.BATTERY_ALMOST_EMPTY) // set image battery_20 ivBattery.setImageResource(R.drawable.battery_20); else if (value < CommonValues.BATTERY_ALMOST_EMPTY && value > CommonValues.BATTERY_EMPTY) // set image battery_empty ivBattery.setImageResource(R.drawable.battery_empty); } if (name.equals(WorkableService.ACTUAL_LEVEL)) { byte value = data.getByte(name.toString()); // Toast.makeText(getApplicationContext(), "value = " + // value, Toast.LENGTH_SHORT).show(); Debugger.d(TAG, "Handler() >>>> Actual Level = " + value); dd.drawLine((short) value); } if (name.equals(WorkableService.TIME_IN_ACTIVE_MODE)) { byte[] value = data.getByteArray(name.toString()); Debugger.d(TAG, "Handler() >>>> time in active mode = " + value[0] + value[1]); } if (name.equals(WorkableService.PIN_CODE)) { byte[] value = data.getByteArray(name.toString()); Debugger.d(TAG, "Handler() >>>> pincode = " + value[0] + value[1] + value[2] + value[3]); } if (name.equals(WorkableService.CURRENT_OFFSET)) { byte value = data.getByte(name.toString()); Debugger.d(TAG, " Handler() >>>> Current Offset = " + value); } if (name.equals(WorkableService.ELECTRODES_MODE)) { byte value = data.getByte(name.toString()); Debugger.d(TAG, " Handler() >>>> Electrodes modes = " + value); } break; case WorkableService.CHARACTERISTIC_CHANGED: UUID uuid = UUID.fromString(data .getString(WorkableService.EXTRA_CHARACTERISTIC)); if (uuid.equals(WorkableService.ACTUAL_LEVEL)) mService.readSpecificChar(WorkableService.ACTUAL_LEVEL); if (uuid.equals(WorkableService.BATTERY_LEVEL)) mService.readSpecificChar(WorkableService.BATTERY_LEVEL); break; default: super.handleMessage(msg); } } }; public void pairDevice(BluetoothDevice device) { // startActivity(intent); // connect(device); Debugger.d(TAG, "pairDevice() >>>> Pairing to device:" + device.getAddress()); try { createBond(device); } catch (Exception e) { e.printStackTrace(); } } private final BroadcastReceiver proximityStatusChangeReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); final Intent mIntent = intent; if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { BluetoothDevice device = mIntent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int state = mIntent.getIntExtra( BluetoothDevice.EXTRA_BOND_STATE, 0); // int prevState = // mIntent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, // 0); Debugger.d(TAG, "onReceive() >>>> BluetoothDevice.ACTION_BOND_STATE_CHANGED. State = " + state); if (device.equals(mDevice)) { if (state == BluetoothDevice.BOND_BONDED) { setState(State.BONDED); // DONT connect right after bonding. Device should be // disconnected first. // mService.disconnect(); if (mService.connect(device)) { setState(State.CONNECTED); Toast.makeText(context, "Device was bonded", Toast.LENGTH_LONG).show(); } } if (state == BluetoothDevice.BOND_NONE) setState(State.UNBONDED); } } if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { final int state = mIntent.getIntExtra( BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); Debugger.d(TAG, "onReceive() >>>> BluetoothAdapter.ACTION_STATE_CHANGED." + "state is" + state); runOnUiThread(new Runnable() { public void run() { // TODO make some function that // setState(States.DISCONNECTED); } }); } } }; @Override protected void onResume() { if (mService != null) mService.setActivityHandler(mHandler); TestFlight.endSession(); super.onResume(); } @Override public void onDestroy() { Debugger.d(TAG, "onDestroy()"); try { unregisterReceiver(proximityStatusChangeReceiver); unbindService(mServiceConnection); stopService(new Intent(this, WorkableService.class)); if (timer != null) timer.cancel(); } catch (Exception ignore) { Debugger.e(TAG, ignore.toString()); } super.onDestroy(); } @Override public void onBackPressed() { // super.onBackPressed(); if (currentState != State.WORKING) new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle(R.string.popup_title) .setMessage(R.string.popup_message) .setPositiveButton(R.string.popup_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).setNegativeButton(R.string.popup_no, null) .show(); } protected void setState(final State state) { previousState = currentState; currentState = state; runOnUiThread(new Runnable() { @Override public void run() { switch (state) { case BONDED: tvText.setVisibility(View.VISIBLE); tvText.setText(R.string.bonded); tvValue.setVisibility(View.INVISIBLE); tvValue.setText(dateFormat.format(new Date( (long) currentValue * measure))); Debugger.d(TAG, "setState() >>>> State changed to bonded."); case UNBONDED: setState(State.DISCONNECTED); tvText.setText(R.string.unbonded); Debugger.d(TAG, "setState() >>>> State changed to unbonded."); case CONNECTED: tvText.setVisibility(View.VISIBLE); tvText.setText(R.string.press_message); tvValue.setVisibility(View.INVISIBLE); tvValue.setText(dateFormat.format(new Date( (long) currentValue * measure))); ivKnob.setOnTouchListener(new MyOnTouchListener()); gauge.setVisibility(View.INVISIBLE); ivGauge.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.gauge_blue_bg)); if (timer != null) timer.cancel(); Debugger.d(TAG, "setState() >>>> State changed to connected."); break; case DISCONNECTED: tvText.setVisibility(View.VISIBLE); tvText.setText(R.string.disconnected); tvValue.setVisibility(View.INVISIBLE); ivBattery.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.battery_empty)); setKnobState(false); gauge.setVisibility(View.INVISIBLE); ivGauge.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.gauge_blue_bg)); ivKnob.setOnTouchListener(null); Debugger.d(TAG, "setState() >>>> State changed to disconnected."); if (previousState == State.BONDED) { Debugger.d(TAG, " setState() >>>> Previous state == State.BONDED"); // if state was changed from Bonded, try reconnect. if (mDevice != null && mService != null) mService.connect(mDevice); } break; case WAITING: tvValue.setText(dateFormat.format(new Date((long) ONE_HOUR * measure))); ivKnob.setOnTouchListener(null); ivGauge.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.gauge_orange_bg2)); gauge.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.gauge_orange_empty2)); gauge.setVisibility(View.VISIBLE); Debugger.d(TAG, "setState() >>>> State changed to waiting."); break; case WORKING: tvText.setVisibility(View.INVISIBLE); tvValue.setVisibility(View.VISIBLE); ivGauge.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.gauge_blue_bg2)); gauge.setImageDrawable(getApplicationContext() .getResources().getDrawable( R.drawable.gauge_blue_empty)); gauge.setVisibility(View.VISIBLE); Debugger.d(TAG, "setState() >>>> State changed to working."); break; case KNOB_ROTATING: tvText.setVisibility(View.INVISIBLE); tvText.setText(R.string.press_message); tvValue.setVisibility(View.VISIBLE); Debugger.d(TAG, " setState() >>>> State changed to Knob_rotating."); break; } } }); } /** Reads Actual Level Characteristic every 200 milliseconds. */ class ReadActualLevelCharacteristic extends TimerTask { @Override public void run() { if (mService != null) mService.readSpecificChar(WorkableService.ACTUAL_LEVEL); else { Debugger.d( TAG, "Timer. ReadActualLevelCharacteristic cannot be started. Make sure Service is not null"); } } } /** Changes Progress - fade in/ out one degree in the circularProgressBar. */ class ChangeProgress extends TimerTask { CircularProgressBar progress; int current; int end_angle; ImageView gauge; boolean clockwise = false; boolean isCanceled; public ChangeProgress(ImageView g, CircularProgressBar p, int start, int end, boolean clock) { progress = p; current = start; end_angle = end; gauge = g; clockwise = clock; isCanceled = false; } public void setCanceled(boolean value) { isCanceled = value; Debugger.d(TAG, "ChangeProgress >>>> setCanceled()"); } @Override public void run() { if (!isCanceled) { if (clockwise) { if (current < end_angle) { progress.disappearSector(current % DEGREES_IN_CIRCLE, (current % DEGREES_IN_CIRCLE) + 1, 0); current++; displayImageView(); } else { // Debug.stopMethodTracing(); this.cancel(); setState(State.WAITING); startNewTimer(); } } else { if (current > end_angle) { if (current % DEGREES_IN_CIRCLE == 0) progress.disappearSector(DEGREES_IN_CIRCLE - 1, DEGREES_IN_CIRCLE, 0); else progress.disappearSector( (current % DEGREES_IN_CIRCLE) - 1, current % DEGREES_IN_CIRCLE, 0); current--; displayImageView(); } else { // this.cancel(); // don't need this, because timer is // canceled in setState() method setState(State.CONNECTED); } } } } protected void displayImageView() { runOnUiThread(new Runnable() { @Override public void run() { if (!isCanceled) { // height sets as the width, because if set real // width - it display the image not correct. For now // have no idea why this happens. int height = progress.getBitmap().getHeight(); gauge.setImageBitmap(Bitmap.createScaledBitmap( progress.getBitmap(), height, height, false)); Debugger.d(TAG, "ChangeProgress >>>> DisplayImageView()"); } } }); } } /** Changes Label */ class ChangeTimeLabel extends TimerTask { TextView label; long currentTime; long min; public ChangeTimeLabel(TextView l, long ct) { label = l; currentTime = ct; min = (long) minValue * measure; } @Override public void run() { if (currentTime >= 0) { runOnUiThread(new Runnable() { @Override public void run() { label.setText(dateFormat.format(new Date(currentTime))); currentTime -= SECOND; } }); } else { this.cancel(); } } } public void startNewTimer() { runOnUiThread(new Runnable() { @Override public void run() { Debugger.d(TAG, "startNewTimer"); setKnobState(false); ivKnob.setOnTouchListener(null); Debugger.d(TAG, "StartNewTimer()->Set device mode to PAIRED(1)"); mService.writeCharacteristic(WorkableService.MODE, (byte) CommonValues.PAIRED); final CircularProgressBar progress = createProgressBar(); if (timer != null) timer.cancel(); timer = new Timer(); // 360 - One hour to wait until start working again final int delay = (int) (ONE_HOUR * measure / (END_ANGLE - START_ANGLE)); if (timer != null) { runOnUiThread(new Runnable() { @Override public void run() { // TODO change to real after testing timer.scheduleAtFixedRate(new ChangeProgress(gauge, progress, END_ANGLE, END_ANGLE - 2, false), delay, delay); timer.scheduleAtFixedRate(new ChangeTimeLabel( tvValue, 360 * measure), SECOND, SECOND); } }); } } }); } // ****************************************************RotatyKnob************************************************************* protected void initializeIvKnob() { ivKnob.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // method called more than once, but the values only // need to be // initialized one time if (dialerHeight == 0 || dialerWidth == 0) { dialerHeight = ivKnob.getHeight(); dialerWidth = ivKnob.getWidth(); // resize Matrix resize = new Matrix(); resize.postScale( (float) Math.min(dialerWidth, dialerHeight) / (float) imageOriginal.getWidth(), (float) Math.min(dialerWidth, dialerHeight) / (float) imageOriginal.getHeight()); imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false); // translate to the image view's center float translateX = dialerWidth / 2 - imageScaled.getWidth() / 2; float translateY = dialerHeight / 2 - imageScaled.getHeight() / 2; matrix.postTranslate(translateX, translateY); ivKnob.setImageBitmap(imageScaled); ivKnob.setImageMatrix(matrix); rotateDialer(initRotateAngle); } else if (dialerHeight != ivKnob.getHeight()) { dialerHeight = ivKnob.getHeight(); dialerWidth = ivKnob.getWidth(); // resize Matrix resize = new Matrix(); resize.postScale( (float) Math.min(dialerWidth, dialerHeight) / (float) imageOriginal.getWidth(), (float) Math.min(dialerWidth, dialerHeight) / (float) imageOriginal.getHeight()); imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false); // translate to the image view's center // float translateX = dialerWidth / 2 - // imageScaled.getWidth() / 2; // float translateY = dialerHeight / 2 - // imageScaled.getHeight() / 2; // // matrix.postTranslate(translateX, translateY); ivKnob.setImageBitmap(imageScaled); matrix.reset(); ivKnob.setImageMatrix(matrix); rotateDialer(initRotateAngle); rotateDialer((currentValue - minValue) * angleDiapazon / (maxValue - minValue)); if (knobOn == true) { ivKnob.setY(tvValue.getY() + ivKnob.getHeight()); } } } }); } // **********************************************RotaryKnob********************************************** protected void initializeRotatyKnob() { ivGauge = (ImageView) findViewById(R.id.ivGauge); gauge = (ImageView) findViewById(R.id.gauge_fill); // gauge.setVisibility(View.INVISIBLE); tvValue = (TextView) findViewById(R.id.tvValue); tvText = (TextView) findViewById(R.id.tvText); diagramLayout = (RelativeLayout) findViewById(R.id.diagramLayout); ivGaugeDiagram = (ImageView) findViewById(R.id.ivGaugeDiagram); ivKnob = (ImageView) findViewById(R.id.ivKnob); ivBattery = (ImageView) findViewById(R.id.ivBattery); initializeIvKnob(); // int pixels = (int) (dp * scale + 0.5f); float scale = getResources().getDisplayMetrics().density; // Checks the orientation of the screen if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { ((RelativeLayout.LayoutParams) ivGauge.getLayoutParams()).height = (int) (210 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGauge.getLayoutParams()).bottomMargin = (int) (10 * scale + 0.5f); ((RelativeLayout.LayoutParams) tvValue.getLayoutParams()).topMargin = (int) (50 * scale + 0.5f); tvValue.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); ((RelativeLayout.LayoutParams) diagramLayout.getLayoutParams()).width = (int) (80 * scale + 0.5f); ((RelativeLayout.LayoutParams) diagramLayout.getLayoutParams()).height = (int) (35 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGaugeDiagram.getLayoutParams()).height = (int) (210 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGaugeDiagram.getLayoutParams()).bottomMargin = (int) (10 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivKnob.getLayoutParams()).height = (int) (90 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivKnob.getLayoutParams()).width = (int) (90 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivBattery.getLayoutParams()).height = (int) (20 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivBattery.getLayoutParams()).width = (int) (20 * scale + 0.5f); } // DrawDiagram dd = new DrawDiagram(this); dd = (com.example.focus.DrawDiagram) findViewById(R.id.drawDiagram); // dd.setZOrderOnTop(true); // dd.getHolder().setFormat(PixelFormat.TRANSPARENT); // load the image only once if (imageOriginal == null) { imageOriginal = BitmapFactory.decodeResource(getResources(), R.drawable.knob_high); } // initialize the matrix only once if (matrix == null) { matrix = new Matrix(); } else { // not needed, you can also post the matrix immediately to restore // the old state matrix.reset(); } division = (maxValue - minValue) / angleDiapazon; dateFormat = new SimpleDateFormat("HH:mm:ss", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+00:00")); tvValue.setText(dateFormat.format(new Date((long) currentValue * measure))); tvValue.setVisibility(View.INVISIBLE); tvText.setVisibility(View.VISIBLE); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // int pixels = (int) (dp * scale + 0.5f); float scale = getResources().getDisplayMetrics().density; // Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { ((RelativeLayout.LayoutParams) ivGauge.getLayoutParams()).height = (int) (210 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGauge.getLayoutParams()).bottomMargin = (int) (10 * scale + 0.5f); ((RelativeLayout.LayoutParams) tvValue.getLayoutParams()).topMargin = (int) (50 * scale + 0.5f); tvValue.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); ((RelativeLayout.LayoutParams) diagramLayout.getLayoutParams()).width = (int) (80 * scale + 0.5f); ((RelativeLayout.LayoutParams) diagramLayout.getLayoutParams()).height = (int) (35 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGaugeDiagram.getLayoutParams()).height = (int) (210 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGaugeDiagram.getLayoutParams()).bottomMargin = (int) (10 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivKnob.getLayoutParams()).height = (int) (90 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivKnob.getLayoutParams()).width = (int) (90 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivBattery.getLayoutParams()).height = (int) (20 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivBattery.getLayoutParams()).width = (int) (20 * scale + 0.5f); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { ((RelativeLayout.LayoutParams) ivGauge.getLayoutParams()).height = (int) (330 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGauge.getLayoutParams()).bottomMargin = (int) (30 * scale + 0.5f); ((RelativeLayout.LayoutParams) tvValue.getLayoutParams()).topMargin = (int) (80 * scale + 0.5f); tvValue.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); ((RelativeLayout.LayoutParams) diagramLayout.getLayoutParams()).width = (int) (120 * scale + 0.5f); ((RelativeLayout.LayoutParams) diagramLayout.getLayoutParams()).height = (int) (60 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGaugeDiagram.getLayoutParams()).height = (int) (330 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivGaugeDiagram.getLayoutParams()).bottomMargin = (int) (30 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivKnob.getLayoutParams()).height = (int) (150 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivKnob.getLayoutParams()).width = (int) (150 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivBattery.getLayoutParams()).height = (int) (30 * scale + 0.5f); ((RelativeLayout.LayoutParams) ivBattery.getLayoutParams()).width = (int) (30 * scale + 0.5f); } } /** * Simple implementation of an {@link OnTouchListener} for registering the * dialer's touch events. */ private class MyOnTouchListener implements OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: topY = tvValue.getY(); bottomY = tvValue.getY() + ivKnob.getHeight(); touchX = event.getX(); touchY = event.getY(); touchLayoutX = ivKnob.getX() + touchX; touchLayoutY = ivKnob.getY() + touchY; startAngle = getAngle(event.getX(), event.getY()); break; case MotionEvent.ACTION_MOVE: if (knobOn == false) { float partX = ivKnob.getWidth() / 4; float partY = ivKnob.getHeight() / 4; if ((touchLayoutX < tvValue.getX() + partX) || (touchLayoutX > tvValue.getX() + 3 * partX) || (touchLayoutY < tvValue.getY() + partY) || (touchLayoutY > tvValue.getY() + 3 * partY)) { currentAngle = getAngle(event.getX(), event.getY()); getRotateValue(); isRotate = true; break; } } float tempY = ivKnob.getY() + event.getY() - touchY; if ((tempY >= topY) && (tempY <= bottomY)) { ivKnob.setY(tempY); } break; case MotionEvent.ACTION_UP: if (isRotate == true) { isRotate = false; } else { if ((event.getX() < touchX + 10) && (event.getX() > touchX - 10) && (event.getY() < touchY + 10) && (event.getY() > touchY - 10)) { if (knobOn == true) { ivKnob.setY(topY); ivKnob.setBackgroundResource(R.drawable.knob_low); knobOn = false; knobStateChange(); } else { ivKnob.setY(bottomY); ivKnob.setBackgroundResource(R.drawable.knob_low_off); knobOn = true; knobStateChange(); } } else { if ((bottomY - ivKnob.getY()) >= (ivKnob.getY() - topY)) { ivKnob.setY(topY); if (knobOn == true) { ivKnob.setBackgroundResource(R.drawable.knob_low); knobOn = false; knobStateChange(); } } else { ivKnob.setY(bottomY); if (knobOn == false) { ivKnob.setBackgroundResource(R.drawable.knob_low_off); knobOn = true; knobStateChange(); } } } } break; } return true; } } /** * Calculate rotate value of dialer * */ private void getRotateValue() { /* * Bugs: 1. long rotate to min side when startValue == minValue; 2. long * rotate to max side when startValue == maxValue; */ if ((startAngle >= 0) && (startAngle <= 90) && (currentAngle >= 270) && (currentAngle < 360)) { currentValue += (float) (360 - currentAngle + startAngle) * division; if (currentValue > maxValue) { double t = startAngle - (maxValue - startValue) / division; currentAngle = (t >= 0) ? t : 360 + t; currentValue = maxValue; } } else if ((startAngle >= 270) && (startAngle < 360) && (currentAngle >= 0) && (currentAngle <= 90)) { currentValue -= (float) (360 - startAngle + currentAngle) * division; if (currentValue < minValue) { double t = startAngle + (startValue - minValue) / division; currentAngle = (t < 360) ? t : t - 360; currentValue = minValue; } } else { currentValue += (float) (startAngle - currentAngle) * division; if (currentValue < minValue) { currentAngle = startAngle + (startValue - minValue) / division; currentValue = minValue; } else if (currentValue > maxValue) { currentAngle = startAngle - (maxValue - startValue) / division; currentValue = maxValue; } } rotateDialer((float) (startAngle - currentAngle)); tvValue.setText(dateFormat.format(new Date((long) currentValue * measure))); if (currentState != State.KNOB_ROTATING) setState(State.KNOB_ROTATING); startValue = currentValue; startAngle = currentAngle; } /** * @return The angle of the unit circle with the image view's center */ private double getAngle(double xTouch, double yTouch) { double x = xTouch - (dialerWidth / 2d); double y = dialerHeight - yTouch - (dialerHeight / 2d); switch (getQuadrant(x, y)) { case 1: return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI; case 2: return 180 - Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI; case 3: return 180 + (-1 * Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI); case 4: return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI; default: return 0; } } /** * @return The selected quadrant. */ private static int getQuadrant(double x, double y) { if (x >= 0) { return y >= 0 ? 1 : 4; } else { return y >= 0 ? 2 : 3; } } /** * Rotate the dialer. * * @param degrees * The degrees, the dialer should get rotated. */ private void rotateDialer(float degrees) { matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2); ivKnob.setImageMatrix(matrix); } private void setKnobState(boolean state) { if (state == true) { ivKnob.setY(tvValue.getY() + ivKnob.getHeight()); ivKnob.setBackgroundResource(R.drawable.knob_low_off); knobOn = true; } else { ivKnob.setY(tvValue.getY()); ivKnob.setBackgroundResource(R.drawable.knob_low); knobOn = false; } } // **********************************************RotaryKnob********************************************** private Boolean connect(BluetoothDevice bdDevice) { Boolean bool = false; try { Debugger.i("Log", "service method is called "); Class cl = Class.forName("android.bluetooth.BluetoothDevice"); Class[] par = {}; Method method = cl.getMethod("createBond", par); Object[] args = {}; bool = (Boolean) method.invoke(bdDevice);// , args);// this invoke // creates the detected // devices paired. // Log.i("Log", "This is: "+bool.booleanValue()); // Log.i("Log", "devicesss: "+bdDevice.getName()); } catch (Exception e) { Debugger.i("Log", "Inside catch of serviceFromDevice Method"); e.printStackTrace(); } return bool.booleanValue(); }; public boolean createBond(BluetoothDevice btDevice) throws Exception { Class class1 = Class.forName("android.bluetooth.BluetoothDevice"); Method createBondMethod = class1.getMethod("createBond"); Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice); return returnValue.booleanValue(); } private void removeBond(BluetoothDevice device) { try { Method m = device.getClass() .getMethod("removeBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { Debugger.e(TAG, e.getMessage()); } } }