Android Tutorial - Hardware

 

  1. Bluetooth
  2. Storage
  3. Joystick
  4. Display
  5. Gps
  6. PowerManager
  7. SensorManager
  8. USB
  9. Vibrator

Bluetooth Adapter Util
//package com.hustaty.android.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.util.Log;

/**
 * 
 * @author Slavomir Hustaty
 *
 */
public class BluetoothAdapterUtil {

  // logger entry
  private final static String LOG_TAG = BluetoothAdapterUtil.class.getSimpleName();

  private static final int LOOP_WAIT_TIME = 500;
  
  private static final int MAX_REPETITIONS_COUNT = 30;
  
  public static void startBluetoothAdapter() {
    try {
      waitUntilBluetoothAdapterIsInState(BluetoothAdapter.STATE_ON, MAX_REPETITIONS_COUNT);
    } catch (Exception e) {
      Log.d(LOG_TAG, e.getMessage());
    }
  }
  
  public static void stopBluetoothAdapter() {    
    try {
      waitUntilBluetoothAdapterIsInState(BluetoothAdapter.STATE_OFF, MAX_REPETITIONS_COUNT);
    } catch (Exception e) {
      Log.d(LOG_TAG, e.getMessage());
    }
  }
  
  /**
   * waits until BluetoothAdapter is in required state
   * 
   * @param state
   * @throws Exception
   */
  private static void waitUntilBluetoothAdapterIsInState(int state, int remainingLoops) throws Exception {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    
    if(remainingLoops > 0) {
      switch (state) {
      case BluetoothAdapter.STATE_OFF:
        if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF) {
          waitNMillis(LOOP_WAIT_TIME);
          waitUntilBluetoothAdapterIsInState(BluetoothAdapter.STATE_OFF, remainingLoops - 1);
        } else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
          Log.d(LOG_TAG, "BluetoothAdapter is in state OFF");
          return;
        } else {
          // ensure we're not waiting for Godot ;)
          bluetoothAdapter.disable();
          waitUntilBluetoothAdapterIsInState(BluetoothAdapter.STATE_OFF, remainingLoops - 1);
        }
        break;
      case BluetoothAdapter.STATE_ON:
        if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_TURNING_ON) {
          waitNMillis(LOOP_WAIT_TIME);
          waitUntilBluetoothAdapterIsInState(BluetoothAdapter.STATE_ON, remainingLoops - 1);
        } else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
          Log.d(LOG_TAG, "BluetoothAdapter is in state ON");
          return;
        } else {
          // ensure we're not waiting for Godot ;)
          bluetoothAdapter.enable();
          waitUntilBluetoothAdapterIsInState(BluetoothAdapter.STATE_ON, remainingLoops - 1);
        }
        break;
      default:
        throw new Exception(
            "You can check only final states of BluetoothAdapter(STATE_ON|STATE_OFF).");
      }
    } else {
      Log.e(LOG_TAG, "Error on waiting while BluetoothAdapter changes state to #" + state + ". ");
      return;
    }
  }

  /**
   * delay N milliseconds
   * 
   * @param n
   */
  private static void waitNMillis(long n) {
    try {
      Thread.sleep(n);
    } catch (InterruptedException e) {
      Log.e(LOG_TAG, "#waitNMillis() " + e.getMessage());
    }
  }

}
Bluetooth Chat
package com.example.android.BluetoothChat;

import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

/**
 * This Activity appears as a dialog. It lists any paired devices and
 * devices detected in the area after discovery. When a device is chosen
 * by the user, the MAC address of the device is sent back to the parent
 * Activity in the result Intent.
 */
public class DeviceListActivity extends Activity {
    // Debugging
    private static final String TAG = "DeviceListActivity";
    private static final boolean D = true;

    // Return Intent extra
    public static String EXTRA_DEVICE_ADDRESS = "device_address";

    // Member fields
    private BluetoothAdapter mBtAdapter;
    private ArrayAdapter<String> mPairedDevicesArrayAdapter;
    private ArrayAdapter<String> mNewDevicesArrayAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Setup the window
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.device_list);

        // Set result CANCELED in case the user backs out
        setResult(Activity.RESULT_CANCELED);

        // Initialize the button to perform device discovery
        Button scanButton = (Button) findViewById(R.id.button_scan);
        scanButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                doDiscovery();
                v.setVisibility(View.GONE);
            }
        });

        // Initialize array adapters. One for already paired devices and
        // one for newly discovered devices
        mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
        mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);

        // Find and set up the ListView for paired devices
        ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
        pairedListView.setAdapter(mPairedDevicesArrayAdapter);
        pairedListView.setOnItemClickListener(mDeviceClickListener);

        // Find and set up the ListView for newly discovered devices
        ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
        newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
        newDevicesListView.setOnItemClickListener(mDeviceClickListener);

        // Register for broadcasts when a device is discovered
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        this.registerReceiver(mReceiver, filter);

        // Register for broadcasts when discovery has finished
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        this.registerReceiver(mReceiver, filter);

        // Get the local Bluetooth adapter
        mBtAdapter = BluetoothAdapter.getDefaultAdapter();

        // Get a set of currently paired devices
        Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

        // If there are paired devices, add each one to the ArrayAdapter
        if (pairedDevices.size() > 0) {
            findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
            for (BluetoothDevice device : pairedDevices) {
                mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
            }
        } else {
            String noDevices = getResources().getText(R.string.none_paired).toString();
            mPairedDevicesArrayAdapter.add(noDevices);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // Make sure we're not doing discovery anymore
        if (mBtAdapter != null) {
            mBtAdapter.cancelDiscovery();
        }

        // Unregister broadcast listeners
        this.unregisterReceiver(mReceiver);
    }

    /**
     * Start device discover with the BluetoothAdapter
     */
    private void doDiscovery() {
        if (D) Log.d(TAG, "doDiscovery()");

        // Indicate scanning in the title
        setProgressBarIndeterminateVisibility(true);
        setTitle(R.string.scanning);

        // Turn on sub-title for new devices
        findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);

        // If we're already discovering, stop it
        if (mBtAdapter.isDiscovering()) {
            mBtAdapter.cancelDiscovery();
        }

        // Request discover from BluetoothAdapter
        mBtAdapter.startDiscovery();
    }

    // The on-click listener for all devices in the ListViews
    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
            // Cancel discovery because it's costly and we're about to connect
            mBtAdapter.cancelDiscovery();

            // Get the device MAC address, which is the last 17 chars in the View
            String info = ((TextView) v).getText().toString();
            String address = info.substring(info.length() - 17);

            // Create the result Intent and include the MAC address
            Intent intent = new Intent();
            intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

            // Set result and finish this Activity
            setResult(Activity.RESULT_OK, intent);
            finish();
        }
    };

    // The BroadcastReceiver that listens for discovered devices and
    // changes the title when discovery is finished
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // If it's already paired, skip it, because it's been listed already
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                }
            // When discovery is finished, change the Activity title
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                setProgressBarIndeterminateVisibility(false);
                setTitle(R.string.select_device);
                if (mNewDevicesArrayAdapter.getCount() == 0) {
                    String noDevices = getResources().getText(R.string.none_found).toString();
                    mNewDevicesArrayAdapter.add(noDevices);
                }
            }
        }
    };

}


package com.example.android.BluetoothChat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * This class does all the work for setting up and managing Bluetooth
 * connections with other devices. It has a thread that listens for
 * incoming connections, a thread for connecting with a device, and a
 * thread for performing data transmissions when connected.
 */
public class BluetoothChatService {
    // Debugging
    private static final String TAG = "BluetoothChatService";
    private static final boolean D = true;

    // Name for the SDP record when creating server socket
    private static final String NAME_SECURE = "BluetoothChatSecure";
    private static final String NAME_INSECURE = "BluetoothChatInsecure";

    // Unique UUID for this application
    private static final UUID MY_UUID_SECURE =
        UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    private static final UUID MY_UUID_INSECURE =
        UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");

    // Member fields
    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    private AcceptThread mSecureAcceptThread;
    private AcceptThread mInsecureAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int mState;

    // Constants that indicate the current connection state
    public static final int STATE_NONE = 0;       // we're doing nothing
    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_CONNECTED = 3;  // now connected to a remote device

    /**
     * Constructor. Prepares a new BluetoothChat session.
     * @param context  The UI Activity Context
     * @param handler  A Handler to send messages back to the UI Activity
     */
    public BluetoothChatService(Context context, Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler = handler;
    }

    /**
     * Set the current state of the chat connection
     * @param state  An integer defining the current connection state
     */
    private synchronized void setState(int state) {
        if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
        mState = state;

        // Give the new state to the Handler so the UI Activity can update
        mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -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() {
        if (D) Log.d(TAG, "start");

        // 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;}

        setState(STATE_LISTEN);

        // Start the thread to listen on a BluetoothServerSocket
        if (mSecureAcceptThread == null) {
            mSecureAcceptThread = new AcceptThread(true);
            mSecureAcceptThread.start();
        }
        if (mInsecureAcceptThread == null) {
            mInsecureAcceptThread = new AcceptThread(false);
            mInsecureAcceptThread.start();
        }
    }

    /**
     * Start the ConnectThread to initiate a connection to a remote device.
     * @param device  The BluetoothDevice to connect
     * @param secure Socket Security type - Secure (true) , Insecure (false)
     */
    public synchronized void connect(BluetoothDevice device, boolean secure) {
        if (D) Log.d(TAG, "connect to: " + device);

        // Cancel any thread attempting to make a connection
        if (mState == STATE_CONNECTING) {
            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        }

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        // Start the thread to connect with the given device
        mConnectThread = new ConnectThread(device, secure);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }

    /**
     * Start the ConnectedThread to begin managing a Bluetooth connection
     * @param socket  The BluetoothSocket on which the connection was made
     * @param device  The BluetoothDevice that has been connected
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice
            device, final String socketType) {
        if (D) Log.d(TAG, "connected, Socket Type:" + socketType);

        // Cancel the thread that completed the connection
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        // Cancel the accept thread because we only want to connect to one device
        if (mSecureAcceptThread != null) {
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = null;
        }
        if (mInsecureAcceptThread != null) {
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = null;
        }

        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(socket, socketType);
        mConnectedThread.start();

        // Send the name of the connected device back to the UI Activity
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        setState(STATE_CONNECTED);
    }

    /**
     * Stop all threads
     */
    public synchronized void stop() {
        if (D) Log.d(TAG, "stop");

        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }

        if (mSecureAcceptThread != null) {
            mSecureAcceptThread.cancel();
            mSecureAcceptThread = null;
        }

        if (mInsecureAcceptThread != null) {
            mInsecureAcceptThread.cancel();
            mInsecureAcceptThread = null;
        }
        setState(STATE_NONE);
    }

    /**
     * Write to the ConnectedThread in an unsynchronized manner
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (this) {
            if (mState != STATE_CONNECTED) return;
            r = mConnectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }

    /**
     * Indicate that the connection attempt failed and notify the UI Activity.
     */
    private void connectionFailed() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.TOAST, "Unable to connect device");
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        // Start the service over to restart listening mode
        BluetoothChatService.this.start();
    }

    /**
     * Indicate that the connection was lost and notify the UI Activity.
     */
    private void connectionLost() {
        // Send a failure message back to the Activity
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.TOAST, "Device connection was lost");
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        // Start the service over to restart listening mode
        BluetoothChatService.this.start();
    }

    /**
     * This thread runs while listening for incoming connections. It behaves
     * like a server-side client. It runs until a connection is accepted
     * (or until cancelled).
     */
    private class AcceptThread extends Thread {
        // The local server socket
        private final BluetoothServerSocket mmServerSocket;
        private String mSocketType;

        public AcceptThread(boolean secure) {
            BluetoothServerSocket tmp = null;
            mSocketType = secure ? "Secure":"Insecure";

            // Create a new listening server socket
            try {
                if (secure) {
                    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                        MY_UUID_SECURE);
                } else {
                    tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
                            NAME_INSECURE, MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
            }
            mmServerSocket = tmp;
        }

        public void run() {
            if (D) Log.d(TAG, "Socket Type: " + mSocketType +
                    "BEGIN mAcceptThread" + this);
            setName("AcceptThread" + mSocketType);

            BluetoothSocket socket = null;

            // Listen to the server socket if we're not connected
            while (mState != STATE_CONNECTED) {
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
                    break;
                }

                // If a connection was accepted
                if (socket != null) {
                    synchronized (BluetoothChatService.this) {
                        switch (mState) {
                        case STATE_LISTEN:
                        case STATE_CONNECTING:
                            // Situation normal. Start the connected thread.
                            connected(socket, socket.getRemoteDevice(),
                                    mSocketType);
                            break;
                        case STATE_NONE:
                        case STATE_CONNECTED:
                            // Either not ready or already connected. Terminate new socket.
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
            if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);

        }

        public void cancel() {
            if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
            }
        }
    }


    /**
     * This thread runs while attempting to make an outgoing connection
     * with a device. It runs straight through; the connection either
     * succeeds or fails.
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        private String mSocketType;

        public ConnectThread(BluetoothDevice device, boolean secure) {
            mmDevice = device;
            BluetoothSocket tmp = null;
            mSocketType = secure ? "Secure" : "Insecure";

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                if (secure) {
                    tmp = device.createRfcommSocketToServiceRecord(
                            MY_UUID_SECURE);
                } else {
                    tmp = device.createInsecureRfcommSocketToServiceRecord(
                            MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
            }
            mmSocket = tmp;
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
            setName("ConnectThread" + mSocketType);

            // Always cancel discovery because it will slow down a connection
            mAdapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mmSocket.connect();
            } catch (IOException e) {
                // Close the socket
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() " + mSocketType +
                            " socket during connection failure", e2);
                }
                connectionFailed();
                return;
            }

            // Reset the ConnectThread because we're done
            synchronized (BluetoothChatService.this) {
                mConnectThread = null;
            }

            // Start the connected thread
            connected(mmSocket, mmDevice, mSocketType);
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
            }
        }
    }

    /**
     * This thread runs during a connection with a remote device.
     * It handles all incoming and outgoing transmissions.
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket, String socketType) {
            Log.d(TAG, "create ConnectedThread: " + socketType);
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectedThread");
            byte[] buffer = new byte[1024];
            int bytes;

            // Keep listening to the InputStream while connected
            while (true) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);

                    // Send the obtained bytes to the UI Activity
                    mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    // Start the service over to restart listening mode
                    BluetoothChatService.this.start();
                    break;
                }
            }
        }

        /**
         * Write to the connected OutStream.
         * @param buffer  The bytes to write
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);

                // Share the sent message back to the UI Activity
                mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
}


package com.example.android.BluetoothChat;

import android.app.ActionBar;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * This is the main Activity that displays the current chat session.
 */
public class BluetoothChat extends Activity {
    // Debugging
    private static final String TAG = "BluetoothChat";
    private static final boolean D = true;

    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;

    // Key names received from the BluetoothChatService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String TOAST = "toast";

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
    private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
    private static final int REQUEST_ENABLE_BT = 3;

    // Layout Views
    private ListView mConversationView;
    private EditText mOutEditText;
    private Button mSendButton;

    // Name of the connected device
    private String mConnectedDeviceName = null;
    // Array adapter for the conversation thread
    private ArrayAdapter<String> mConversationArrayAdapter;
    // String buffer for outgoing messages
    private StringBuffer mOutStringBuffer;
    // Local Bluetooth adapter
    private BluetoothAdapter mBluetoothAdapter = null;
    // Member object for the chat services
    private BluetoothChatService mChatService = null;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(D) Log.e(TAG, "+++ ON CREATE +++");

        // Set up the window layout
        setContentView(R.layout.main);

        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if(D) Log.e(TAG, "++ ON START ++");

        // If BT is not on, request that it be enabled.
        // setupChat() will then be called during onActivityResult
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        // Otherwise, setup the chat session
        } else {
            if (mChatService == null) setupChat();
        }
    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        if(D) Log.e(TAG, "+ ON RESUME +");

        // Performing this check in onResume() covers the case in which BT was
        // not enabled during onStart(), so we were paused to enable it...
        // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
        if (mChatService != null) {
            // Only if the state is STATE_NONE, do we know that we haven't started already
            if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
              // Start the Bluetooth chat services
              mChatService.start();
            }
        }
    }

    private void setupChat() {
        Log.d(TAG, "setupChat()");

        // Initialize the array adapter for the conversation thread
        mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
        mConversationView = (ListView) findViewById(R.id.in);
        mConversationView.setAdapter(mConversationArrayAdapter);

        // Initialize the compose field with a listener for the return key
        mOutEditText = (EditText) findViewById(R.id.edit_text_out);
        mOutEditText.setOnEditorActionListener(mWriteListener);

        // Initialize the send button with a listener that for click events
        mSendButton = (Button) findViewById(R.id.button_send);
        mSendButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                // Send a message using content of the edit text widget
                TextView view = (TextView) findViewById(R.id.edit_text_out);
                String message = view.getText().toString();
                sendMessage(message);
            }
        });

        // Initialize the BluetoothChatService to perform bluetooth connections
        mChatService = new BluetoothChatService(this, mHandler);

        // Initialize the buffer for outgoing messages
        mOutStringBuffer = new StringBuffer("");
    }

    @Override
    public synchronized void onPause() {
        super.onPause();
        if(D) Log.e(TAG, "- ON PAUSE -");
    }

    @Override
    public void onStop() {
        super.onStop();
        if(D) Log.e(TAG, "-- ON STOP --");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Stop the Bluetooth chat services
        if (mChatService != null) mChatService.stop();
        if(D) Log.e(TAG, "--- ON DESTROY ---");
    }

    private void ensureDiscoverable() {
        if(D) Log.d(TAG, "ensure discoverable");
        if (mBluetoothAdapter.getScanMode() !=
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivity(discoverableIntent);
        }
    }

    /**
     * Sends a message.
     * @param message  A string of text to send.
     */
    private void sendMessage(String message) {
        // Check that we're actually connected before trying anything
        if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }

        // Check that there's actually something to send
        if (message.length() > 0) {
            // Get the message bytes and tell the BluetoothChatService to write
            byte[] send = message.getBytes();
            mChatService.write(send);

            // Reset out string buffer to zero and clear the edit text field
            mOutStringBuffer.setLength(0);
            mOutEditText.setText(mOutStringBuffer);
        }
    }

    // The action listener for the EditText widget, to listen for the return key
    private TextView.OnEditorActionListener mWriteListener =
        new TextView.OnEditorActionListener() {
        public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
            // If the action is a key-up event on the return key, send the message
            if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
                String message = view.getText().toString();
                sendMessage(message);
            }
            if(D) Log.i(TAG, "END onEditorAction");
            return true;
        }
    };

    private final void setStatus(int resId) {
        final ActionBar actionBar = getActionBar();
        actionBar.setSubtitle(resId);
    }

    private final void setStatus(CharSequence subTitle) {
        final ActionBar actionBar = getActionBar();
        actionBar.setSubtitle(subTitle);
    }

    // The Handler that gets information back from the BluetoothChatService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case BluetoothChatService.STATE_CONNECTED:
                    setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
                    mConversationArrayAdapter.clear();
                    break;
                case BluetoothChatService.STATE_CONNECTING:
                    setStatus(R.string.title_connecting);
                    break;
                case BluetoothChatService.STATE_LISTEN:
                case BluetoothChatService.STATE_NONE:
                    setStatus(R.string.title_not_connected);
                    break;
                }
                break;
            case MESSAGE_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                // construct a string from the buffer
                String writeMessage = new String(writeBuf);
                mConversationArrayAdapter.add("Me:  " + writeMessage);
                break;
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                String readMessage = new String(readBuf, 0, msg.arg1);
                mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "Connected to "
                               + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                break;
            case MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                               Toast.LENGTH_SHORT).show();
                break;
            }
        }
    };

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(D) Log.d(TAG, "onActivityResult " + resultCode);
        switch (requestCode) {
        case REQUEST_CONNECT_DEVICE_SECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, true);
            }
            break;
        case REQUEST_CONNECT_DEVICE_INSECURE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, false);
            }
            break;
        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                // Bluetooth is now enabled, so set up a chat session
                setupChat();
            } else {
                // User did not enable Bluetooth or an error occurred
                Log.d(TAG, "BT not enabled");
                Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    private void connectDevice(Intent data, boolean secure) {
        // Get the device MAC address
        String address = data.getExtras()
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
        // Get the BluetoothDevice object
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        // Attempt to connect to the device
        mChatService.connect(device, secure);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Intent serverIntent = null;
        switch (item.getItemId()) {
        case R.id.secure_connect_scan:
            // Launch the DeviceListActivity to see devices and do scan
            serverIntent = new Intent(this, DeviceListActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
            return true;
        case R.id.insecure_connect_scan:
            // Launch the DeviceListActivity to see devices and do scan
            serverIntent = new Intent(this, DeviceListActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
            return true;
        case R.id.discoverable:
            // Ensure this device is discoverable by others
            ensureDiscoverable();
            return true;
        }
        return false;
    }

}
//res\layout\custom_title.xml
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
  >
  <TextView android:id="@+id/title_left_text"
      android:layout_alignParentLeft="true"
      android:ellipsize="end"
      android:singleLine="true"
      style="?android:attr/windowTitleStyle"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_weight="1"
    />
    <TextView android:id="@+id/title_right_text"
        android:layout_alignParentRight="true"
        android:ellipsize="end"
        android:singleLine="true"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:textColor="#fff"
        android:layout_weight="1" 
    />
</RelativeLayout>



//res\layout\device_list.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView android:id="@+id/title_paired_devices"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/title_paired_devices"
        android:visibility="gone"
        android:background="#666"
        android:textColor="#fff"
        android:paddingLeft="5dp"
    />
    <ListView android:id="@+id/paired_devices"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stackFromBottom="true"
        android:layout_weight="1"
    />
    <TextView android:id="@+id/title_new_devices"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/title_other_devices"
        android:visibility="gone"
        android:background="#666"
        android:textColor="#fff"
        android:paddingLeft="5dp"
    />
    <ListView android:id="@+id/new_devices"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stackFromBottom="true"
        android:layout_weight="2"
    />
    <Button android:id="@+id/button_scan"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/button_scan"
    />
</LinearLayout>



//res\layout\device_name.xml
<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:padding="5dp"
/>



//res\layout\main.xml
<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ListView android:id="@+id/in"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:stackFromBottom="true"
        android:transcriptMode="alwaysScroll"
        android:layout_weight="1"
    />
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
        <EditText android:id="@+id/edit_text_out"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="bottom"
        />
        <Button android:id="@+id/button_send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/send"
        />
    </LinearLayout>
</LinearLayout>



//res\layout\message.xml
<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="18sp"
    android:padding="5dp"
/>



//res\menu\option_menu.xml
<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/secure_connect_scan"
          android:icon="@android:drawable/ic_menu_search"
          android:title="@string/secure_connect"
          android:showAsAction="ifRoom|withText" />
    <item android:id="@+id/insecure_connect_scan"
          android:icon="@android:drawable/ic_menu_search"
          android:title="@string/insecure_connect"
          android:showAsAction="ifRoom|withText" />
    <item android:id="@+id/discoverable"
          android:icon="@android:drawable/ic_menu_mylocation"
          android:title="@string/discoverable"
          android:showAsAction="ifRoom|withText" />
</menu>


//res\values\strings.xml
<?xml version="1.0" encoding="utf-8"?>


<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="app_name">Bluetooth Chat</string>

    <!--  BluetoothChat -->
    <string name="send">Send</string>
    <string name="not_connected">You are not connected to a device</string>
    <string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string>
    <string name="title_connecting">connecting...</string>
    <string name="title_connected_to">connected to <xliff:g id="device_name">%1$s</xliff:g></string>
    <string name="title_not_connected">not connected</string>

    <!--  DeviceListActivity -->
    <string name="scanning">scanning for devices...</string>
    <string name="select_device">select a device to connect</string>
    <string name="none_paired">No devices have been paired</string>
    <string name="none_found">No devices found</string>
    <string name="title_paired_devices">Paired Devices</string>
    <string name="title_other_devices">Other Available Devices</string>
    <string name="button_scan">Scan for devices</string>

    <!-- Options Menu -->
    <string name="secure_connect">Connect a device - Secure</string>
    <string name="insecure_connect">Connect a device - Insecure</string>
    <string name="discoverable">Make discoverable</string>
</resources>

External Storage Directory

   
package app.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Test extends Activity {
  private EditText textBox;
  private static final int READ_BLOCK_SIZE = 100;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InputStream is = this.getResources().openRawResource(R.raw.textfile);
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String str = null;
    try {
      while ((str = br.readLine()) != null) {
        Toast.makeText(getBaseContext(), str, Toast.LENGTH_SHORT)
            .show();
      }
      is.close();
      br.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

    textBox = (EditText) findViewById(R.id.txtText1);
    Button saveBtn = (Button) findViewById(R.id.btnSave);
    Button loadBtn = (Button) findViewById(R.id.btnLoad);

    saveBtn.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {

        String str = textBox.getText().toString();
        try {
          /*
           * //---Internal Storage--- FileOutputStream fOut =
           * openFileOutput("textfile.txt", MODE_WORLD_READABLE);
           *
           */
          File sdCard = Environment.getExternalStorageDirectory();
          File directory = new File(sdCard.getAbsolutePath()
              + "/MyFiles");
          directory.mkdirs();
          File file = new File(directory, "textfile.txt");
          FileOutputStream fOut = new FileOutputStream(file);
          OutputStreamWriter osw = new OutputStreamWriter(fOut);
          osw.write(str);
          osw.flush();
          osw.close();
          Toast.makeText(getBaseContext(),"File saved successfully!", Toast.LENGTH_SHORT).show();
          textBox.setText("");
        } catch (IOException ioe) {
          ioe.printStackTrace();
        }
      }
    });

    loadBtn.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        try {

          // ---SD Storage---
          File sdCard = Environment.getExternalStorageDirectory();
          File directory = new File(sdCard.getAbsolutePath()
              + "/MyFiles");
          File file = new File(directory, "textfile.txt");
          FileInputStream fIn = new FileInputStream(file);
          InputStreamReader isr = new InputStreamReader(fIn);
          char[] inputBuffer = new char[READ_BLOCK_SIZE];
          String s = "";
          int charRead;
          while ((charRead = isr.read(inputBuffer)) > 0) {

            String readString = String.copyValueOf(inputBuffer, 0,
                charRead);
            s += readString;

            inputBuffer = new char[READ_BLOCK_SIZE];
          }
          textBox.setText(s);

          Toast.makeText(getBaseContext(),
              "File loaded successfully!", Toast.LENGTH_SHORT)
              .show();
        } catch (IOException ioe) {
          ioe.printStackTrace();
        }
      }
    });
  }
}

//raw/textfile.txt

The quick brown fox jumps over the lazy dog

// main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Please enter some text"
    />
<EditText
    android:id="@+id/txtText1" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
    
<Button 
    android:id="@+id/btnSave"
    android:text="Save"  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" />

<Button 
    android:id="@+id/btnLoad"
    android:text="Load"  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" />

</LinearLayout>

A trivial joystick based physics game to demonstrate joystick handling.
package com.example.android.apis.view;

import com.example.android.apis.R;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.InputDevice.MotionRange;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLong;



public class GameControllerInput extends Activity {
    private static final String TAG = "GameControllerInput";

    private SparseArray<InputDeviceState> mInputDeviceStates;
    private GameView mGame;
    private ListView mSummaryList;
    private SummaryAdapter mSummaryAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mInputDeviceStates = new SparseArray<InputDeviceState>();
        mSummaryAdapter = new SummaryAdapter(this, getResources());

        setContentView(R.layout.game_controller_input);

        mGame = (GameView) findViewById(R.id.game);

        mSummaryList = (ListView) findViewById(R.id.summary);
        mSummaryList.setAdapter(mSummaryAdapter);
        mSummaryList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mSummaryAdapter.onItemClick(position);
            }
        });
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        mGame.requestFocus();
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        // Update device state for visualization and logging.
        InputDeviceState state = getInputDeviceState(event);
        if (state != null) {
            switch (event.getAction()) {
                case KeyEvent.ACTION_DOWN:
                    if (state.onKeyDown(event)) {
                        mSummaryAdapter.show(state);
                    }
                    break;
                case KeyEvent.ACTION_UP:
                    if (state.onKeyUp(event)) {
                        mSummaryAdapter.show(state);
                    }
                    break;
            }
        }
        return super.dispatchKeyEvent(event);
    }

    @Override
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        // Check that the event came from a joystick since a generic motion event
        // could be almost anything.
        if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0
                && event.getAction() == MotionEvent.ACTION_MOVE) {
            // Update device state for visualization and logging.
            InputDeviceState state = getInputDeviceState(event);
            if (state != null && state.onJoystickMotion(event)) {
                mSummaryAdapter.show(state);
            }
        }
        return super.dispatchGenericMotionEvent(event);
    }

    private InputDeviceState getInputDeviceState(InputEvent event) {
        final int deviceId = event.getDeviceId();
        InputDeviceState state = mInputDeviceStates.get(deviceId);
        if (state == null) {
            final InputDevice device = event.getDevice();
            if (device == null) {
                return null;
            }
            state = new InputDeviceState(device);
            mInputDeviceStates.put(deviceId, state);

            Log.i(TAG, device.toString());
        }
        return state;
    }

    /**
     * Tracks the state of joystick axes and game controller buttons for a particular
     * input device for diagnostic purposes.
     */
    private static class InputDeviceState {
        private final InputDevice mDevice;
        private final int[] mAxes;
        private final float[] mAxisValues;
        private final SparseIntArray mKeys;

        public InputDeviceState(InputDevice device) {
            mDevice = device;

            int numAxes = 0;
            for (MotionRange range : device.getMotionRanges()) {
                if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
                    numAxes += 1;
                }
            }

            mAxes = new int[numAxes];
            mAxisValues = new float[numAxes];
            int i = 0;
            for (MotionRange range : device.getMotionRanges()) {
                if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
                    numAxes += 1;
                }
                mAxes[i++] = range.getAxis();
            }

            mKeys = new SparseIntArray();
        }

        public InputDevice getDevice() {
            return mDevice;
        }

        public int getAxisCount() {
            return mAxes.length;
        }

        public int getAxis(int axisIndex) {
            return mAxes[axisIndex];
        }

        public float getAxisValue(int axisIndex) {
            return mAxisValues[axisIndex];
        }

        public int getKeyCount() {
            return mKeys.size();
        }

        public int getKeyCode(int keyIndex) {
            return mKeys.keyAt(keyIndex);
        }

        public boolean isKeyPressed(int keyIndex) {
            return mKeys.valueAt(keyIndex) != 0;
        }

        public boolean onKeyDown(KeyEvent event) {
            final int keyCode = event.getKeyCode();
            if (isGameKey(keyCode)) {
                if (event.getRepeatCount() == 0) {
                    final String symbolicName = KeyEvent.keyCodeToString(keyCode);
                    mKeys.put(keyCode, 1);
                    Log.i(TAG, mDevice.getName() + " - Key Down: " + symbolicName);
                }
                return true;
            }
            return false;
        }

        public boolean onKeyUp(KeyEvent event) {
            final int keyCode = event.getKeyCode();
            if (isGameKey(keyCode)) {
                int index = mKeys.indexOfKey(keyCode);
                if (index >= 0) {
                    final String symbolicName = KeyEvent.keyCodeToString(keyCode);
                    mKeys.put(keyCode, 0);
                    Log.i(TAG, mDevice.getName() + " - Key Up: " + symbolicName);
                }
                return true;
            }
            return false;
        }

        public boolean onJoystickMotion(MotionEvent event) {
            StringBuilder message = new StringBuilder();
            message.append(mDevice.getName()).append(" - Joystick Motion:\n");

            final int historySize = event.getHistorySize();
            for (int i = 0; i < mAxes.length; i++) {
                final int axis = mAxes[i];
                final float value = event.getAxisValue(axis);
                mAxisValues[i] = value;
                message.append("  ").append(MotionEvent.axisToString(axis)).append(": ");

                // Append all historical values in the batch.
                for (int historyPos = 0; historyPos < historySize; historyPos++) {
                    message.append(event.getHistoricalAxisValue(axis, historyPos));
                    message.append(", ");
                }

                // Append the current value.
                message.append(value);
                message.append("\n");
            }
            Log.i(TAG, message.toString());
            return true;
        }

        // Check whether this is a key we care about.
        // In a real game, we would probably let the user configure which keys to use
        // instead of hardcoding the keys like this.
        private static boolean isGameKey(int keyCode) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_UP:
                case KeyEvent.KEYCODE_DPAD_DOWN:
                case KeyEvent.KEYCODE_DPAD_LEFT:
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                case KeyEvent.KEYCODE_DPAD_CENTER:
                case KeyEvent.KEYCODE_SPACE:
                    return true;
                default:
                    return KeyEvent.isGamepadButton(keyCode);
            }
        }
    }

    /**
     * A list adapter that displays a summary of the device state.
     */
    private static class SummaryAdapter extends BaseAdapter {
        private static final int BASE_ID_HEADING = 1 << 10;
        private static final int BASE_ID_DEVICE_ITEM = 2 << 10;
        private static final int BASE_ID_AXIS_ITEM = 3 << 10;
        private static final int BASE_ID_KEY_ITEM = 4 << 10;

        private final Context mContext;
        private final Resources mResources;

        private final SparseArray<Item> mDataItems = new SparseArray<Item>();
        private final ArrayList<Item> mVisibleItems = new ArrayList<Item>();

        private final Heading mDeviceHeading;
        private final TextColumn mDeviceNameTextColumn;

        private final Heading mAxesHeading;
        private final Heading mKeysHeading;

        private InputDeviceState mState;

        public SummaryAdapter(Context context, Resources resources) {
            mContext = context;
            mResources = resources;

            mDeviceHeading = new Heading(BASE_ID_HEADING | 0,
                    mResources.getString(R.string.game_controller_input_heading_device));
            mDeviceNameTextColumn = new TextColumn(BASE_ID_DEVICE_ITEM | 0,
                    mResources.getString(R.string.game_controller_input_label_device_name));

            mAxesHeading = new Heading(BASE_ID_HEADING | 1,
                    mResources.getString(R.string.game_controller_input_heading_axes));
            mKeysHeading = new Heading(BASE_ID_HEADING | 2,
                    mResources.getString(R.string.game_controller_input_heading_keys));
        }

        public void onItemClick(int position) {
            if (mState != null) {
                Toast toast = Toast.makeText(
                        mContext, mState.getDevice().toString(), Toast.LENGTH_LONG);
                toast.show();
            }
        }

        public void show(InputDeviceState state) {
            mState = state;
            mVisibleItems.clear();

            // Populate device information.
            mVisibleItems.add(mDeviceHeading);
            mDeviceNameTextColumn.setContent(state.getDevice().getName());
            mVisibleItems.add(mDeviceNameTextColumn);

            // Populate axes.
            mVisibleItems.add(mAxesHeading);
            final int axisCount = state.getAxisCount();
            for (int i = 0; i < axisCount; i++) {
                final int axis = state.getAxis(i);
                final int id = BASE_ID_AXIS_ITEM | axis;
                TextColumn column = (TextColumn) mDataItems.get(id);
                if (column == null) {
                    column = new TextColumn(id, MotionEvent.axisToString(axis));
                    mDataItems.put(id, column);
                }
                column.setContent(Float.toString(state.getAxisValue(i)));
                mVisibleItems.add(column);
            }

            // Populate keys.
            mVisibleItems.add(mKeysHeading);
            final int keyCount = state.getKeyCount();
            for (int i = 0; i < keyCount; i++) {
                final int keyCode = state.getKeyCode(i);
                final int id = BASE_ID_KEY_ITEM | keyCode;
                TextColumn column = (TextColumn) mDataItems.get(id);
                if (column == null) {
                    column = new TextColumn(id, KeyEvent.keyCodeToString(keyCode));
                    mDataItems.put(id, column);
                }
                column.setContent(mResources.getString(state.isKeyPressed(i)
                        ? R.string.game_controller_input_key_pressed
                        : R.string.game_controller_input_key_released));
                mVisibleItems.add(column);
            }

            notifyDataSetChanged();
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public int getCount() {
            return mVisibleItems.size();
        }

        @Override
        public Item getItem(int position) {
            return mVisibleItems.get(position);
        }

        @Override
        public long getItemId(int position) {
            return getItem(position).getItemId();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return getItem(position).getView(convertView, parent);
        }

        private static abstract class Item {
            private final int mItemId;
            private final int mLayoutResourceId;
            private View mView;

            public Item(int itemId, int layoutResourceId) {
                mItemId = itemId;
                mLayoutResourceId = layoutResourceId;
            }

            public long getItemId() {
                return mItemId;
            }

            public View getView(View convertView, ViewGroup parent) {
                if (mView == null) {
                    LayoutInflater inflater = (LayoutInflater)
                            parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    mView = inflater.inflate(mLayoutResourceId, parent, false);
                    initView(mView);
                }
                updateView(mView);
                return mView;
            }

            protected void initView(View view) {
            }

            protected void updateView(View view) {
            }
        }

        private static class Heading extends Item {
            private final String mLabel;

            public Heading(int itemId, String label) {
                super(itemId, R.layout.game_controller_input_heading);
                mLabel = label;
            }

            @Override
            public void initView(View view) {
                TextView textView = (TextView) view;
                textView.setText(mLabel);
            }
        }

        private static class TextColumn extends Item {
            private final String mLabel;

            private String mContent;
            private TextView mContentView;

            public TextColumn(int itemId, String label) {
                super(itemId, R.layout.game_controller_input_text_column);
                mLabel = label;
            }

            public void setContent(String content) {
                mContent = content;
            }

            @Override
            public void initView(View view) {
                TextView textView = (TextView) view.findViewById(R.id.label);
                textView.setText(mLabel);

                mContentView = (TextView) view.findViewById(R.id.content);
            }

            @Override
            public void updateView(View view) {
                mContentView.setText(mContent);
            }
        }
    }
}


package com.example.android.apis.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.os.Handler;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * A trivial joystick based physics game to demonstrate joystick handling.
 *
 * @see GameControllerInput
 */
public class GameView extends View {
    private final long ANIMATION_TIME_STEP = 1000 / 60;
    private final int MAX_OBSTACLES = 12;

    private final Random mRandom;
    private Ship mShip;
    private final List<Bullet> mBullets;
    private final List<Obstacle> mObstacles;

    private long mLastStepTime;
    private InputDevice mLastInputDevice;

    private static final int DPAD_STATE_LEFT  = 1 << 0;
    private static final int DPAD_STATE_RIGHT = 1 << 1;
    private static final int DPAD_STATE_UP    = 1 << 2;
    private static final int DPAD_STATE_DOWN  = 1 << 3;

    private int mDPadState;

    private float mShipSize;
    private float mMaxShipThrust;
    private float mMaxShipSpeed;

    private float mBulletSize;
    private float mBulletSpeed;

    private float mMinObstacleSize;
    private float mMaxObstacleSize;
    private float mMinObstacleSpeed;
    private float mMaxObstacleSpeed;

    private final Runnable mAnimationRunnable = new Runnable() {
        public void run() {
            animateFrame();
        }
    };

    public GameView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mRandom = new Random();
        mBullets = new ArrayList<Bullet>();
        mObstacles = new ArrayList<Obstacle>();

        setFocusable(true);
        setFocusableInTouchMode(true);

        float baseSize = getContext().getResources().getDisplayMetrics().density * 5f;
        float baseSpeed = baseSize * 3;

        mShipSize = baseSize * 3;
        mMaxShipThrust = baseSpeed * 0.25f;
        mMaxShipSpeed = baseSpeed * 12;

        mBulletSize = baseSize;
        mBulletSpeed = baseSpeed * 12;

        mMinObstacleSize = baseSize * 2;
        mMaxObstacleSize = baseSize * 12;
        mMinObstacleSpeed = baseSpeed;
        mMaxObstacleSpeed = baseSpeed * 3;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // Reset the game when the view changes size.
        reset();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        ensureInitialized();

        // Handle DPad keys and fire button on initial down but not on auto-repeat.
        boolean handled = false;
        if (event.getRepeatCount() == 0) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    mShip.setHeadingX(-1);
                    mDPadState |= DPAD_STATE_LEFT;
                    handled = true;
                    break;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    mShip.setHeadingX(1);
                    mDPadState |= DPAD_STATE_RIGHT;
                    handled = true;
                    break;
                case KeyEvent.KEYCODE_DPAD_UP:
                    mShip.setHeadingY(-1);
                    mDPadState |= DPAD_STATE_UP;
                    handled = true;
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    mShip.setHeadingY(1);
                    mDPadState |= DPAD_STATE_DOWN;
                    handled = true;
                    break;
                default:
                    if (isFireKey(keyCode)) {
                        fire();
                        handled = true;
                    }
                    break;
            }
        }
        if (handled) {
            step(event.getEventTime());
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        ensureInitialized();

        // Handle keys going up.
        boolean handled = false;
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                mShip.setHeadingX(0);
                mDPadState &= ~DPAD_STATE_LEFT;
                handled = true;
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                mShip.setHeadingX(0);
                mDPadState &= ~DPAD_STATE_RIGHT;
                handled = true;
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                mShip.setHeadingY(0);
                mDPadState &= ~DPAD_STATE_UP;
                handled = true;
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                mShip.setHeadingY(0);
                mDPadState &= ~DPAD_STATE_DOWN;
                handled = true;
                break;
            default:
                if (isFireKey(keyCode)) {
                    handled = true;
                }
                break;
        }
        if (handled) {
            step(event.getEventTime());
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    private static boolean isFireKey(int keyCode) {
        return KeyEvent.isGamepadButton(keyCode)
                || keyCode == KeyEvent.KEYCODE_DPAD_CENTER
                || keyCode == KeyEvent.KEYCODE_SPACE;
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        ensureInitialized();

        // Check that the event came from a joystick since a generic motion event
        // could be almost anything.
        if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0
                && event.getAction() == MotionEvent.ACTION_MOVE) {
            // Cache the most recently obtained device information.
            // The device information may change over time but it can be
            // somewhat expensive to query.
            if (mLastInputDevice == null || mLastInputDevice.getId() != event.getDeviceId()) {
                mLastInputDevice = event.getDevice();
                // It's possible for the device id to be invalid.
                // In that case, getDevice() will return null.
                if (mLastInputDevice == null) {
                    return false;
                }
            }

            // Ignore joystick while the DPad is pressed to avoid conflicting motions.
            if (mDPadState != 0) {
                return true;
            }

            // Process all historical movement samples in the batch.
            final int historySize = event.getHistorySize();
            for (int i = 0; i < historySize; i++) {
                processJoystickInput(event, i);
            }

            // Process the current movement sample in the batch.
            processJoystickInput(event, -1);
            return true;
        }
        return super.onGenericMotionEvent(event);
    }

    private void processJoystickInput(MotionEvent event, int historyPos) {
        // Get joystick position.
        // Many game pads with two joysticks report the position of the second joystick
        // using the Z and RZ axes so we also handle those.
        // In a real game, we would allow the user to configure the axes manually.
        float x = getCenteredAxis(event, mLastInputDevice, MotionEvent.AXIS_X, historyPos);
        if (x == 0) {
            x = getCenteredAxis(event, mLastInputDevice, MotionEvent.AXIS_HAT_X, historyPos);
        }
        if (x == 0) {
            x = getCenteredAxis(event, mLastInputDevice, MotionEvent.AXIS_Z, historyPos);
        }

        float y = getCenteredAxis(event, mLastInputDevice, MotionEvent.AXIS_Y, historyPos);
        if (y == 0) {
            y = getCenteredAxis(event, mLastInputDevice, MotionEvent.AXIS_HAT_Y, historyPos);
        }
        if (y == 0) {
            y = getCenteredAxis(event, mLastInputDevice, MotionEvent.AXIS_RZ, historyPos);
        }

        // Set the ship heading.
        mShip.setHeading(x, y);
        step(historyPos < 0 ? event.getEventTime() : event.getHistoricalEventTime(historyPos));
    }

    private static float getCenteredAxis(MotionEvent event, InputDevice device,
            int axis, int historyPos) {
        final InputDevice.MotionRange range = device.getMotionRange(axis, event.getSource());
        if (range != null) {
            final float flat = range.getFlat();
            final float value = historyPos < 0 ? event.getAxisValue(axis)
                    : event.getHistoricalAxisValue(axis, historyPos);

            // Ignore axis values that are within the 'flat' region of the joystick axis center.
            // A joystick at rest does not always report an absolute position of (0,0).
            if (Math.abs(value) > flat) {
                return value;
            }
        }
        return 0;
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        // Turn on and off animations based on the window focus.
        // Alternately, we could update the game state using the Activity onResume()
        // and onPause() lifecycle events.
        if (hasWindowFocus) {
            getHandler().postDelayed(mAnimationRunnable, ANIMATION_TIME_STEP);
            mLastStepTime = SystemClock.uptimeMillis();
        } else {
            getHandler().removeCallbacks(mAnimationRunnable);

            mDPadState = 0;
            if (mShip != null) {
                mShip.setHeading(0, 0);
                mShip.setVelocity(0, 0);
            }
        }

        super.onWindowFocusChanged(hasWindowFocus);
    }

    private void fire() {
        if (mShip != null && !mShip.isDestroyed()) {
            Bullet bullet = new Bullet();
            bullet.setPosition(mShip.getBulletInitialX(), mShip.getBulletInitialY());
            bullet.setVelocity(mShip.getBulletVelocityX(mBulletSpeed),
                    mShip.getBulletVelocityY(mBulletSpeed));
            mBullets.add(bullet);
        }
    }

    private void ensureInitialized() {
        if (mShip == null) {
            reset();
        }
    }

    private void reset() {
        mShip = new Ship();
        mBullets.clear();
        mObstacles.clear();
    }

    void animateFrame() {
        long currentStepTime = SystemClock.uptimeMillis();
        step(currentStepTime);

        Handler handler = getHandler();
        if (handler != null) {
            handler.postAtTime(mAnimationRunnable, currentStepTime + ANIMATION_TIME_STEP);
            invalidate();
        }
    }

    private void step(long currentStepTime) {
        float tau = (currentStepTime - mLastStepTime) * 0.001f;
        mLastStepTime = currentStepTime;

        ensureInitialized();

        // Move the ship.
        mShip.accelerate(tau, mMaxShipThrust, mMaxShipSpeed);
        if (!mShip.step(tau)) {
            reset();
        }

        // Move the bullets.
        int numBullets = mBullets.size();
        for (int i = 0; i < numBullets; i++) {
            final Bullet bullet = mBullets.get(i);
            if (!bullet.step(tau)) {
                mBullets.remove(i);
                i -= 1;
                numBullets -= 1;
            }
        }

        // Move obstacles.
        int numObstacles = mObstacles.size();
        for (int i = 0; i < numObstacles; i++) {
            final Obstacle obstacle = mObstacles.get(i);
            if (!obstacle.step(tau)) {
                mObstacles.remove(i);
                i -= 1;
                numObstacles -= 1;
            }
        }

        // Check for collisions between bullets and obstacles.
        for (int i = 0; i < numBullets; i++) {
            final Bullet bullet = mBullets.get(i);
            for (int j = 0; j < numObstacles; j++) {
                final Obstacle obstacle = mObstacles.get(j);
                if (bullet.collidesWith(obstacle)) {
                    bullet.destroy();
                    obstacle.destroy();
                    break;
                }
            }
        }

        // Check for collisions between the ship and obstacles.
        for (int i = 0; i < numObstacles; i++) {
            final Obstacle obstacle = mObstacles.get(i);
            if (mShip.collidesWith(obstacle)) {
                mShip.destroy();
                obstacle.destroy();
                break;
            }
        }

        // Spawn more obstacles offscreen when needed.
        // Avoid putting them right on top of the ship.
        OuterLoop: while (mObstacles.size() < MAX_OBSTACLES) {
            final float minDistance = mShipSize * 4;
            float size = mRandom.nextFloat() * (mMaxObstacleSize - mMinObstacleSize)
                    + mMinObstacleSize;
            float positionX, positionY;
            int tries = 0;
            do {
                int edge = mRandom.nextInt(4);
                switch (edge) {
                    case 0:
                        positionX = -size;
                        positionY = mRandom.nextInt(getHeight());
                        break;
                    case 1:
                        positionX = getWidth() + size;
                        positionY = mRandom.nextInt(getHeight());
                        break;
                    case 2:
                        positionX = mRandom.nextInt(getWidth());
                        positionY = -size;
                        break;
                    default:
                        positionX = mRandom.nextInt(getWidth());
                        positionY = getHeight() + size;
                        break;
                }
                if (++tries > 10) {
                    break OuterLoop;
                }
            } while (mShip.distanceTo(positionX, positionY) < minDistance);

            float direction = mRandom.nextFloat() * (float) Math.PI * 2;
            float speed = mRandom.nextFloat() * (mMaxObstacleSpeed - mMinObstacleSpeed)
                    + mMinObstacleSpeed;
            float velocityX = (float) Math.cos(direction) * speed;
            float velocityY = (float) Math.sin(direction) * speed;

            Obstacle obstacle = new Obstacle();
            obstacle.setPosition(positionX, positionY);
            obstacle.setSize(size);
            obstacle.setVelocity(velocityX, velocityY);
            mObstacles.add(obstacle);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // Draw the ship.
        if (mShip != null) {
            mShip.draw(canvas);
        }

        // Draw bullets.
        int numBullets = mBullets.size();
        for (int i = 0; i < numBullets; i++) {
            final Bullet bullet = mBullets.get(i);
            bullet.draw(canvas);
        }

        // Draw obstacles.
        int numObstacles = mObstacles.size();
        for (int i = 0; i < numObstacles; i++) {
            final Obstacle obstacle = mObstacles.get(i);
            obstacle.draw(canvas);
        }
    }

    static float pythag(float x, float y) {
        return (float) Math.sqrt(x * x + y * y);
    }

    static int blend(float alpha, int from, int to) {
        return from + (int) ((to - from) * alpha);
    }

    static void setPaintARGBBlend(Paint paint, float alpha,
            int a1, int r1, int g1, int b1,
            int a2, int r2, int g2, int b2) {
        paint.setARGB(blend(alpha, a1, a2), blend(alpha, r1, r2),
                blend(alpha, g1, g2), blend(alpha, b1, b2));
    }

    private abstract class Sprite {
        protected float mPositionX;
        protected float mPositionY;
        protected float mVelocityX;
        protected float mVelocityY;
        protected float mSize;
        protected boolean mDestroyed;
        protected float mDestroyAnimProgress;

        public void setPosition(float x, float y) {
            mPositionX = x;
            mPositionY = y;
        }

        public void setVelocity(float x, float y) {
            mVelocityX = x;
            mVelocityY = y;
        }

        public void setSize(float size) {
            mSize = size;
        }

        public float distanceTo(float x, float y) {
            return pythag(mPositionX - x, mPositionY - y);
        }

        public float distanceTo(Sprite other) {
            return distanceTo(other.mPositionX, other.mPositionY);
        }

        public boolean collidesWith(Sprite other) {
            // Really bad collision detection.
            return !mDestroyed && !other.mDestroyed
                    && distanceTo(other) <= Math.max(mSize, other.mSize)
                            + Math.min(mSize, other.mSize) * 0.5f;
        }

        public boolean isDestroyed() {
            return mDestroyed;
        }

        public boolean step(float tau) {
            mPositionX += mVelocityX * tau;
            mPositionY += mVelocityY * tau;

            if (mDestroyed) {
                mDestroyAnimProgress += tau / getDestroyAnimDuration();
                if (mDestroyAnimProgress >= 1.0f) {
                    return false;
                }
            }
            return true;
        }

        public abstract void draw(Canvas canvas);

        public abstract float getDestroyAnimDuration();

        protected boolean isOutsidePlayfield() {
            final int width = GameView.this.getWidth();
            final int height = GameView.this.getHeight();
            return mPositionX < 0 || mPositionX >= width
                    || mPositionY < 0 || mPositionY >= height;
        }

        protected void wrapAtPlayfieldBoundary() {
            final int width = GameView.this.getWidth();
            final int height = GameView.this.getHeight();
            while (mPositionX <= -mSize) {
                mPositionX += width + mSize * 2;
            }
            while (mPositionX >= width + mSize) {
                mPositionX -= width + mSize * 2;
            }
            while (mPositionY <= -mSize) {
                mPositionY += height + mSize * 2;
            }
            while (mPositionY >= height + mSize) {
                mPositionY -= height + mSize * 2;
            }
        }

        public void destroy() {
            mDestroyed = true;
            step(0);
        }
    }

    private class Ship extends Sprite {
        private static final float CORNER_ANGLE = (float) Math.PI * 2 / 3;
        private static final float TO_DEGREES = (float) (180.0 / Math.PI);

        private float mHeadingX;
        private float mHeadingY;
        private float mHeadingAngle;
        private float mHeadingMagnitude;
        private final Paint mPaint;
        private final Path mPath;


        public Ship() {
            mPaint = new Paint();
            mPaint.setStyle(Style.FILL);

            setPosition(getWidth() * 0.5f, getHeight() * 0.5f);
            setVelocity(0, 0);
            setSize(mShipSize);

            mPath = new Path();
            mPath.moveTo(0, 0);
            mPath.lineTo((float)Math.cos(-CORNER_ANGLE) * mSize,
                    (float)Math.sin(-CORNER_ANGLE) * mSize);
            mPath.lineTo(mSize, 0);
            mPath.lineTo((float)Math.cos(CORNER_ANGLE) * mSize,
                    (float)Math.sin(CORNER_ANGLE) * mSize);
            mPath.lineTo(0, 0);
        }

        public void setHeadingX(float x) {
            mHeadingX = x;
            updateHeading();
        }

        public void setHeadingY(float y) {
            mHeadingY = y;
            updateHeading();
        }

        public void setHeading(float x, float y) {
            mHeadingX = x;
            mHeadingY = y;
            updateHeading();
        }

        private void updateHeading() {
            mHeadingMagnitude = pythag(mHeadingX, mHeadingY);
            if (mHeadingMagnitude > 0.1f) {
                mHeadingAngle = (float) Math.atan2(mHeadingY, mHeadingX);
            }
        }

        private float polarX(float radius) {
            return (float) Math.cos(mHeadingAngle) * radius;
        }

        private float polarY(float radius) {
            return (float) Math.sin(mHeadingAngle) * radius;
        }

        public float getBulletInitialX() {
            return mPositionX + polarX(mSize);
        }

        public float getBulletInitialY() {
            return mPositionY + polarY(mSize);
        }

        public float getBulletVelocityX(float relativeSpeed) {
            return mVelocityX + polarX(relativeSpeed);
        }

        public float getBulletVelocityY(float relativeSpeed) {
            return mVelocityY + polarY(relativeSpeed);
        }

        public void accelerate(float tau, float maxThrust, float maxSpeed) {
            final float thrust = mHeadingMagnitude * maxThrust;
            mVelocityX += polarX(thrust);
            mVelocityY += polarY(thrust);

            final float speed = pythag(mVelocityX, mVelocityY);
            if (speed > maxSpeed) {
                final float scale = maxSpeed / speed;
                mVelocityX = mVelocityX * scale;
                mVelocityY = mVelocityY * scale;
            }
        }

        @Override
        public boolean step(float tau) {
            if (!super.step(tau)) {
                return false;
            }
            wrapAtPlayfieldBoundary();
            return true;
        }

        public void draw(Canvas canvas) {
            setPaintARGBBlend(mPaint, mDestroyAnimProgress,
                    255, 63, 255, 63,
                    0, 255, 0, 0);

            canvas.save(Canvas.MATRIX_SAVE_FLAG);
            canvas.translate(mPositionX, mPositionY);
            canvas.rotate(mHeadingAngle * TO_DEGREES);
            canvas.drawPath(mPath, mPaint);
            canvas.restore();
        }

        @Override
        public float getDestroyAnimDuration() {
            return 1.0f;
        }
    }

    private class Bullet extends Sprite {
        private final Paint mPaint;

        public Bullet() {
            mPaint = new Paint();
            mPaint.setStyle(Style.FILL);

            setSize(mBulletSize);
        }

        @Override
        public boolean step(float tau) {
            if (!super.step(tau)) {
                return false;
            }
            return !isOutsidePlayfield();
        }

        public void draw(Canvas canvas) {
            setPaintARGBBlend(mPaint, mDestroyAnimProgress,
                    255, 255, 255, 0,
                    0, 255, 255, 255);
            canvas.drawCircle(mPositionX, mPositionY, mSize, mPaint);
        }

        @Override
        public float getDestroyAnimDuration() {
            return 0.125f;
        }
    }

    private class Obstacle extends Sprite {
        private final Paint mPaint;

        public Obstacle() {
            mPaint = new Paint();
            mPaint.setARGB(255, 127, 127, 255);
            mPaint.setStyle(Style.FILL);
        }

        @Override
        public boolean step(float tau) {
            if (!super.step(tau)) {
                return false;
            }
            wrapAtPlayfieldBoundary();
            return true;
        }

        public void draw(Canvas canvas) {
            setPaintARGBBlend(mPaint, mDestroyAnimProgress,
                    255, 127, 127, 255,
                    0, 255, 0, 0);
            canvas.drawCircle(mPositionX, mPositionY,
                    mSize * (1.0f - mDestroyAnimProgress), mPaint);
        }

        @Override
        public float getDestroyAnimDuration() {
            return 0.25f;
        }
    }
}
//layout/game_controller_input.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/game_controller_input_description"
        android:padding="12dip" />

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:padding="12dip">
        <ListView
            android:id="@+id/summary"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:padding="3dip">
        </ListView>

        <com.example.android.apis.view.GameView
            android:id="@+id/game"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#000000"
            android:padding="3dip" />
    </LinearLayout>
</LinearLayout>

oystick View

 
//package com.MobileAnarchy.Android.Widgets.Joystick;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
interface JoystickClickedListener {
  public void OnClicked();
  public void OnReleased();
}

public class JoystickView extends View {
  public static final int INVALID_POINTER_ID = -1;
  
  private final boolean D = false;
  String TAG = "JoystickView";
  
  private Paint dbgPaint1;
  private Paint dbgPaint2;
  
  private Paint bgPaint;
  private Paint handlePaint;
  
  private int innerPadding;
  private int bgRadius;
  private int handleRadius;
  private int movementRadius;
  private int handleInnerBoundaries;
  
  private JoystickMovedListener moveListener;
  private JoystickClickedListener clickListener;

  //# of pixels movement required between reporting to the listener
  private float moveResolution;

  private boolean yAxisInverted;
  private boolean autoReturnToCenter;
  
  //Max range of movement in user coordinate system
  public final static int CONSTRAIN_BOX = 0;
  public final static int CONSTRAIN_CIRCLE = 1;
  private int movementConstraint;
  private float movementRange;

  public final static int COORDINATE_CARTESIAN = 0;    //Regular cartesian coordinates
  public final static int COORDINATE_DIFFERENTIAL = 1;  //Uses polar rotation of 45 degrees to calc differential drive paramaters
  private int userCoordinateSystem;
  
  //Records touch pressure for click handling
  private float touchPressure;
  private boolean clicked;
  private float clickThreshold;
  
  //Last touch point in view coordinates
  private int pointerId = INVALID_POINTER_ID;
  private float touchX, touchY;
  
  //Last reported position in view coordinates (allows different reporting sensitivities)
  private float reportX, reportY;
  
  //Handle center in view coordinates
  private float handleX, handleY;
  
  //Center of the view in view coordinates
  private int cX, cY;

  //Size of the view in view coordinates
  private int dimX, dimY;

  //Cartesian coordinates of last touch point - joystick center is (0,0)
  private int cartX, cartY;
  
  //Polar coordinates of the touch point from joystick center
  private double radial;
  private double angle;
  
  //User coordinates of last touch point
  private int userX, userY;

  //Offset co-ordinates (used when touch events are received from parent's coordinate origin)
  private int offsetX;
  private int offsetY;

  public JoystickView(Context context) {
    super(context);
    initJoystickView();
  }

  public JoystickView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initJoystickView();
  }

  public JoystickView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initJoystickView();
  }


  private void initJoystickView() {
    setFocusable(true);

    dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
    dbgPaint1.setColor(Color.RED);
    dbgPaint1.setStrokeWidth(1);
    dbgPaint1.setStyle(Paint.Style.STROKE);
    
    dbgPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
    dbgPaint2.setColor(Color.GREEN);
    dbgPaint2.setStrokeWidth(1);
    dbgPaint2.setStyle(Paint.Style.STROKE);
    
    bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    bgPaint.setStyle(Paint.Style.FILL);

    handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    handlePaint.setColor(Color.rgb(8, 8, 8));
    handlePaint.setStrokeWidth(1);
    handlePaint.setStyle(Paint.Style.FILL_AND_STROKE);

    innerPadding = 10;
    
    setMovementRange(150);
    setMoveResolution(0.1f);
    setClickThreshold(0.4f);
    setYAxisInverted(false);
    setUserCoordinateSystem(COORDINATE_CARTESIAN);
    setAutoReturnToCenter(true);
  }

  public void setAutoReturnToCenter(boolean autoReturnToCenter) {
    this.autoReturnToCenter = autoReturnToCenter;
  }
  
  public boolean isAutoReturnToCenter() {
    return autoReturnToCenter;
  }
  
  public void setUserCoordinateSystem(int userCoordinateSystem) {
    if (userCoordinateSystem < COORDINATE_CARTESIAN || movementConstraint > COORDINATE_DIFFERENTIAL)
      Log.e(TAG, "invalid value for userCoordinateSystem");
    else
      this.userCoordinateSystem = userCoordinateSystem;
  }
  
  public int getUserCoordinateSystem() {
    return userCoordinateSystem;
  }
  
  public void setMovementConstraint(int movementConstraint) {
    if (movementConstraint < CONSTRAIN_BOX || movementConstraint > CONSTRAIN_CIRCLE)
      Log.e(TAG, "invalid value for movementConstraint");
    else
      this.movementConstraint = movementConstraint;
  }
  
  public int getMovementConstraint() {
    return movementConstraint;
  }
  
  public boolean isYAxisInverted() {
    return yAxisInverted;
  }
  
  public void setYAxisInverted(boolean yAxisInverted) {
    this.yAxisInverted = yAxisInverted;
  }
  
  /**
   * Set the pressure sensitivity for registering a click
   * @param clickThreshold threshold 0...1.0f inclusive. 0 will cause clicks to never be reported, 1.0 is a very hard click
   */
  public void setClickThreshold(float clickThreshold) {
    if (clickThreshold < 0 || clickThreshold > 1.0f)
      Log.e(TAG, "clickThreshold must range from 0...1.0f inclusive");
    else
      this.clickThreshold = clickThreshold;
  }
  
  public float getClickThreshold() {
    return clickThreshold;
  }
  
  public void setMovementRange(float movementRange) {
    this.movementRange = movementRange;
  }
  
  public float getMovementRange() {
    return movementRange;
  }
  
  public void setMoveResolution(float moveResolution) {
    this.moveResolution = moveResolution;
  }
  
  public float getMoveResolution() {
    return moveResolution;
  }
  

  public void setOnJostickMovedListener(JoystickMovedListener listener) {
    this.moveListener = listener;
  }
  
  public void setOnJostickClickedListener(JoystickClickedListener listener) {
    this.clickListener = listener;
  }
  

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Here we make sure that we have a perfect circle
    int measuredWidth = measure(widthMeasureSpec);
    int measuredHeight = measure(heightMeasureSpec);
    setMeasuredDimension(measuredWidth, measuredHeight);
  }

  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    int d = Math.min(getMeasuredWidth(), getMeasuredHeight());

    dimX = d;
    dimY = d;

    cX = d / 2;
    cY = d / 2;
    
    bgRadius = dimX/2 - innerPadding;
    
    // Texturize the back of the joysticks
    Bitmap backTexture = null;//BitmapFactory.decodeResource(getResources(), R.drawable.joy_back);
    backTexture = Bitmap.createScaledBitmap(backTexture, dimX, dimY, true);
    BitmapShader backShader = new BitmapShader(backTexture, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
    bgPaint.setShader(backShader);
    
    handleRadius = (int)(d * 0.25);
    handleInnerBoundaries = handleRadius;
    movementRadius = Math.min(cX, cY) - handleInnerBoundaries;
  }

  private int measure(int measureSpec) {
    int result = 0;
    // Decode the measurement specifications.
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if (specMode == MeasureSpec.UNSPECIFIED) {
      // Return a default size of 200 if no bounds are specified.
      result = 200;
    } else {
      // As you want to fill the available space
      // always return the full available bounds.
      result = specSize;
    }
    return result;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    canvas.save();
    // Draw the background
    canvas.drawCircle(cX, cY, bgRadius, bgPaint);

    // Draw the handle
    handleX = touchX + cX;
    handleY = touchY + cY;
    canvas.drawCircle(handleX, handleY, handleRadius, handlePaint);

    if (D) {
      canvas.drawRect(1, 1, getMeasuredWidth()-1, getMeasuredHeight()-1, dbgPaint1);
      
      canvas.drawCircle(handleX, handleY, 3, dbgPaint1);
      
      if ( movementConstraint == CONSTRAIN_CIRCLE ) {
        canvas.drawCircle(cX, cY, this.movementRadius, dbgPaint1);
      }
      else {
        canvas.drawRect(cX-movementRadius, cY-movementRadius, cX+movementRadius, cY+movementRadius, dbgPaint1);
      }
      
      //Origin to touch point
      canvas.drawLine(cX, cY, handleX, handleY, dbgPaint2);
      
      int baseY = (int) (touchY < 0 ? cY + handleRadius : cY - handleRadius);
      canvas.drawText(String.format("%s (%.0f,%.0f)", TAG, touchX, touchY), handleX-20, baseY-7, dbgPaint2);
      canvas.drawText("("+ String.format("%.0f, %.1f", radial, angle * 57.2957795) + (char) 0x00B0 + ")", handleX-20, baseY+15, dbgPaint2);
    }

//    Log.d(TAG, String.format("touch(%f,%f)", touchX, touchY));
//    Log.d(TAG, String.format("onDraw(%.1f,%.1f)\n\n", handleX, handleY));
    canvas.restore();
  }

  // Constrain touch within a box
  private void constrainBox() {
    touchX = Math.max(Math.min(touchX, movementRadius), -movementRadius);
    touchY = Math.max(Math.min(touchY, movementRadius), -movementRadius);
  }

  // Constrain touch within a circle
  private void constrainCircle() {
    float diffX = touchX;
    float diffY = touchY;
    double radial = Math.sqrt((diffX*diffX) + (diffY*diffY));
    if ( radial > movementRadius ) {
      touchX = (int)((diffX / radial) * movementRadius);
      touchY = (int)((diffY / radial) * movementRadius);
    }
  }
  
  public void setPointerId(int id) {
    this.pointerId = id;
  }
  
  public int getPointerId() {
    return pointerId;
  }

  @Override
  public boolean onTouchEvent(MotionEvent ev) {
      final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_MOVE: {
          return processMoveEvent(ev);
        }      
        case MotionEvent.ACTION_CANCEL: 
        case MotionEvent.ACTION_UP: {
          if ( pointerId != INVALID_POINTER_ID ) {
//            Log.d(TAG, "ACTION_UP");
            returnHandleToCenter();
              setPointerId(INVALID_POINTER_ID);
          }
            break;
        }
        case MotionEvent.ACTION_POINTER_UP: {
          if ( pointerId != INVALID_POINTER_ID ) {
              final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
              final int pointerId = ev.getPointerId(pointerIndex);
              if ( pointerId == this.pointerId ) {
//                Log.d(TAG, "ACTION_POINTER_UP: " + pointerId);
                returnHandleToCenter();
                setPointerId(INVALID_POINTER_ID);
              return true;
              }
          }
            break;
        }
        case MotionEvent.ACTION_DOWN: {
          if ( pointerId == INVALID_POINTER_ID ) {
            int x = (int) ev.getX();
            if ( x >= offsetX && x < offsetX + dimX ) {
                setPointerId(ev.getPointerId(0));
//                Log.d(TAG, "ACTION_DOWN: " + getPointerId());
              return true;
            }
          }
            break;
        }
        case MotionEvent.ACTION_POINTER_DOWN: {
          if ( pointerId == INVALID_POINTER_ID ) {
              final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
              final int pointerId = ev.getPointerId(pointerIndex);
            int x = (int) ev.getX(pointerId);
            if ( x >= offsetX && x < offsetX + dimX ) {
//                Log.d(TAG, "ACTION_POINTER_DOWN: " + pointerId);
                setPointerId(pointerId);
              return true;
            }
          }
            break;
        }
      }
    return false;
  }
  
  private boolean processMoveEvent(MotionEvent ev) {
    if ( pointerId != INVALID_POINTER_ID ) {
      final int pointerIndex = ev.findPointerIndex(pointerId);
      
      // Translate touch position to center of view
      float x = ev.getX(pointerIndex);
      touchX = x - cX - offsetX;
      float y = ev.getY(pointerIndex);
      touchY = y - cY - offsetY;

//          Log.d(TAG, String.format("ACTION_MOVE: (%03.0f, %03.0f) => (%03.0f, %03.0f)", x, y, touchX, touchY));
          
      reportOnMoved();
      invalidate();
      
      touchPressure = ev.getPressure(pointerIndex);
      reportOnPressure();
      
      return true;
    }
    return false;
  }

  private void reportOnMoved() {
    if ( movementConstraint == CONSTRAIN_CIRCLE )
      constrainCircle();
    else
      constrainBox();

    calcUserCoordinates();

    if (moveListener != null) {
      boolean rx = Math.abs(touchX - reportX) >= moveResolution;
      boolean ry = Math.abs(touchY - reportY) >= moveResolution;
      if (rx || ry) {
        this.reportX = touchX;
        this.reportY = touchY;
        
//        Log.d(TAG, String.format("moveListener.OnMoved(%d,%d)", (int)userX, (int)userY));
        moveListener.OnMoved(userX, userY);
      }
    }
  }

  private void calcUserCoordinates() {
    //First convert to cartesian coordinates
    cartX = (int)(touchX / movementRadius * movementRange);
    cartY = (int)(touchY / movementRadius * movementRange);
    
    radial = Math.sqrt((cartX*cartX) + (cartY*cartY));
    angle = Math.atan2(cartY, cartX);
    
    //Invert Y axis if requested
    if ( !yAxisInverted )
      cartY  *= -1;
    
    if ( userCoordinateSystem == COORDINATE_CARTESIAN ) {
      userX = cartX;
      userY = cartY;
    }
    else if ( userCoordinateSystem == COORDINATE_DIFFERENTIAL ) {
      userX = cartY + cartX / 4;
      userY = cartY - cartX / 4;
      
      if ( userX < -movementRange )
        userX = (int)-movementRange;
      if ( userX > movementRange )
        userX = (int)movementRange;

      if ( userY < -movementRange )
        userY = (int)-movementRange;
      if ( userY > movementRange )
        userY = (int)movementRange;
    }
    
  }
  
  //Simple pressure click
  private void reportOnPressure() {
//    Log.d(TAG, String.format("touchPressure=%.2f", this.touchPressure));
    if ( clickListener != null ) {
      if ( clicked && touchPressure < clickThreshold ) {
        clickListener.OnReleased();
        this.clicked = false;
//        Log.d(TAG, "reset click");
        invalidate();
      }
      else if ( !clicked && touchPressure >= clickThreshold ) {
        clicked = true;
        clickListener.OnClicked();
//        Log.d(TAG, "click");
        invalidate();
        performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
      }
    }
  }

  private void returnHandleToCenter() {
    if ( autoReturnToCenter ) {
      final int numberOfFrames = 5;
      final double intervalsX = (0 - touchX) / numberOfFrames;
      final double intervalsY = (0 - touchY) / numberOfFrames;

      for (int i = 0; i < numberOfFrames; i++) {
        final int j = i;
        postDelayed(new Runnable() {
          @Override
          public void run() {
            touchX += intervalsX;
            touchY += intervalsY;
            
            reportOnMoved();
            invalidate();
            
            if (moveListener != null && j == numberOfFrames - 1) {
              moveListener.OnReturnedToCenter();
            }
          }
        }, i * 40);
      }

      if (moveListener != null) {
        moveListener.OnReleased();
      }
    }
  }

  public void setTouchOffset(int x, int y) {
    offsetX = x;
    offsetY = y;
  }
}
interface JoystickMovedListener {
  public void OnMoved(int pan, int tilt);
  public void OnReleased();
  public void OnReturnedToCenter();
}

Get Display Metrics

 
package app.test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import android.util.Log;

class CMDExecute {

  public synchronized String run(String[] cmd, String workdirectory)
      throws IOException {
    String result = "";

    try {
      ProcessBuilder builder = new ProcessBuilder(cmd);
      // set working directory
      if (workdirectory != null)
        builder.directory(new File(workdirectory));
      builder.redirectErrorStream(true);
      Process process = builder.start();
      InputStream in = process.getInputStream();
      byte[] re = new byte[1024];
      while (in.read(re) != -1) {
        System.out.println(new String(re));
        result = result + new String(re);
      }
      in.close();

    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return result;
  }

}

public class Main {
  private static StringBuffer buffer;
  public static String getDisplayMetrics(Context cx) {
    String str = "";
    DisplayMetrics dm = new DisplayMetrics();
    dm = cx.getApplicationContext().getResources().getDisplayMetrics();
    int screenWidth = dm.widthPixels;
    int screenHeight = dm.heightPixels;
    float density = dm.density;
    float xdpi = dm.xdpi;
    float ydpi = dm.ydpi;
    str += "The absolute width:" + String.valueOf(screenWidth) + "pixels\n";
    str += "The absolute heightin:" + String.valueOf(screenHeight)
        + "pixels\n";
    str += "The logical density of the display.:" + String.valueOf(density)
        + "\n";
    str += "X dimension :" + String.valueOf(xdpi) + "pixels per inch\n";
    str += "Y dimension :" + String.valueOf(ydpi) + "pixels per inch\n";
    return str;
  }
}

GpsUtils contains code snippets for GPS.

  
//package backend.snippets;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;

/**
 * GpsUtils contains code snippets for GPS.
 * @author Maurya
 *
 */
class GpsUtils {
  
  static Location loc; // CLEAN THIS THING!
  private static LocationManager locationManager;

  void getLocation(Activity activity) {
      // Acquire a reference to the system Location Manager
      locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);

      // Register the listener with the Location Manager to receive location updates
      locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationUpdateHandler());
  }
  
  static Location getLastKnownLocation() {
    String locationProvider = LocationManager.GPS_PROVIDER;
    // Or use LocationManager.GPS_PROVIDER

    Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
    return lastKnownLocation;
  }
  
  public class LocationUpdateHandler implements LocationListener {
      public void onLocationChanged(Location location) {
          // Called when a new location is found by the network location provider.
          makeUseOfNewLocation(location);
        }

        private void makeUseOfNewLocation(Location location) {
          loc = location;
          
          // Remove the listener you previously added
          locationManager.removeUpdates(this);
        }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

        public void onProviderEnabled(String provider) {}

        public void onProviderDisabled(String provider) {}
    
  }

}

Gps Helper

  
//package djrain.lib;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;

public class GpsHelper implements LocationListener {
  private static final String tag = "LocationHelper";
  private String bestProvider;
  private LocationManager locationManager;

  private OnLocationChangeListener listener;

  private Location location;
  private String gpsProvider;

  static long MINTIME = 3000;
  static float MINDISTANCE = 0f;
  static float SPEED_UNIT = 1f;


  static public interface OnLocationChangeListener
  {
    public void onLocationChanged(Location location);
  }

  void setOnLocationChangeListener(OnLocationChangeListener listener)
  {
    this.listener = listener;
  }

  public Location getLocation()
  {
    return location;
  }

  public GpsHelper(Context context)
  {
    locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    findBestProvider();
  }

  public void findBestProvider()
  {
    // if(bestProvider != null &&
    // locationManager.isProviderEnabled(bestProvider)){
    // }

    Criteria criteria = new Criteria();
    bestProvider = locationManager.getBestProvider(criteria, false);
    location = locationManager.getLastKnownLocation(bestProvider);
    Log.e("Lilo", "find best provider:" + bestProvider);
    printProvider(bestProvider);

    // if(bestProvider == null)
    {
      gpsProvider = LocationManager.GPS_PROVIDER;
      bestProvider = gpsProvider;
    }
  }

  protected void onResume()
  {
    locationManager.requestLocationUpdates(bestProvider, MINTIME, MINDISTANCE, this);
  }

  protected void onPause()
  {
    locationManager.removeUpdates(this);
  }

  
  public void onLocationChanged(Location location)
  {

    if (location == null)
      return;

    printLocation(location);

    this.location = location;

    if (listener != null)
    {
      listener.onLocationChanged(location);
    }
  }

  public void onProviderDisabled(String provider)
  {
    Log.e(tag, "onProviderDisabled:  " + provider);
  }

  public void onProviderEnabled(String provider)
  {
    Log.e(tag, "onProviderEnabled:  " + provider);
  }

  public void onStatusChanged(String provider, int status, Bundle extras)
  {
    Log.e(tag, "onStatusChanged:  " + provider + "," + status);
  }

  private void printLocation(Location location)
  {
    if (location == null)
    {
      Log.e(tag, "Location[unknown]");
    }
    else
    {
      Log.e(tag, "" + location.getSpeed());
      Log.e(tag, "" + location.getLongitude());
      Log.e(tag, "" + location.getLatitude());
    }
  }

  private void printProvider(String provider)
  {
    LocationProvider info = locationManager.getProvider(provider);
    StringBuilder builder = new StringBuilder();
    builder.append("LocationProvider[").append("name=").append(info.getName()).append(",enabled=").append(locationManager.isProviderEnabled(provider)).append(",getAccuracy=")
        .append(info.getAccuracy()).append(",getPowerRequirement=").append(info.getPowerRequirement()).append(",hasMonetaryCost=").append(info.hasMonetaryCost()).append(",requiresCell=")
        .append(info.requiresCell()).append(",requiresNetwork=").append(info.requiresNetwork()).append(",requiresSatellite=").append(info.requiresSatellite()).append(",supportsAltitude=")
        .append(info.supportsAltitude()).append(",supportsBearing=").append(info.supportsBearing()).append(",supportsSpeed=").append(info.supportsSpeed()).append("]");
    Log.e(tag, builder.toString());
  }
}

Using PowerManager

  
package app.test;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.provider.Settings;
import android.util.Log;

public class Test extends Activity implements SensorEventListener {
    private WakeLock mWakelock = null;
  private SensorManager mMgr;
    private Sensor mAccel;
    private BufferedWriter mLog;
  final private SimpleDateFormat mTimeFormat = new SimpleDateFormat("HH:mm:ss - ");
  private int mSavedTimeout;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mMgr = (SensorManager) this.getSystemService(SENSOR_SERVICE);
        mAccel = mMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        try {
            String filename = Environment.getExternalStorageDirectory().getAbsolutePath() +"/accel.log";
            mLog = new BufferedWriter(new FileWriter(filename, true));
        }
        catch(Exception e) {
          e.printStackTrace();
          finish();
        }

        PowerManager pwrMgr = (PowerManager) this.getSystemService(POWER_SERVICE);
        mWakelock = pwrMgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Accel");
        mWakelock.acquire();

        try {
          mSavedTimeout = Settings.System.getInt(getContentResolver(), 
              Settings.System.SCREEN_OFF_TIMEOUT);
        }
        catch(Exception e) {
          mSavedTimeout = 120000;
        }
        Settings.System.putInt(getContentResolver(), 
            Settings.System.SCREEN_OFF_TIMEOUT, 5000);
    }

    public BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
                writeLog("The screen has turned off");
                mMgr.unregisterListener(Test.this);
                mMgr.registerListener(Test.this, mAccel,
                    SensorManager.SENSOR_DELAY_NORMAL);
            }
        }
    };
    @Override
    protected void onStart() {
        mMgr.registerListener(this, mAccel, SensorManager.SENSOR_DELAY_NORMAL);
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mReceiver, filter);
      super.onStart();
    }
    @Override
    protected void onStop() {
        mMgr.unregisterListener(this, mAccel);
        unregisterReceiver(mReceiver);
        try {
      mLog.flush();
    } catch (IOException e) {
    }
      super.onStop();
    }
    @Override
    protected void onDestroy() {
      try {
          mLog.flush();
          mLog.close();
      }
      catch(Exception e) {
      }
        Settings.System.putInt(getContentResolver(), 
                Settings.System.SCREEN_OFF_TIMEOUT, mSavedTimeout);
        mWakelock.release();
        super.onDestroy();
    }
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
  }
  public void onSensorChanged(SensorEvent event) {
    writeLog("Got a sensor event: " + event.values[0] + ", " +
        event.values[1] + ", " + event.values[2]);
  }
  private void writeLog(String str) {
    try {
        Date now = new Date();
        mLog.write(mTimeFormat.format(now));
      mLog.write(str);
      mLog.write("\n");
    }
    catch(IOException ioe) {
      ioe.printStackTrace();
    }
  }
}

SensorManager Demo

 
//main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TableLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:stretchColumns="0,1,2">
    <TableRow
      android:layout_weight="1">
      <View
        android:id="@+id/top"
        android:layout_column="1"
      />
    </TableRow>
    <TableRow
      android:layout_weight="1">
      <View
        android:id="@+id/left"
        android:layout_column="0"
      />
      <View
        android:id="@+id/right"
        android:layout_column="2"
      />
    </TableRow>
    <TableRow
      android:layout_weight="1">
      <View
        android:id="@+id/bottom"
        android:layout_column="1"
      />
    </TableRow>
  </TableLayout>
  <TextView  
    android:id="@+id/values"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true"
  />
</RelativeLayout>
package app.test;

import android.app.Activity;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class Test extends Activity implements SensorEventListener {
    
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
    private TextView valueView;
    private View mTop, mBottom, mLeft, mRight;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        
        valueView = (TextView)findViewById(R.id.values);
        mTop = findViewById(R.id.top);
        mBottom = findViewById(R.id.bottom);
        mLeft = findViewById(R.id.left);
        mRight = findViewById(R.id.right);
    }

    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
    }

    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) { }

    public void onSensorChanged(SensorEvent event) {
        float[] values = event.values;
        float x = values[0]/10;
        float y = values[1]/10;
        int scaleFactor;
        
        if(x > 0) {
            scaleFactor = (int)Math.min(x*255, 255);
            mRight.setBackgroundColor(Color.TRANSPARENT);
            mLeft.setBackgroundColor(Color.argb(scaleFactor, 255, 0, 0));
        } else {
            scaleFactor = (int)Math.min(Math.abs(x)*255, 255);
            mRight.setBackgroundColor(Color.argb(scaleFactor, 255, 0, 0));
            mLeft.setBackgroundColor(Color.TRANSPARENT);
        }
        
        if(y > 0) {
            scaleFactor = (int)Math.min(y*255, 255);
            mTop.setBackgroundColor(Color.TRANSPARENT);
            mBottom.setBackgroundColor(Color.argb(scaleFactor, 255, 0, 0));
        } else {
            scaleFactor = (int)Math.min(Math.abs(y)*255, 255);
            mTop.setBackgroundColor(Color.argb(scaleFactor, 255, 0, 0));
            mBottom.setBackgroundColor(Color.TRANSPARENT);
        }
        valueView.setText(String.format("X: %1$1.2f, Y: %2$1.2f, Z: %3$1.2f",
                values[0], values[1], values[2]));
    }
}

Using SensorManager to calculate acceleration and check if it is still

 
//package com.hairy.nipples.util;

import android.hardware.SensorManager;

class AccelerationUtil {
  public static double calculateAcceleration(float[] values) {
    double acceleration = Math.sqrt(Math.pow(values[0], 2)
        + Math.pow(values[1], 2) + Math.pow(values[2], 2));
    return acceleration;
  }
  
  public static boolean isStandingStill(float[] accelerationValues) {
    double acceleration = calculateAcceleration(accelerationValues);

    // If acceleration doesn't differ from earth's gravity more than 10%, then
    // it's safe to assume that phone is standing still
    if (acceleration > SensorManager.GRAVITY_EARTH * 0.9
        && acceleration < SensorManager.GRAVITY_EARTH * 1.1) {
      return true;
    }
    return false;
  }
}
USB device that supports the adb protocol
package com.android.adb;

import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
import android.util.SparseArray;

import java.util.LinkedList;

/* This class represents a USB device that supports the adb protocol. */
public class AdbDevice {

    private final AdbTestActivity mActivity;
    private final UsbDeviceConnection mDeviceConnection;
    private final UsbEndpoint mEndpointOut;
    private final UsbEndpoint mEndpointIn;

    private String mSerial;

    // pool of requests for the OUT endpoint
    private final LinkedList<UsbRequest> mOutRequestPool = new LinkedList<UsbRequest>();
    // pool of requests for the IN endpoint
    private final LinkedList<UsbRequest> mInRequestPool = new LinkedList<UsbRequest>();
    // list of currently opened sockets
    private final SparseArray<AdbSocket> mSockets = new SparseArray<AdbSocket>();
    private int mNextSocketId = 1;

    private final WaiterThread mWaiterThread = new WaiterThread();

    public AdbDevice(AdbTestActivity activity, UsbDeviceConnection connection,
            UsbInterface intf) {
        mActivity = activity;
        mDeviceConnection = connection;
        mSerial = connection.getSerial();

        UsbEndpoint epOut = null;
        UsbEndpoint epIn = null;
        // look for our bulk endpoints
        for (int i = 0; i < intf.getEndpointCount(); i++) {
            UsbEndpoint ep = intf.getEndpoint(i);
            if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                    epOut = ep;
                } else {
                    epIn = ep;
                }
            }
        }
        if (epOut == null || epIn == null) {
            throw new IllegalArgumentException("not all endpoints found");
        }
        mEndpointOut = epOut;
        mEndpointIn = epIn;
    }

    // return device serial number
    public String getSerial() {
        return mSerial;
    }

    // get an OUT request from our pool
    public UsbRequest getOutRequest() {
        synchronized(mOutRequestPool) {
            if (mOutRequestPool.isEmpty()) {
                UsbRequest request = new UsbRequest();
                request.initialize(mDeviceConnection, mEndpointOut);
                return request;
            } else {
                return mOutRequestPool.removeFirst();
            }
        }
    }

    // return an OUT request to the pool
    public void releaseOutRequest(UsbRequest request) {
        synchronized (mOutRequestPool) {
            mOutRequestPool.add(request);
        }
    }

    // get an IN request from the pool
    public UsbRequest getInRequest() {
        synchronized(mInRequestPool) {
            if (mInRequestPool.isEmpty()) {
                UsbRequest request = new UsbRequest();
                request.initialize(mDeviceConnection, mEndpointIn);
                return request;
            } else {
                return mInRequestPool.removeFirst();
            }
        }
    }

    public void start() {
        mWaiterThread.start();
        connect();
    }

    public AdbSocket openSocket(String destination) {
        AdbSocket socket;
        synchronized (mSockets) {
            int id = mNextSocketId++;
            socket = new AdbSocket(this, id);
            mSockets.put(id, socket);
        }
        if (socket.open(destination)) {
            return socket;
        } else {
            return null;
        }
    }

    private AdbSocket getSocket(int id) {
        synchronized (mSockets) {
            return mSockets.get(id);
        }
    }

    public void socketClosed(AdbSocket socket) {
        synchronized (mSockets) {
            mSockets.remove(socket.getId());
        }
    }

    // send a connect command
    private void connect() {
        AdbMessage message = new AdbMessage();
        message.set(AdbMessage.A_CNXN, AdbMessage.A_VERSION, AdbMessage.MAX_PAYLOAD, "host::\0");
        message.write(this);
    }

    // handle connect response
    private void handleConnect(AdbMessage message) {
        if (message.getDataString().startsWith("device:")) {
            log("connected");
            mActivity.deviceOnline(this);
        }
    }

    public void stop() {
        synchronized (mWaiterThread) {
            mWaiterThread.mStop = true;
        }
    }

    // dispatch a message from the device
    void dispatchMessage(AdbMessage message) {
        int command = message.getCommand();
        switch (command) {
            case AdbMessage.A_SYNC:
                log("got A_SYNC");
                break;
            case AdbMessage.A_CNXN:
                handleConnect(message);
                break;
            case AdbMessage.A_OPEN:
            case AdbMessage.A_OKAY:
            case AdbMessage.A_CLSE:
            case AdbMessage.A_WRTE:
                AdbSocket socket = getSocket(message.getArg1());
                if (socket == null) {
                    log("ERROR socket not found");
                } else {
                    socket.handleMessage(message);
                }
                break;
        }
    }

    void log(String s) {
        mActivity.log(s);
    }


    private class WaiterThread extends Thread {
        public boolean mStop;

        public void run() {
            // start out with a command read
            AdbMessage currentCommand = new AdbMessage();
            AdbMessage currentData = null;
            // FIXME error checking
            currentCommand.readCommand(getInRequest());

            while (true) {
                synchronized (this) {
                    if (mStop) {
                        return;
                    }
                }
                UsbRequest request = mDeviceConnection.requestWait();
                if (request == null) {
                    break;
                }

                AdbMessage message = (AdbMessage)request.getClientData();
                request.setClientData(null);
                AdbMessage messageToDispatch = null;

                if (message == currentCommand) {
                    int dataLength = message.getDataLength();
                    // read data if length > 0
                    if (dataLength > 0) {
                        message.readData(getInRequest(), dataLength);
                        currentData = message;
                    } else {
                        messageToDispatch = message;
                    }
                    currentCommand = null;
                } else if (message == currentData) {
                    messageToDispatch = message;
                    currentData = null;
                }

                if (messageToDispatch != null) {
                    // queue another read first
                    currentCommand = new AdbMessage();
                    currentCommand.readCommand(getInRequest());

                    // then dispatch the current message
                    dispatchMessage(messageToDispatch);
                }

                // put request back into the appropriate pool
                if (request.getEndpoint() == mEndpointOut) {
                    releaseOutRequest(request);
                } else {
                    synchronized (mInRequestPool) {
                        mInRequestPool.add(request);
                    }
                }
            }
        }
    }
}



//src\com\android\adb\AdbMessage.java


package com.android.adb;

import android.hardware.usb.UsbRequest;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/* This class encapsulates and adb command packet */
public class AdbMessage {

    // command names
    public static final int A_SYNC = 0x434e5953;
    public static final int A_CNXN = 0x4e584e43;
    public static final int A_OPEN = 0x4e45504f;
    public static final int A_OKAY = 0x59414b4f;
    public static final int A_CLSE = 0x45534c43;
    public static final int A_WRTE = 0x45545257;

    // ADB protocol version
    public static final int A_VERSION = 0x01000000;

    public static final int MAX_PAYLOAD = 4096;

    private final ByteBuffer mMessageBuffer;
    private final ByteBuffer mDataBuffer;

    public AdbMessage() {
        mMessageBuffer = ByteBuffer.allocate(24);
        mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD);
        mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN);
        mDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
    }

    // sets the fields in the command header
    public void set(int command, int arg0, int arg1, byte[] data) {
        mMessageBuffer.putInt(0, command);
        mMessageBuffer.putInt(4, arg0);
        mMessageBuffer.putInt(8, arg1);
        mMessageBuffer.putInt(12, (data == null ? 0 : data.length));
        mMessageBuffer.putInt(16, (data == null ? 0 : checksum(data)));
        mMessageBuffer.putInt(20, command ^ 0xFFFFFFFF);
        if (data != null) {
            mDataBuffer.put(data, 0, data.length);
        }
    }

    public void set(int command, int arg0, int arg1) {
        set(command, arg0, arg1, (byte[])null);
    }
    public void set(int command, int arg0, int arg1, String data) {
        // add trailing zero
        data += "\0";
        set(command, arg0, arg1, data.getBytes());
    }

    // returns the command's message ID
    public int getCommand() {
        return mMessageBuffer.getInt(0);
    }

    // returns command's first argument
    public int getArg0() {
        return mMessageBuffer.getInt(4);
    }

    // returns command's second argument
    public int getArg1() {
        return mMessageBuffer.getInt(8);
    }

    // returns command's data buffer
    public ByteBuffer getData() {
        return mDataBuffer;
    }

    // returns command's data length
    public int getDataLength() {
        return mMessageBuffer.getInt(12);
    }

    // returns command's data as a string
    public String getDataString() {
        int length = getDataLength();
        if (length == 0) return null;
        // trim trailing zero
        return new String(mDataBuffer.array(), 0, length - 1);
    }


    public boolean write(AdbDevice device) {
        synchronized (device) {
            UsbRequest request = device.getOutRequest();
            request.setClientData(this);
            if (request.queue(mMessageBuffer, 24)) {
                int length = getDataLength();
                if (length > 0) {
                    request = device.getOutRequest();
                    request.setClientData(this);
                    if (request.queue(mDataBuffer, length)) {
                        return true;
                    } else {
                        device.releaseOutRequest(request);
                        return false;
                    }
                }
                return true;
            } else {
                device.releaseOutRequest(request);
                return false;
            }
        }
    }

    public boolean readCommand(UsbRequest request) {
        request.setClientData(this);
        return request.queue(mMessageBuffer, 24);
    }

    public boolean readData(UsbRequest request, int length) {
        request.setClientData(this);
        return request.queue(mDataBuffer, length);
    }

    private static String extractString(ByteBuffer buffer, int offset, int length) {
        byte[] bytes = new byte[length];
        for (int i = 0; i < length; i++) {
            bytes[i] = buffer.get(offset++);
        }
        return new String(bytes);
    }

    @Override
    public String toString() {
        String commandName = extractString(mMessageBuffer, 0, 4);
        int dataLength = getDataLength();
        String result = "Adb Message: " + commandName + " arg0: " + getArg0() +
             " arg1: " + getArg1() + " dataLength: " + dataLength;
        if (dataLength > 0) {
            result += (" data: \"" + getDataString() + "\"");
        }
        return result;
    }

    private static int checksum(byte[] data) {
        int result = 0;
        for (int i = 0; i < data.length; i++) {
            int x = data[i];
            // dang, no unsigned ints in java
            if (x < 0) x += 256;
            result += x;
        }
        return result;
    }
}



//src\com\android\adb\AdbSocket.java


package com.android.adb;

/* This class represents an adb socket.  adb supports multiple independent
 * socket connections to a single device.  Typically a socket is created
 * for each adb command that is executed.
 */
public class AdbSocket {

    private final AdbDevice mDevice;
    private final int mId;
    private int mPeerId;

    public AdbSocket(AdbDevice device, int id) {
        mDevice = device;
        mId = id;
    }

    public int getId() {
        return mId;
    }

    public boolean open(String destination) {
        AdbMessage message = new AdbMessage();
        message.set(AdbMessage.A_OPEN, mId, 0, destination);
        if (! message.write(mDevice)) {
            return false;
        }

        synchronized (this) {
            try {
                wait();
            } catch (InterruptedException e) {
                return false;
            }
        }
        return true;
    }

    public void handleMessage(AdbMessage message) {
        switch (message.getCommand()) {
            case AdbMessage.A_OKAY:
                mPeerId = message.getArg0();
                synchronized (this) {
                    notify();
                }
                break;
            case AdbMessage.A_WRTE:
                mDevice.log(message.getDataString());
                sendReady();
                break;
        }
    }

    private void sendReady() {
        AdbMessage message = new AdbMessage();
        message.set(AdbMessage.A_OKAY, mId, mPeerId);
        message.write(mDevice);
    }
}



//src\com\android\adb\AdbTestActivity.java


package com.android.adb;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

/* Main activity for the adb test program */
public class AdbTestActivity extends Activity {

    private static final String TAG = "AdbTestActivity";

    private TextView mLog;
    private UsbManager mManager;
    private UsbDevice mDevice;
    private UsbDeviceConnection mDeviceConnection;
    private UsbInterface mInterface;
    private AdbDevice mAdbDevice;

    private static final int MESSAGE_LOG = 1;
    private static final int MESSAGE_DEVICE_ONLINE = 2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.adb);
        mLog = (TextView)findViewById(R.id.log);

        mManager = (UsbManager)getSystemService(Context.USB_SERVICE);

        // check for existing devices
        for (UsbDevice device :  mManager.getDeviceList().values()) {
            UsbInterface intf = findAdbInterface(device);
            if (setAdbInterface(device, intf)) {
                break;
            }
        }

        // listen for new devices
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mUsbReceiver, filter);
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(mUsbReceiver);
        setAdbInterface(null, null);
        super.onDestroy();
    }

    public void log(String s) {
        Message m = Message.obtain(mHandler, MESSAGE_LOG);
        m.obj = s;
        mHandler.sendMessage(m);
    }

    private void appendLog(String text) {
        Rect r = new Rect();
        mLog.getDrawingRect(r);
        int maxLines = r.height() / mLog.getLineHeight() - 1;
        text = mLog.getText() + "\n" + text;

        // see how many lines we have
        int index = text.lastIndexOf('\n');
        int count = 0;
        while (index > 0 && count <= maxLines) {
            count++;
            index = text.lastIndexOf('\n', index - 1);
        }

        // truncate to maxLines
        if (index > 0) {
            text = text.substring(index + 1);
        }
        mLog.setText(text);
    }

    public void deviceOnline(AdbDevice device) {
        Message m = Message.obtain(mHandler, MESSAGE_DEVICE_ONLINE);
        m.obj = device;
        mHandler.sendMessage(m);
    }

    private void handleDeviceOnline(AdbDevice device) {
        log("device online: " + device.getSerial());
        device.openSocket("shell:exec logcat");
    }

    // Sets the current USB device and interface
    private boolean setAdbInterface(UsbDevice device, UsbInterface intf) {
        if (mDeviceConnection != null) {
            if (mInterface != null) {
                mDeviceConnection.releaseInterface(mInterface);
                mInterface = null;
            }
            mDeviceConnection.close();
            mDevice = null;
            mDeviceConnection = null;
        }

        if (device != null && intf != null) {
            UsbDeviceConnection connection = mManager.openDevice(device);
            if (connection != null) {
                log("open succeeded");
                if (connection.claimInterface(intf, false)) {
                    log("claim interface succeeded");
                    mDevice = device;
                    mDeviceConnection = connection;
                    mInterface = intf;
                    mAdbDevice = new AdbDevice(this, mDeviceConnection, intf);
                    log("call start");
                    mAdbDevice.start();
                    return true;
                } else {
                    log("claim interface failed");
                    connection.close();
                }
            } else {
                log("open failed");
            }
        }

        if (mDeviceConnection == null && mAdbDevice != null) {
            mAdbDevice.stop();
            mAdbDevice = null;
        }
        return false;
    }

    // searches for an adb interface on the given USB device
    static private UsbInterface findAdbInterface(UsbDevice device) {
        Log.d(TAG, "findAdbInterface " + device);
        int count = device.getInterfaceCount();
        for (int i = 0; i < count; i++) {
            UsbInterface intf = device.getInterface(i);
            if (intf.getInterfaceClass() == 255 && intf.getInterfaceSubclass() == 66 &&
                    intf.getInterfaceProtocol() == 1) {
                return intf;
            }
        }
        return null;
    }

    BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                UsbInterface intf = findAdbInterface(device);
                if (intf != null) {
                    log("Found adb interface " + intf);
                    setAdbInterface(device, intf);
                }
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                String deviceName = device.getDeviceName();
                if (mDevice != null && mDevice.equals(deviceName)) {
                    log("adb interface removed");
                    setAdbInterface(null, null);
                }
            }
        }
    };

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_LOG:
                    appendLog((String)msg.obj);
                    break;
                case MESSAGE_DEVICE_ONLINE:
                    handleDeviceOnline((AdbDevice)msg.obj);
                    break;
            }
        }
    };
}


//res\layout\adb.xml
<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView android:id="@+id/log"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="25dp"
        android:textSize="18sp"
        android:textColor="#ffffffff"
        />

</LinearLayout>





//
//res\xml\device_filter.xml
<?xml version="1.0" encoding="utf-8"?>

<resources>
    <usb-device class="255" subclass="66" protocol="1" />
</resources>
Detect USB device
package com.android.missilelauncher;

import java.nio.ByteBuffer;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MissileLauncherActivity extends Activity
        implements View.OnClickListener, Runnable {

    private static final String TAG = "MissileLauncherActivity";

    private Button mFire;
    private UsbManager mUsbManager;
    private UsbDevice mDevice;
    private UsbDeviceConnection mConnection;
    private UsbEndpoint mEndpointIntr;
    private SensorManager mSensorManager;
    private Sensor mGravitySensor;

    // USB control commands
    private static final int COMMAND_UP = 1;
    private static final int COMMAND_DOWN = 2;
    private static final int COMMAND_RIGHT = 4;
    private static final int COMMAND_LEFT = 8;
    private static final int COMMAND_FIRE = 16;
    private static final int COMMAND_STOP = 32;
    private static final int COMMAND_STATUS = 64;

    // constants for accelerometer orientation
    private static final int TILT_LEFT = 1;
    private static final int TILT_RIGHT = 2;
    private static final int TILT_UP = 4;
    private static final int TILT_DOWN = 8;
    private static final double THRESHOLD = 5.0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.launcher);
        mFire = (Button)findViewById(R.id.fire);
        mFire.setOnClickListener(this);

        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);

        mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        mGravitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
    }

    @Override
    public void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(mGravityListener);
    }

    @Override
    public void onResume() {
        super.onResume();
        mSensorManager.registerListener(mGravityListener, mGravitySensor,
                SensorManager.SENSOR_DELAY_NORMAL);

        Intent intent = getIntent();
        Log.d(TAG, "intent: " + intent);
        String action = intent.getAction();

        UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
        if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            setDevice(device);
        } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            if (mDevice != null && mDevice.equals(device)) {
                setDevice(null);
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private void setDevice(UsbDevice device) {
        Log.d(TAG, "setDevice " + device);
        if (device.getInterfaceCount() != 1) {
            Log.e(TAG, "could not find interface");
            return;
        }
        UsbInterface intf = device.getInterface(0);
        // device should have one endpoint
        if (intf.getEndpointCount() != 1) {
            Log.e(TAG, "could not find endpoint");
            return;
        }
        // endpoint should be of type interrupt
        UsbEndpoint ep = intf.getEndpoint(0);
        if (ep.getType() != UsbConstants.USB_ENDPOINT_XFER_INT) {
            Log.e(TAG, "endpoint is not interrupt type");
            return;
        }
        mDevice = device;
        mEndpointIntr = ep;
        if (device != null) {
            UsbDeviceConnection connection = mUsbManager.openDevice(device);
            if (connection != null && connection.claimInterface(intf, true)) {
                Log.d(TAG, "open SUCCESS");
                mConnection = connection;
                Thread thread = new Thread(this);
                thread.start();

            } else {
                Log.d(TAG, "open FAIL");
                mConnection = null;
            }
         }
    }

    private void sendCommand(int control) {
        synchronized (this) {
            if (control != COMMAND_STATUS) {
                Log.d(TAG, "sendMove " + control);
            }
            if (mConnection != null) {
                byte[] message = new byte[1];
                message[0] = (byte)control;
                // Send command via a control request on endpoint zero
                mConnection.controlTransfer(0x21, 0x9, 0x200, 0, message, message.length, 0);
            }
        }
    }

    public void onClick(View v) {
        if (v == mFire) {
            sendCommand(COMMAND_FIRE);
        }
    }

    private int mLastValue = 0;

    SensorEventListener mGravityListener = new SensorEventListener() {
        public void onSensorChanged(SensorEvent event) {

            // compute current tilt
            int value = 0;
            if (event.values[0] < -THRESHOLD) {
                value += TILT_LEFT;
            } else if (event.values[0] > THRESHOLD) {
                value += TILT_RIGHT;
            }
            if (event.values[1] < -THRESHOLD) {
                value += TILT_UP;
            } else if (event.values[1] > THRESHOLD) {
                value += TILT_DOWN;
            }

            if (value != mLastValue) {
                mLastValue = value;
                // send motion command if the tilt changed
                switch (value) {
                    case TILT_LEFT:
                        sendCommand(COMMAND_LEFT);
                        break;
                    case TILT_RIGHT:
                       sendCommand(COMMAND_RIGHT);
                        break;
                    case TILT_UP:
                        sendCommand(COMMAND_UP);
                        break;
                    case TILT_DOWN:
                        sendCommand(COMMAND_DOWN);
                        break;
                    default:
                        sendCommand(COMMAND_STOP);
                        break;
                }
            }
        }

        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // ignore
        }
    };

    @Override
    public void run() {
        ByteBuffer buffer = ByteBuffer.allocate(1);
        UsbRequest request = new UsbRequest();
        request.initialize(mConnection, mEndpointIntr);
        byte status = -1;
        while (true) {
            // queue a request on the interrupt endpoint
            request.queue(buffer, 1);
            // send poll status command
            sendCommand(COMMAND_STATUS);
            // wait for status event
            if (mConnection.requestWait() == request) {
                byte newStatus = buffer.get(0);
                if (newStatus != status) {
                    Log.d(TAG, "got status " + newStatus);
                    status = newStatus;
                    if ((status & COMMAND_FIRE) != 0) {
                        // stop firing
                        sendCommand(COMMAND_STOP);
                    }
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                }
            } else {
                Log.e(TAG, "requestWait failed, exiting");
                break;
            }
        }
    }
}


//
//res\layout\launcher.xml
<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

        <Button android:id="@+id/fire"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="25dp"
            android:layout_marginBottom="25dp"
            android:layout_marginLeft="25dp"
            android:layout_marginRight="25dp"
            android:textSize="36sp"
            android:text="@string/fire">
        </Button>


</LinearLayout>





//
//res\values\strings.xml
<?xml version="1.0" encoding="utf-8"?>


<resources>

    <string name="fire">Fire!</string>

</resources>




//
//res\xml\device_filter.xml

<resources>
    <!-- vendor and product ID for Dream Cheeky USB Missle Launcher -->
    <usb-device vendor-id="2689" product-id="1793" />
    <!-- vendor and product ID for Dream Cheeky Wireless USB Missle Launcher -->
    <usb-device vendor-id="2689" product-id="65281" />
</resources>

Demonstrates android.os.Vibrator android.os.Vibrator class.

package com.example.android.apis.os;

// Need the following import to get access to the app resources, since this
// class is in a sub-package.

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.View;
import android.widget.TextView;
import com.example.android.apis.R;

public class MorseCode extends Activity
{
    /** Our text view */
    private TextView mTextView;

    /**
     * Initialization of the Activity after it is first created.  Must at least
     * call {@link android.app.Activity#setContentView setContentView()} to
     * describe what is to be displayed in the screen.
     */
    @Override
  protected void onCreate(Bundle savedInstanceState)
    {
        // Be sure to call the super class.
        super.onCreate(savedInstanceState);

        // See assets/res/any/layout/hello_world.xml for this
        // view layout definition, which is being set here as
        // the content of our screen.
        setContentView(R.layout.morse_code);

        // Set the OnClickListener for the button so we see when it's pressed.
        findViewById(R.id.button).setOnClickListener(mClickListener);

        // Save the text view so we don't have to look it up each time
        mTextView = (TextView)findViewById(R.id.text);
    }

    /** Called when the button is pushed */
    View.OnClickListener mClickListener = new View.OnClickListener() {
        public void onClick(View v) {
            // Get the text out of the view
            String text = mTextView.getText().toString();

            // convert it using the function defined above.  See the docs for
            // android.os.Vibrator for more info about the format of this array
            long[] pattern = MorseCodeConverter.pattern(text);

            // Start the vibration
            Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
            vibrator.vibrate(pattern, -1);
        }
    };
}

/** Class that implements the text to morse code coversion */
class MorseCodeConverter {
    private static final long SPEED_BASE = 100;
    static final long DOT = SPEED_BASE;
    static final long DASH = SPEED_BASE * 3;
    static final long GAP = SPEED_BASE;
    static final long LETTER_GAP = SPEED_BASE * 3;
    static final long WORD_GAP = SPEED_BASE * 7;

    /** The characters from 'A' to 'Z' */
    private static final long[][] LETTERS = new long[][] {
        /* A */ new long[] { DOT, GAP, DASH },
        /* B */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DOT },
        /* C */ new long[] { DASH, GAP, DOT, GAP, DASH, GAP, DOT },
        /* D */ new long[] { DASH, GAP, DOT, GAP, DOT },
        /* E */ new long[] { DOT },
        /* F */ new long[] { DOT, GAP, DOT, GAP, DASH, GAP, DOT },
        /* G */ new long[] { DASH, GAP, DASH, GAP, DOT },
        /* H */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DOT },
        /* I */ new long[] { DOT, GAP, DOT },
        /* J */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DASH },
        /* K */ new long[] { DASH, GAP, DOT, GAP, DASH },
        /* L */ new long[] { DOT, GAP, DASH, GAP, DOT, GAP, DOT },
        /* M */ new long[] { DASH, GAP, DASH },
        /* N */ new long[] { DASH, GAP, DOT },
        /* O */ new long[] { DASH, GAP, DASH, GAP, DASH },
        /* P */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DOT },
        /* Q */ new long[] { DASH, GAP, DASH, GAP, DOT, GAP, DASH },
        /* R */ new long[] { DOT, GAP, DASH, GAP, DOT },
        /* S */ new long[] { DOT, GAP, DOT, GAP, DOT },
        /* T */ new long[] { DASH },
        /* U */ new long[] { DOT, GAP, DOT, GAP, DASH },
        /* V */ new long[] { DOT, GAP, DOT, GAP, DASH },
        /* W */ new long[] { DOT, GAP, DASH, GAP, DASH },
        /* X */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DASH },
        /* Y */ new long[] { DASH, GAP, DOT, GAP, DASH, GAP, DASH },
        /* Z */ new long[] { DASH, GAP, DASH, GAP, DOT, GAP, DOT },
    };

    /** The characters from '0' to '9' */
    private static final long[][] NUMBERS = new long[][] {
        /* 0 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DASH, GAP, DASH },
        /* 1 */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DASH, GAP, DASH },
        /* 2 */ new long[] { DOT, GAP, DOT, GAP, DASH, GAP, DASH, GAP, DASH },
        /* 3 */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DASH, GAP, DASH },
        /* 4 */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DOT, GAP, DASH },
        /* 5 */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DOT, GAP, DOT },
        /* 6 */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DOT, GAP, DOT },
        /* 7 */ new long[] { DASH, GAP, DASH, GAP, DOT, GAP, DOT, GAP, DOT },
        /* 8 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DOT, GAP, DOT },
        /* 9 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DASH, GAP, DOT },
    };

    private static final long[] ERROR_GAP = new long[] { GAP };

    /** Return the pattern data for a given character */
    static long[] pattern(char c) {
        if (c >= 'A' && c <= 'Z') {
            return LETTERS[c - 'A'];
        }
        if (c >= 'a' && c <= 'z') {
            return LETTERS[c - 'a'];
        }
        else if (c >= '0' && c <= '9') {
            return NUMBERS[c - '0'];
        }
        else {
            return ERROR_GAP;
        }
    }

    static long[] pattern(String str) {
        boolean lastWasWhitespace;
        int strlen = str.length();

        // Calculate how long our array needs to be.
        int len = 1;
        lastWasWhitespace = true;
        for (int i=0; i<strlen; i++) {
            char c = str.charAt(i);
            if (Character.isWhitespace(c)) {
                if (!lastWasWhitespace) {
                    len++;
                    lastWasWhitespace = true;
                }
            } else {
                if (!lastWasWhitespace) {
                    len++;
                }
                lastWasWhitespace = false;
                len += pattern(c).length;
            }
        }

        // Generate the pattern array.  Note that we put an extra element of 0
        // in at the beginning, because the pattern always starts with the pause,
        // not with the vibration.
        long[] result = new long[len+1];
        result[0] = 0;
        int pos = 1;
        lastWasWhitespace = true;
        for (int i=0; i<strlen; i++) {
            char c = str.charAt(i);
            if (Character.isWhitespace(c)) {
                if (!lastWasWhitespace) {
                    result[pos] = WORD_GAP;
                    pos++;
                    lastWasWhitespace = true;
                }
            } else {
                if (!lastWasWhitespace) {
                    result[pos] = LETTER_GAP;
                    pos++;
                }
                lastWasWhitespace = false;
                long[] letter = pattern(c);
                System.arraycopy(letter, 0, result, pos, letter.length);
                pos += letter.length;
            }
        }
        return result;
    }
}
//main.xml

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <EditText
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="4dip"
        />
    
    <Button
        android:id="@+id/button"
        android:text="vibrate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

Using Vibrator

  
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Vibrator;

 class Utils {

  public static SharedPreferences preferencias;
  public static Vibrator v;
  public static final int CORTO = 50;
  public static final int LARGO = 500;
  
  
  static public void vibrar(Context ctx, int t){
    //boolean activo = Utils.p.getBoolean("cbVibrar", true);
    if(!preferencias.getBoolean("cbVibrar", true)) return;
    v = (Vibrator) ctx.getSystemService(Context.VIBRATOR_SERVICE);
    v.vibrate(t);
  }

  
}