I am following this GitHub project https://github.com/kernl/PC-to-Android-Bluetooth-Example
PC is working as a client while android app as a server.Server searches for the devices and send a string to the device named BT_ .While android device listens for the connection and receive the string.
The problem is its not consistent..Sometimes it sends the string correctly but sometimes PC client code keeps running but can't send the string.most of the times it can't call "broadcastCommand" function.It stucks here.
It always work fine for the first time.But it does not work again and after some time it starts working again.When I close the android app and open it again every time,it receives properly.
Please helppppp !
PC client code is:
public class BT_Dummy extends Thread implements DiscoveryListener {
/**
* Service serial-port UUID
*/
protected UUID defaultUUID = new UUID(0x1101);
/**
* Local bluetooth device.
*/
private LocalDevice local;
/**
* Agent responsible for the discovery of bluetooth devices.
*/
private DiscoveryAgent agent;
/**
* Output stream used to send information to the bluetooth.
*/
private DataOutputStream dout;
/**
* Bluetooth Connection.
*/
private StreamConnection conn;
/**
* List of bluetooth devices of interest. (name starting with the defined token)
*/
private Vector<RemoteDevice> devices;
/**
* Services of interest (defined in UUID) of each device.
*/
private Vector<ServiceRecord> services;
public BT_Dummy() {
services = new Vector<ServiceRecord>();
}
#Override
public void run() {
findDevices();
}
/**
* Find all the discoverable devices in range.
*/
protected void findDevices(){
try{
devices = new Vector<RemoteDevice>();
LocalDevice local = LocalDevice.getLocalDevice();
DiscoveryAgent agent = local.getDiscoveryAgent();
agent.startInquiry(DiscoveryAgent.GIAC, this);
debugString("Starting device discovery...");
}catch(Exception e) {
debugString("Error initiating discovery.");
}
}
/**
* Obtains a list of services with the UUID defined from a device.
*
* #param device
* Device to obtain the service list.
*/
protected void findServices(RemoteDevice device){
try{
UUID[] uuids = new UUID[1];
uuids[0] = defaultUUID; //The UUID of the each service
local = LocalDevice.getLocalDevice();
agent = local.getDiscoveryAgent();
agent.searchServices(null, uuids, device, this);
debugString("Starting Service Discovery...");
}catch(Exception e){
debugString("Error finding services.");
}
}
/**
* Sends a message to all the devices. (using the service)
*
* #param str
* Byte array which represents a string.
*/
public void broadcastCommand(String str) {
for(ServiceRecord sr : services) {
String url = sr.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
conn = null;
try {
debugString("Sending command to " + url);
conn = (StreamConnection) Connector.open(url);
dout = new DataOutputStream(conn.openOutputStream());
dout.writeUTF(str);
debugString(String.format("Sending %s", str));
dout.flush();
dout.close();
conn.close();
debugString("Sent. Connection Closed.");
} catch (Exception e) {
debugString("Failed to connect to " + url);
e.printStackTrace();
}
}
}
#Override
public void deviceDiscovered(RemoteDevice arg0, DeviceClass arg1) {
try {
String name = arg0.getFriendlyName(true);
debugString("Found device: " + name);
if(name.startsWith("BT_")) {
devices.add(arg0);
}
} catch (IOException e) {
debugString("Failed to get remoteDevice Name.");
}
}
#Override
public void inquiryCompleted(int arg0) {
debugString("Inquiry Completed.");
// Start service probing
for(RemoteDevice d :devices) {
findServices(d);
}
}
#Override
public void serviceSearchCompleted(int arg0, int arg1) {
debugString("Service search completed.");
broadcastCommand(new String("Hello world!"));
}
#Override
public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {
for(ServiceRecord x : arg1) {
services.add(x);
}
}
/**
* Helper to format a debug string for output.
*
* #param str
* Debug Message
*/
protected static void debugString(String str) {
System.out.println(String.format("%s :: %s", BT_Dummy.class.getName(), str));
}
}
Android code is:
public class BT_Example extends Activity implements OnClickListener {
/**
* Default Serial-Port UUID
*/
private String defaultUUID = "00001101-0000-1000-8000-00805F9B34FB";
/**
* Default bluetooth adapter on the device.
*/
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
/**
* String used to identify this application in the log.
*/
private final String TAG = BT_Example.class.getName();
/**
* The prefix to identify devices of interest.
*/
private final static String PREFIX = "BT_";
/**
* The Server thread.
*/
private AcceptThread server;
/**
* Magic number used in the bluetooth enabling request.
*/
private final int REQ = 111;
private NotificationCenter mNotificationCenter;
private static final String MESSAGE_RECEIVED_INTENT = "com.almightybuserror.intent.MESSAGE_RECEIVED";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mNotificationCenter = new NotificationCenter();
if(mBluetoothAdapter == null) {
Log.e(TAG, "No Bluetooth Adapter available. Exiting...");
this.finish();
}
this.registerReceiver(mNotificationCenter, new IntentFilter(MESSAGE_RECEIVED_INTENT));
setHandlers();
}
#Override
public void onBackPressed() {
onPause();
}
#Override
public void onPause() {
server.cancel();
restoreBTDeviceName();
super.onPause();
}
#Override
public void onClick(View v) {
Button btn = (Button) v;
if(btn.getId() == R.id.btn_start_server) {
if(!mBluetoothAdapter.getName().startsWith(PREFIX))
mBluetoothAdapter.setName(PREFIX + mBluetoothAdapter.getName());
if(mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)
requestBTDiscoverable();
server = new AcceptThread();
server.start();
btn.setEnabled(false);
((Button) this.findViewById(R.id.btn_stop_server)).setEnabled(true);
} else if(btn.getId() == R.id.btn_stop_server) {
server.cancel();
btn.setEnabled(false);
((Button) this.findViewById(R.id.btn_start_server)).setEnabled(true);
restoreBTDeviceName();
}
}
/**
* Launches Discoverable Bluetooth Intent.
*/
public void requestBTDiscoverable() {
Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(i, REQ);
int result = 0;
this.onActivityResult(REQ, result, i);
Log.i(TAG, "Bluetooth discoverability enabled");
}
/**
* Obtains the Vibrator service.
* #return
* Vibrator Object.
*/
private Vibrator getVibrator() {
return (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
/**
* Removes the prefix from the device name if the prefix is present.
*/
private void restoreBTDeviceName() {
if(mBluetoothAdapter.getName().startsWith(PREFIX))
mBluetoothAdapter.setName(mBluetoothAdapter.getName().substring(PREFIX.length()));
}
/**
* Sets the interface button handlers.
*/
public void setHandlers() {
Button start_server = (Button) this.findViewById(R.id.btn_start_server);
start_server.setOnClickListener(this);
Button stop_server = (Button) this.findViewById(R.id.btn_stop_server);
stop_server.setOnClickListener(this);
}
/**
* Shows a information dialog.
* #param message
* String resource used to define the message.
* #param duration
* Dialog's TTL.
*/
private void showInformation(String message, long duration) {
final Dialog mDialog = new Dialog(this);
TextView txt = new TextView(this);
txt.setText(message);
mDialog.setContentView(txt);
mDialog.setTitle("Information");
mDialog.show();
(new Handler()).postDelayed(new Runnable() {
public void run() {
mDialog.dismiss();
}}, duration); // Close dialog after delay
}
/**
* Thread that handles an incoming connection.
* Adapted from http://developer.android.com/guide/topics/wireless/bluetooth.html
*/
class AcceptThread extends Thread {
/**
* Tag that will appear in the log.
*/
private final String ACCEPT_TAG = AcceptThread.class.getName();
/**
* The bluetooth server socket.
*/
private final BluetoothServerSocket mServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(ACCEPT_TAG,
UUID.fromString(defaultUUID));
} catch (IOException e) {
e.printStackTrace();
}
mServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
while (true) {
try {
Log.i(ACCEPT_TAG, "Listening for a connection...");
socket = mServerSocket.accept();
Log.i(ACCEPT_TAG, "Connected to " + socket.getRemoteDevice().getName());
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
try {
// Read the incoming string.
String buffer;
DataInputStream in = new DataInputStream(socket.getInputStream());
buffer = in.readUTF();
Intent i = new Intent(MESSAGE_RECEIVED_INTENT);
i.putExtra("Message", String.format("%sn From: %s", buffer, socket.getRemoteDevice().getName()));
getBaseContext().sendBroadcast(i);
} catch (IOException e) {
Log.e(ACCEPT_TAG, "Error obtaining InputStream from socket");
e.printStackTrace();
}
try {
mServerSocket.close();
} catch (IOException e) { }
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mServerSocket.close();
} catch (IOException e) { }
}
}
class NotificationCenter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(MESSAGE_RECEIVED_INTENT)) {
showInformation(intent.getExtras().getString("Message"), 5000);
getVibrator().vibrate(500);
}
}
}
}
I've accomplished this using the android source example:
https://android.googlesource.com/platform/development/+/master/samples/BluetoothChat/
For the PC code I used a simple python server:
#!/usr/bin/python
from bluetooth import *
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",6))
#server_sock.bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "8ce255c0-200a-11e0-ac64-0800200c9a66" #Insecure
#uuid = "fa87c0d0-afac-11de-8a39-0800200c9a66"
advertise_service( server_sock, "BluetoothChatInsecure",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ],
# protocols = [ OBEX_UUID ]
)
print "Waiting for connection on RFCOMM channel %d" % port
client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info
try:
while True:
data = client_sock.recv(1024)
if len(data) == 0: break
print "received [%s]" % data
except IOError:
pass
print "disconnected"
client_sock.close()
server_sock.close()
print "all done"
Ensure that the UUID inside your android app matches the one inside your PC server.
RFCOMM isn't the newest way to exchange data, GATT is a more advanced system which is also supported by iOS. RFCOMM on the other hand is easier to get started, its supported by Android, Windows, and BlueZ stacks.
Related
I make a POS in android. I want to make a printing in my apps. To do printing I'm using bluetooth printer. Then, I had success make the bluetooth connection and I make it in one fragment. But every time I move to another fragment the bluetooth connction will be disconnected. How can I prevent bluetooth disconnect when moving fragment?
SettingFragment.Java
/**
* A simple {#link Fragment} subclass.
*/
public class SettingFragment extends Fragment {
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;
public static final int MESSAGE_CONNECTION_LOST = 6;
public static final int MESSAGE_UNABLE_CONNECT = 7;
private String mConnectedDeviceName = null;
// Key names received from the BluetoothService 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 = 1;
private static final int REQUEST_ENABLE_BT = 2;
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothService mService = null;
private static final String CHINESE = "GBK";
SessionManagement sessionManagement;
DatabaseHandler db;
TextView tvConnected;
Button btnScan;
Button btnTest;
public SettingFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootview = inflater.inflate(R.layout.fragment_setting, container, false);
getActivity().setTitle("Setting");
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
btnScan = (Button)rootview.findViewById(R.id.btnScan);
btnTest = (Button) rootview.findViewById(R.id.btnTest);
tvConnected = (TextView) rootview.findViewById(R.id.tvPrinterConnect);
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the session
} else {
if (mService == null)
KeyListenerInit();
}
return rootview;
}
#SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if (DEBUG)
Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothService.STATE_CONNECTED:
//btnScan.setText(getText(R.string.Connecting));
btnScan.setEnabled(false);
break;
case BluetoothService.STATE_CONNECTING:
Toast.makeText((MainActivity)getContext(),R.string.title_connecting,Toast.LENGTH_SHORT).show();
break;
case BluetoothService.STATE_LISTEN:
case BluetoothService.STATE_NONE:
Toast.makeText((MainActivity)getContext(),R.string.title_not_connected,Toast.LENGTH_SHORT).show();
break;
}
break;
case MESSAGE_WRITE:
break;
case MESSAGE_READ:
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(getActivity(),
"Connected to " + mConnectedDeviceName,
Toast.LENGTH_SHORT).show();
tvConnected.setText("Connected to "+mConnectedDeviceName );
break;
case MESSAGE_TOAST:
Toast.makeText(getActivity(),
msg.getData().getString(TOAST), Toast.LENGTH_SHORT)
.show();
break;
case MESSAGE_CONNECTION_LOST:
Toast.makeText(getActivity(), "Device connection was lost",
Toast.LENGTH_SHORT).show();
tvConnected.setText("Not Connect to Any Device");
// editText.setEnabled(false);
// sendButton.setEnabled(false);
break;
case MESSAGE_UNABLE_CONNECT:
Toast.makeText(getActivity(), "Unable to connect device",
Toast.LENGTH_SHORT).show();
break;
}
}
};
#Override
public void onStart() {
super.onStart();
// If Bluetooth 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 session
} else {
if (mService == null)
KeyListenerInit();
}
}
#Override
public synchronized void onResume() {
super.onResume();
if (mService != null) {
if (mService.getState() == BluetoothService.STATE_NONE) {
// Start the Bluetooth services
mService.start();
}
}
}
#Override
public synchronized void onPause() {
super.onPause();
if (DEBUG)
Log.e(TAG, "- ON PAUSE -");
}
#Override
public void onStop() {
super.onStop();
if (DEBUG)
Log.e(TAG, "-- ON STOP --");
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Bluetooth services
if (mService != null)
mService.stop();
if (DEBUG)
Log.e(TAG, "--- ON DESTROY ---");
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (DEBUG)
Log.d(TAG, "onActivityResult " + resultCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:{
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Get the device MAC address
String address = data.getExtras().getString(
DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BLuetoothDevice object
if (BluetoothAdapter.checkBluetoothAddress(address)) {
BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
// Attempt to connect to the device
mService.connect(device);
}
}
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 session
KeyListenerInit();
} else {
// User did not enable Bluetooth or an error occured
Log.d(TAG, "BT not enabled");
Toast.makeText(getActivity(), R.string.bt_not_enabled_leaving,
Toast.LENGTH_SHORT).show();
getActivity().onBackPressed();
}
break;
}
}
}
private void KeyListenerInit() {
btnScan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
});
mService = new BluetoothService(getActivity(), mHandler);
}
}
BluetoothService.JAVA
public class BluetoothService {
// Debugging
private static final String TAG = "BluetoothService";
private static final boolean DEBUG = true;
// Name for the SDP record when creating server socket
private static final String NAME = "ZJPrinter";
//UUID must be this
// Unique UUID for this application
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private BluetoothAdapter mAdapter;
private Handler mHandler;
private AcceptThread mAcceptThread;
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
public static String ErrorMessage = "No_Error_Message";
/**
* Constructor. Prepares a new BTPrinter session.
* #param context The UI Activity Context
* #param handler A Handler to send messages back to the UI Activity
*/
public BluetoothService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}
/**
* Set the current state of the connection
* #param state An integer defining the current connection state
*/
private synchronized void setState(int state) {
if (DEBUG) Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(SettingFragment.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Return the current connection state. */
public synchronized int getState() {
return mState;
}
/**
* Start the service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume() */
public synchronized void start() {
if (DEBUG) 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;}
// Start the thread to listen on a BluetoothServerSocket
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
setState(STATE_LISTEN);
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
* #param device The BluetoothDevice to connect
*/
public synchronized void connect(BluetoothDevice device) {
if (DEBUG) 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);
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) {
if (DEBUG) Log.d(TAG, "connected");
// 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 (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(SettingFragment.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(SettingFragment.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
/**
* Stop all threads
*/
public synchronized void stop() {
if (DEBUG) Log.d(TAG, "stop");
setState(STATE_NONE);
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
}
/**
* 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;
}
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
setState(STATE_LISTEN);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(SettingFragment.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(SettingFragment.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
//setState(STATE_LISTEN);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(SettingFragment.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(SettingFragment.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
/**
* 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;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) {
Log.e(TAG, "listen() failed", e);
}
mmServerSocket = tmp;
}
#Override
public void run() {
if (DEBUG) Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
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, "accept() failed", e);
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
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 (DEBUG) Log.i(TAG, "END mAcceptThread");
}
public void cancel() {
if (DEBUG) Log.d(TAG, "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "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;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG, "create() failed", e);
}
mmSocket = tmp;
}
#Override
public void run() {
Log.i(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
// 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) {
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
// Start the service over to restart listening mode
BluetoothService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect 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) {
Log.d(TAG, "create ConnectedThread");
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;
}
#Override
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
byte[] buffer = new byte[256];
// Read from the InputStream
bytes = mmInStream.read(buffer);
if(bytes>0)
{
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(SettingFragment.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
}
else
{
Log.e(TAG, "disconnected");
connectionLost();
//add by chongqing jinou
if(mState != STATE_NONE)
{
Log.e(TAG, "disconnected");
// Start the service over to restart listening mode
BluetoothService.this.start();
}
break;
}
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
//add by chongqing jinou
if(mState != STATE_NONE)
{
// Start the service over to restart listening mode
BluetoothService.this.start();
}
break;
}
}
}
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mmOutStream.flush();//清空缓存
/* if (buffer.length > 3000) //
{
byte[] readata = new byte[1];
SPPReadTimeout(readata, 1, 5000);
}*/
Log.i("BTPWRITE", new String(buffer,"GBK"));
// Share the sent message back to the UI Activity
mHandler.obtainMessage(SettingFragment.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);
}
}
}
}
I have made an app that should connect to a sensor via WiFi Direct, then connect to port 5001 on the sensor to get the sensor data.
I have used "Simple Socket Tester" to start a server on another phone to see if my app succeeded in connecting to port 5001 on that server. When connected, I can send messages to the server, which is displayed on the other phone. But when I send messages to the client from the other phone, I am not receiving the message in my app.
Why is that? Am I missing something inside my code?
public class TCPClient {
public static final String SERVER_IP = "192.168.1.52"; //your computer IP address
public static final int SERVER_PORT = 5001;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TCPClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(String message) {
if (mBufferOut != null && !mBufferOut.checkError()) {
mBufferOut.println(message);
mBufferOut.flush();
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
// send mesage that we are closing the connection
/*sendMessage(Constants.CLOSED_CONNECTION+"Kazy");*/
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// send login name
sendMessage("hi");
//in this while the client listens for the messages sent by the server
while (mRun) {
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
The class where my ConnectTask class is.
public class DeviceDetailFragment extends Fragment implements ConnectionInfoListener {
protected static final int CHOOSE_FILE_RESULT_CODE = 20;
private View mContentView = null;
private WifiP2pDevice device;
private WifiP2pInfo info;
ProgressDialog progressDialog = null;
TCPClient mTCPClient;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mContentView = inflater.inflate(R.layout.device_detail, null);
mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
"Connecting to :" + device.deviceAddress, true, true
// new DialogInterface.OnCancelListener() {
//
// #Override
// public void onCancel(DialogInterface dialog) {
// ((DeviceActionListener)
getActivity()).cancelDisconnect();
// }
// }
);
((DeviceListFragment.DeviceActionListener) getActivity()).connect(config);
}
});
mContentView.findViewById(R.id.btn_disconnect).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
((DeviceListFragment.DeviceActionListener) getActivity()).disconnect();
}
});
/*
mContentView.findViewById(R.id.btn_start_client).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// Allow user to pick an image from Gallery or other
// registered apps
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
}
});
*/
return mContentView;
}
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
this.info = info;
this.getView().setVisibility(View.VISIBLE);
// The owner IP is now known.
TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
view.setText(getResources().getString(R.string.group_owner_text)
+ ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
: getResources().getString(R.string.no)));
// InetAddress from WifiP2pInfo struct.
view = (TextView) mContentView.findViewById(R.id.device_info);
view.setText("Group Owner IP - " + info.groupOwnerAddress.getHostAddress());
if(info.groupFormed) {
new ConnectTask().execute("");
if (mTCPClient != null) {
mTCPClient.sendMessage("testing");
}
//sends the message to the server
}
// After the group negotiation, we assign the group owner as the file
// server. The file server is single threaded, single connection server
// socket.
/*
if (info.groupFormed && info.isGroupOwner) {
new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
.execute();
}
*/
// hide the connect button
mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
}
/**
* Updates the UI with device data
*
* #param device the device to be displayed
*/
public void showDetails(WifiP2pDevice device) {
this.device = device;
this.getView().setVisibility(View.VISIBLE);
TextView view = (TextView) mContentView.findViewById(R.id.device_address);
view.setText(device.deviceAddress);
view = (TextView) mContentView.findViewById(R.id.device_info);
view.setText(device.toString());
}
/**
* Clears the UI fields after a disconnect or direct mode disable operation.
*/
public void resetViews() {
mContentView.findViewById(R.id.btn_connect).setVisibility(View.VISIBLE);
TextView view = (TextView) mContentView.findViewById(R.id.device_address);
view.setText(R.string.empty);
view = (TextView) mContentView.findViewById(R.id.device_info);
view.setText(R.string.empty);
view = (TextView) mContentView.findViewById(R.id.group_owner);
view.setText(R.string.empty);
/*
view = (TextView) mContentView.findViewById(R.id.status_text);
view.setText(R.string.empty);
this.getView().setVisibility(View.GONE);
*/
}
public class ConnectTask extends AsyncTask<String, String, TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
//we create a TCPClient object
mTCPClient = new TCPClient(new TCPClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTCPClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//response received from server
Log.d("test", "response " + values[0]);
//process server response here....
}
}
}
I want to receive a String from the Bluetooth server which is pc I have a java code for it but when ever I run my Android client Activity it shows me this exception
Activity com.waseem.mobileclient.bluetoot_app.MainActivity has leaked IntentReceiver com.waseem.mobileclient.bluetoot_app.MainActivity$1#410480f0 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.waseem.mobileclient.bluetoot_app.MainActivity has leaked IntentReceiver com.waseem.mobileclient.bluetoot_app.MainActivity$1#410480f0 that was originally registered here. Are you missing a call to unregisterReceiver()?
at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:792)
at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1111)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1098)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1092)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:365)
at com.waseem.mobileclient.bluetoot_app.MainActivity.onCreate(MainActivity.java:68)
at android.app.Activity.performCreate(Activity.java:5008)
I am unregistering in onPause() why I am getting this exception please help me out It has stuck me for a long time.
here is the client code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (myBluetoothAdapter == null) {
Log.e(TAG, "No Bluetooth Adapter available. Exiting...");
this.finish();
}
IntentFilter intent_filter=new IntentFilter(MESSAGE_RECEIVED_INTENT);
broad_receiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MESSAGE_RECEIVED_INTENT)) {
showInformation(intent.getExtras().getString("Message"), 5000);
getVibrator().vibrate(500);
}
else {
showInformation("Message unable to receive", 5000);
getVibrator().vibrate(500);
}
}
};
this.registerReceiver(broad_receiver,intent_filter);
Button start_server = (Button)findViewById(R.id.button_start);
start_server.setOnClickListener(this);
Button stop_server = (Button)findViewById(R.id.button_stop);
stop_server.setOnClickListener(this);
}
#Override
protected void onPause() {
this.unregisterReceiver(this.broad_receiver);
super.onPause();
server.cancel();
restoreBTDeviceName();
}
#Override
public void onClick(View v) {
Button btn = (Button) v;
if (btn.getId() == R.id.button_start) {
if (!myBluetoothAdapter.getName().startsWith(PREFIX))
myBluetoothAdapter.setName(PREFIX );
if (myBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
requestBTDiscoverable();
server = new AcceptThread();
server.start();
btn.setEnabled(false);
((Button) this.findViewById(R.id.button_stop)).setEnabled(true);
}
} else if (btn.getId() == R.id.button_stop) {
server.cancel();
btn.setEnabled(false);
((Button) this.findViewById(R.id.button_start)).setEnabled(true);
restoreBTDeviceName();
}
}
/**
* Launches Discoverable Bluetooth Intent.
*/
public void requestBTDiscoverable() {
Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(i, REQUEST);
int result = 0;
this.onActivityResult(REQUEST, result, i);
Log.i(TAG, "Bluetooth discoverability enabled");
}
/**
* Obtains the Vibrator service.
*
* #return Vibrator Object.
*/
private Vibrator getVibrator() {
return (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
/**
* Removes the prefix from the device name if the prefix is present.
*/
private void restoreBTDeviceName() {
if (myBluetoothAdapter.getName().startsWith(PREFIX))
myBluetoothAdapter.setName(myBluetoothAdapter.getName().substring(PREFIX.length()));
}
/**
* Shows a information dialog.
*
* #param message String resource used to define the message.
* #param duration Dialog's TTL.
*/
private void showInformation(String message, long duration) {
final Dialog mDialog = new Dialog(this);
TextView txt = new TextView(this);
txt.setText(message);
mDialog.setContentView(txt);
mDialog.setTitle("Information");
mDialog.show();
(new Handler()).postDelayed(new Runnable() {
public void run() {
mDialog.dismiss();
}
},duration); // Close dialog after delay
}
/**
* ************************************* AcceptThread *************************************
*/
class AcceptThread extends Thread {
/**
* Tag that will appear in the log.
*/
private final String ACCEPT_TAG = AcceptThread.class.getName();
/**
* The bluetooth server socket.
*/
private final BluetoothServerSocket mServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = myBluetoothAdapter.listenUsingRfcommWithServiceRecord(ACCEPT_TAG, UUID.fromString(defaultUUID));
} catch (IOException e) {
e.printStackTrace();
}
mServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
while (true) {
try {
Log.i(ACCEPT_TAG, "Listening for a connection...");
socket = mServerSocket.accept();
Log.i(ACCEPT_TAG, "Connected to " + socket.getRemoteDevice().getName());
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
try {
// Read the incoming string.
String buffer;
DataInputStream in = new DataInputStream(socket.getInputStream());
buffer = in.readUTF();
Intent i = new Intent(MESSAGE_RECEIVED_INTENT);
i.putExtra("Message", String.format("%sn From: %s", buffer, socket.getRemoteDevice().getName()));
getBaseContext().sendBroadcast(i);
} catch (IOException e) {
Log.e(ACCEPT_TAG, "Error obtaining InputStream from socket");
e.printStackTrace();
}
try {
mServerSocket.close();
} catch (IOException e) {
}
break;
}
}
}
/**
* Will cancel the listening socket, and cause the thread to finish
*/
public void cancel() {
try {
mServerSocket.close();
} catch (IOException e) {
}
}
}
The first line of LogCat says:
Are you missing a call to unregisterReceiver()?
It simply means that you need to check the API documentation of BroadcastReceiver for help, which says:
Note: If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.
I am working on a project which makes use of an android tablet(iball 3G 7271) that runs on 4.1.2 and is made of MTK processor AND an RN42 bluetooth (chip on a PCB).These two modules communicate with each other to transfer data among them via bluetooth.
I am facing issues.wherein at certain instances I repeatedly get exceptions stating 'Connection is not created (failed or aborted)'.I have found the instances as described below:
I copied the relevant code from the BlueTerm app(from playstore) and made a sample app to test BT connectivity.Blueterm is an app to test bluetooth connectivity between a device and RN42.
1) I Connected/disconnected the app to RN42,and found that it was working all the time.Proper connection and disconnection was happening.
2) I Simulated power failure(by switching off just the RN42 module),I then disconnected & reconnected the BT connection between app and RN42 & found that the tablet was getting re-connected with RN42 without much issue.
3) Link between re-installation of the app and BT connectivity to the RN42
Test case 1:Before re-installation, the app was disconnected from RN42 ; result- after re-installation BT reconnection to RN42 in the re installed app works fine.
Test case 2:Before re-installation the app was in connected state to RN42;result- after re-installation BT reconnection to RN42 doesnt happen.
I traced that the exception that comes for Test case 2 is :
W/System.err(4603): java.io.IOException: [JSR82] connect: Connection is not created (failed or aborted).
W/System.err(4603): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:395)
This was the exception I was getting again and again few days back.So now I kinda know when this exception can get thrown.
NOTE: For 'Test case2' ,here even un-installing and re-installing the app and then trying to connect app to RN42 doesnt work.We need to reboot the tablet to make the app connect to BT again.Moreover,I even tried connecting the real BlueTerm app(in test case 2),but it also did not get connected.So then I tried switching OFF and ON the tablet's BT.I observed that by switching off and then switching ON the BT and then trying to establish BT connection between tablet and RN42 was happening .But now, I was not getting any input signals from RN42 to tablet,but was able to just send data from tablet to RN42.
Tesing on Samsung S2/grand/nexus devices:
For the above Test case2,on these devices the app does get connected to BT after re-installation,even if it was/was not connected to RN42 via BT prior to re-installation.
Below is the code of my app and the log cat exception:
BlueTerm.java
#SuppressLint("HandlerLeak")
public class BlueTerm extends Activity {
BluetoothSocket Socket;
OutputStream DataOut;
InputStream DataIn;
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
private static TextView mTitle;
// Name of the connected device
private String mConnectedDeviceName = null;
/**
* Set to true to add debugging code and logging.
*/
public static final boolean DEBUG = true;
/**
* Set to true to log each character received from the remote process to the
* android log, which makes it easier to debug some kinds of problems with
* emulating escape sequences and control codes.
*/
public static final boolean LOG_CHARACTERS_FLAG = DEBUG && false;
/**
* Set to true to log unknown escape sequences.
*/
public static final boolean LOG_UNKNOWN_ESCAPE_SEQUENCES = DEBUG && false;
/**
* The tag we use when logging, so that our messages can be distinguished
* from other messages in the log. Public because it's used by several
* classes.
*/
public static final String LOG_TAG = "BlueTerm";
// Message types sent from the BluetoothReadService 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";
private BluetoothAdapter mBluetoothAdapter = null;
private static BluetoothSerialService mSerialService = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG)
Log.e(LOG_TAG, "+++ ON CREATE +++");
setContentView(R.layout.main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mSerialService = new BluetoothSerialService(this, mHandlerBT);
Button buzzerOn = (Button) findViewById(R.id.button1);
buzzerOn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("BlueTerm","Buzzer button clicked");
//send("37".getBytes());
send(bigIntToByteArray(37));
}
});
Button buzzerOff = (Button) findViewById(R.id.button2);
buzzerOff.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("BlueTerm","Buzzer button clicked");
//send("37".getBytes());
send(bigIntToByteArray(30));
}
});
Button recon = (Button) findViewById(R.id.button3);
recon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("BlueTerm","recon button clicked");
BluetoothAdapter iballAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice RN42_Device = iballAdapter.getRemoteDevice("00:06:66:49:57:5F");
try {
Socket = RN42_Device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
DataOut = Socket.getOutputStream();
DataIn = Socket.getInputStream();
} catch (Exception e1) {
e1.printStackTrace();
}
if (DataIn != null) {
Log.d("AppFunctions","DataIn is not null,so making it NULL");
try {DataIn.close();} catch (Exception e) {}
DataIn = null;
}
Log.i("AppFunctions", "DataOut -" + DataOut);
if (DataOut != null) {
Log.d("AppFunctions","DataOut is not null,so making it NULL");
try {DataOut.close();} catch (Exception e) {}
DataOut = null;
}
Log.i("AppFunctions", "Socket -" + Socket);
if (Socket != null) {
Log.d("AppFunctions","Socket is not null,so making it NULL");
try {Socket.close();} catch (Exception e) {}
Socket = null;
}
try {
Socket = RN42_Device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Socket.connect();
} catch (Exception e) {
e.printStackTrace();
}
if (mSerialService != null)
mSerialService.stop();
mSerialService.start();
}
});
if (DEBUG)
Log.e(LOG_TAG, "+++ DONE IN ON CREATE +++");
}
#Override
public void onStart() {
super.onStart();
if (DEBUG)
Log.e(LOG_TAG, "++ ON START ++");
mEnablingBT = false;
}
#Override
public synchronized void onResume() {
super.onResume();
if (DEBUG) {
Log.e(LOG_TAG, "+ ON RESUME +");
}
if (mSerialService != null) {
Log.v("BlueTerm","mSerialService is NOT null");
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mSerialService.getState() == BluetoothSerialService.STATE_NONE) {
// Start the Bluetooth chat services
Log.v("BlueTerm","starting BT chat service");
mSerialService.start();
}
}
}
}
#Override
public synchronized void onPause() {
super.onPause();
if (DEBUG)
Log.e(LOG_TAG, "- ON PAUSE -");
}
#Override
public void onStop() {
super.onStop();
if(DEBUG)
Log.e(LOG_TAG, "-- ON STOP --");
}
#Override
public void onDestroy() {
super.onDestroy();
if (DEBUG)
Log.e(LOG_TAG, "--- ON DESTROY ---");
if (mSerialService != null)
mSerialService.stop();
}
public int getConnectionState() {
return mSerialService.getState();
}
public void send(byte[] out) {
mSerialService.write( out );
}
// The Handler that gets information back from the BluetoothService
private final Handler mHandlerBT = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if(DEBUG) Log.i(LOG_TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothSerialService.STATE_CONNECTED:
break;
case BluetoothSerialService.STATE_CONNECTING:
break;
case BluetoothSerialService.STATE_LISTEN:
case BluetoothSerialService.STATE_NONE:
Log.d("BlueTerm","inside STATE_NONE in handler");
break;
}
break;
case MESSAGE_WRITE:
if (mLocalEcho) {
byte[] writeBuf = (byte[]) msg.obj;
}
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
Log.d("incoming writebytes",""+readBuf.toString());
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(DEBUG) Log.d(LOG_TAG, "onActivityResult " + resultCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Get the device MAC address
String address = "00:06:66:49:57:5F";
// Get the BLuetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mSerialService.connect(device);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
Log.d(LOG_TAG, "BT not enabled");
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.option_menu, menu);
mMenuItemConnect = menu.getItem(0);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.connect:
if (getConnectionState() == BluetoothSerialService.STATE_NONE) {
String address = "00:06:66:49:57:5F";
// Get the BLuetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
Log.d("BlueTerm","device: " + device);
// Attempt to connect to the device
mSerialService.connect(device);
}
else
if (getConnectionState() == BluetoothSerialService.STATE_CONNECTED) {
mSerialService.stop();
mSerialService.start();
}
return true;
case R.id.preferences:
//doPreferences();
return true;
case R.id.menu_special_keys:
//doDocumentKeys();
return true;
}
return false;
}
private byte[] bigIntToByteArray( final int i ) {
BigInteger bigInt = BigInteger.valueOf(i);
return bigInt.toByteArray();
}
}
BluetoothService:
/**
* 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 BluetoothSerialService {
// Debugging
private static final String TAG = "BluetoothReadService";
private static final boolean D = true;
private static final UUID SerialPortServiceClass_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
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 BluetoothSerialService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
// mEmulatorView = emulatorView;
}
/**
* 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;
Log.d("BluetoothSerialService","state : " + state);
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(BlueTerm.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_NONE);
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
* #param device The BluetoothDevice to connect
*/
public synchronized void connect(BluetoothDevice device) {
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);
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) {
if (D) Log.d(TAG, "connected");
// 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;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(BlueTerm.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(BlueTerm.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;
}
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) {
Log.e("BluetoothSerialService","Inside write fn" + " :" + out.toString());
// 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() {
setState(STATE_NONE);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BlueTerm.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BlueTerm.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
setState(STATE_NONE);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BlueTerm.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BlueTerm.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
/**
* 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;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(SerialPortServiceClass_UUID);
} catch (IOException e) {
Log.e(TAG, "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.e(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
// 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) {
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
// Start the service over to restart listening mode
//BluetoothSerialService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothSerialService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect 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) {
Log.e(TAG, "create ConnectedThread");
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.e(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
Log.e(TAG, "Entering while");
while (true) {
Log.e(TAG, "Inside while");
try {
// Read from the InputStream
bytes = 0;
Log.d("incoming bytes",""+bytes);
Log.e("BT","Inputstream :" + mmInStream);
//bytes = mmInStream.read(buffer);
bytes = mmInStream.read();
Log.d("incoming bytes",""+bytes);
//mEmulatorView.write(buffer, bytes);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BlueTerm.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
String a = buffer.toString();
a = "";
} catch (Exception e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
bytes = 0;
}
//Log.e(TAG, "Outside while");
}
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
Log.d("writing to outStream byte :", buffer.toString());
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
//mHandler.obtainMessage(BlueTerm.MESSAGE_WRITE, buffer.length, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (Exception e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}
Logcat error:
W/System.err(4603): java.io.IOException: [JSR82] connect: Connection is not created (failed or aborted).
W/System.err(4603): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:395)
I suspect that this error could be thrown because the app is not able to get access to the active BT port,in the above mentioned test case.Reason is because I read this site : https://code.google.com/p/android/issues/detail?id=5427 (See answer #19 by dknop)
I observe that none of this issue occur on samsung s2/grand/nexus devices which I tested on.My error could also be due to MTK processors/its BT firmware/iball custom android issue.(http://redacacia.me/2012/07/17/overcoming-android-bluetooth-blues-with-reflection-method/)
Has anyone faced a similar problem? Any help would be appreciated.Many thanks !
I've tested Bluetooth connectivity on dozens of different tablets, and I've seen some VERY flaky behavior. My apps always call createRfcommSocketToServiceRecord(...) in a loop because sometimes it will fail for no apparent reason, only to succeed on a later attempt. And the API doesn't let you distinguish between transient and permanent failures. Some tablets give you a clue in the text of the error message, but others don't.
I typically try to connect 100 times at 100ms intervals, and then stop and ask the user if the device they're trying to connect to is turned on and in range. On one particular tablet model I've tested, it's not unusual for the connection to fail more than 300 times... and then it will suddenly work like nothing was ever wrong.
I have used this piece of code to make my connectivity to Bluetooth device(i.e. Bluetooth printer) stable. Now it connect 9.9 times out of 10. If still some error occurred i reset my Bluetooth programmatically again call this piece of code then it connect 10 times out of 10.
public boolean connectToPrinter(String printerName) throws IOException
{
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
BluetoothDevice device = getPrinterByName(printerName);
if (bluetoothSocket != null)
{
bluetoothSocket.close();
}
try {
Method m=device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
bluetoothSocket= (BluetoothSocket) m.invoke(device, 1);
} catch (Exception e) {
e.printStackTrace();
}
if (bluetoothSocket == null)
return false;
bluetoothSocket.connect();
return true;
}
here is the code of getPrinterByName():
private BluetoothDevice getPrinterByName(String printerName)
{
Set<BluetoothDevice> pairedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
for (BluetoothDevice device : pairedDevices)
{
Log.e("","device name: "+device.getName());
if (device.getName() == null)
continue;
if (device.getName().contains(printerName))
{
remoteDevice = device;
// pairPrinter(printerName);
return remoteDevice;
}
}
return null;
}
bluetoothSocket is the Object of BluetoothSocket class. and don't forget to run this code in thread otherwise this will block your Main Thread. :-)
hi friend just replace the code to connect to bluetoothsocket by the code using reflection to
establish connection.....
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, MY_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
}
return device.createRfcommSocketToServiceRecord(MY_UUID);
}
Quote: I observed that by switching off and then switching ON the BT and then trying to establish BT connection between tablet and RN42 was happening .But now, I was not getting any input signals from RN42 to tablet,but was able to just send data from tablet to RN42.
So, before reinstalling app it WAS possible to receive input signals from rn42?
I have gone through Demo's but I tried with the QuickStart example in which a image is uploaded. but I am not getting how to upload a audio file in which i will give path to my files or Intent Picker to select the file.I am using createFile() method
how to upload a audio file to my drive?
I need to convert it to any streams ?
why google has made this so much complicated just to upload file?
How to Synch Drive files ?
How to stream (play audio file from drive)?
The Below code just upload file which contains nothing.
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "android-drive-quickstart";
//private static final int REQUEST_CODE_CAPTURE_IMAGE = 1;
private static final int REQUEST_CODE_CREATOR = 2;
private static final int REQUEST_CODE_RESOLUTION = 3;
private static final int PICKFILE_RESULT_CODE = 1;
private static Uri fileUri;
private ContentsResult result;
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Connect the client. Once connected, the camera is launched.
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
showToast("Error in on connection failed");
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
showToast("error"+e.toString());
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
showToast("Inside Connected");
result = Drive.DriveApi.newContents(mGoogleApiClient).await();
showToast(""+result.getContents().toString());
OutputStream outputStream = result.getContents().getOutputStream();
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
//java.io.File fileContent = new java.io.File(fileUri.getPath());
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("New file")
.setMimeType("audio/MP3")
.setStarred(true).build();
showToast("meta data created");
DriveFileResult dfres= Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), changeSet, result.getContents())
.await();
showToast("await() complete");
if (!result.getStatus().isSuccess()) {
showToast("Error while trying to create the file");
return;
}
showToast("Created a file: " + dfres.getDriveFile().getDriveId());
}
private void saveFileToDrive()
{
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == REQUEST_CODE_RESOLUTION && resultCode == RESULT_OK) {
mGoogleApiClient.connect();
showToast("Connected");
}
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
public void showToast(final String toast) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), toast, Toast.LENGTH_SHORT).show();
}
});
}
public GoogleApiClient getGoogleApiClient() {
return mGoogleApiClient;
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
}
Try this:
**
* An AsyncTask that maintains a connected client.
*/
public abstract class ApiClientAsyncTask<Params, Progress, Result>
extends AsyncTask<Params, Progress, Result> {
private GoogleApiClient mClient;
public ApiClientAsyncTask(Context context) {
GoogleApiClient.Builder builder = new GoogleApiClient.Builder(context)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE);
mClient = builder.build();
}
#Override
protected final Result doInBackground(Params... params) {
Log.d("TAG", "in background");
final CountDownLatch latch = new CountDownLatch(1);
mClient.registerConnectionCallbacks(new ConnectionCallbacks() {
#Override
public void onConnectionSuspended(int cause) {
}
#Override
public void onConnected(Bundle arg0) {
latch.countDown();
}
});
mClient.registerConnectionFailedListener(new OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult arg0) {
latch.countDown();
}
});
mClient.connect();
try {
latch.await();
} catch (InterruptedException e) {
return null;
}
if (!mClient.isConnected()) {
return null;
}
try {
return doInBackgroundConnected(params);
} finally {
mClient.disconnect();
}
}
/**
* Override this method to perform a computation on a background thread, while the client is
* connected.
*/
protected abstract Result doInBackgroundConnected(Params... params);
/**
* Gets the GoogleApliClient owned by this async task.
*/
protected GoogleApiClient getGoogleApiClient() {
return mClient;
}
}
Class to save file:
/**
* An async task that creates a new text file by creating new contents and
* metadata entities on user's root folder. A number of blocking tasks are
* performed serially in a thread. Each time, await() is called on the
* result which blocks until the request has been completed.
*/
public class CreateFileAsyncTask extends ApiClientAsyncTask<String, Void, Metadata>
{
public CreateFileAsyncTask(Context context)
{
super(context);
}
#Override
protected Metadata doInBackgroundConnected(String... arg0)
{
// First we start by creating a new contents, and blocking on the
// result by calling await().
DriveApi.ContentsResult contentsResult = Drive.DriveApi.newContents(getGoogleApiClient()).await();
if (!contentsResult.getStatus().isSuccess()) {
// We failed, stop the task and return.
return null;
}
//file to save in drive
String pathFile = arg0[0];
File file = new File(pathFile);
// Read the contents and open its output stream for writing, then
// write a short message.
Contents originalContents = contentsResult.getContents();
OutputStream os = originalContents.getOutputStream();
try
{
InputStream dbInputStream = new FileInputStream(file);
byte[] buffer = new byte[1024];
int length;
int counter = 0;
while((length = dbInputStream.read(buffer)) > 0)
{
++counter;
os.write(buffer, 0, length);
}
dbInputStream.close();
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
// Create the metadata for the new file including title and MIME
// type.
MetadataChangeSet originalMetadata = new MetadataChangeSet.Builder()
.setTitle(file.getName())
.setMimeType("application/x-sqlite3").build();
// Create the file in the root folder, again calling await() to
// block until the request finishes.
DriveFolder rootFolder = Drive.DriveApi.getRootFolder(getGoogleApiClient());
DriveFolder.DriveFileResult fileResult = rootFolder.createFile(
getGoogleApiClient(), originalMetadata, originalContents).await();
if (!fileResult.getStatus().isSuccess()) {
// We failed, stop the task and return.
return null;
}
// Finally, fetch the metadata for the newly created file, again
// calling await to block until the request finishes.
DriveResource.MetadataResult metadataResult = fileResult.getDriveFile()
.getMetadata(getGoogleApiClient())
.await();
if (!metadataResult.getStatus().isSuccess()) {
// We failed, stop the task and return.
return null;
}
// We succeeded, return the newly created metadata.
return metadataResult.getMetadata();
}
#Override
protected void onPostExecute(Metadata result)
{
super.onPostExecute(result);
if (result == null)
{
// The creation failed somehow, so show a message.
App.showAppMsg(getActivity(),"Error while creating the file.",Style.ALERT);
return;
}
// The creation succeeded, show a message.
App.showAppMsg(getActivity(),"File created: " + result.getDriveId(),Style.CONFIRM);
}
}
I haven't played with audio files, but in general, the Google Drive Android API (GDAA) does not deal with audio files per say. You just create a file, set metadata and stuff binary content in it. Look at the code here (plus some readme blah blah here). You'll find a code line
byte[] buff = ("written on: " + _dfn.getName()).getBytes();
if (null == _gc.creatFile(fldr, name, MIMETEXT, buff)) return;
there, that produces byte[] buffer and creates a file with text MIME type. So, try to use it, just replace the MIME type and stuff the 'buff' with your audio stream. I do it successfully with JPEG binaries.
There is also GooApiClnt wrapper class there that handles most of the basic GDAA functions. Don't try to code this way at work, though, it may get you fired :-).
Good luck.
In your onConnected method you create the new file, but you never put any new content in it. You create the new content in this line:
result = Drive.DriveApi.newContents(mGoogleApiClient).await();
Than you get a hold of it's output stream in this line:
OutputStream outputStream = result.getContents().getOutputStream();
And than you create an empty byte array output stream in this line:
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
But you never fill this 'bitmapStream' with any content, and worst: you never write it to your content's 'outputStream'.
What you should do next is write your audio file's contents to 'bitmapStream' something like this:
InputStream in = file.getInputStream(/*you need to get the file's path and put it here*/ "some_audio_file.mp3");
int singleByte;
while((singleByte = in.read()) != -1){
bitmapStream.write(b);
}
Now you'd have your file's content inside 'bitmapStrea' and you can write it to the new content's 'outputStream' like this:
outputStream.write(bitmapStream.toByteArray());
Than you do the 'MetadataChangeSet' stuff and you should be fine.
Some advices:
1. It is not a good practice to do I/O operations like file or network activities (or file AND network activities in your case) on the main thread. Better use an AsyncTask to do it in a background thread.
Don't call your ByteArrayOutputStream instance 'bitmapStream' if you use it to upload an audio file.
Here's an example of a class that uses an AsyncTask to upload an image (and guess what I called the ByteArrayOutputStream... right - 'bitmapStream'):
public class TakePhotoActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
/**
* Request code for auto Google Play Services error resolution.
*/
protected static final int REQUEST_CODE_RESOLUTION = 1;
private static final String TAG = "TakePhotoActivity";
private static final String KEY_IN_RESOLUTION = "is_in_resolution";
private static final int REQUEST_CODE_CREATOR = 2;
/**
* Google API client.
*/
private GoogleApiClient mGoogleApiClient;
/**
* Receives the new file's contents and executes the editor AsyncTask
*/
private ResultCallback<DriveApi.ContentsResult> mSaveFileCallback = new ResultCallback<DriveApi.ContentsResult>() {
#Override
public void onResult(DriveApi.ContentsResult contentsResult) {
EditFileAsyncTask editFileAsyncTask = new EditFileAsyncTask();
editFileAsyncTask.execute(contentsResult);
}
};
/**
* Determines if the client is in a resolution state, and
* waiting for resolution intent to return.
*/
private boolean mIsInResolution;
private Bitmap mBitmapToSave;
/**
* Called when the activity is starting. Restores the activity state.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_menu_photo);
if (savedInstanceState != null) {
mIsInResolution = savedInstanceState.getBoolean(KEY_IN_RESOLUTION, false);
}
try {
InputStream inputStream = getAssets().open("some_image.jpg");
mBitmapToSave = BitmapFactory.decodeStream(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Called when the Activity is made visible.
* A connection to Play Services need to be initiated as
* soon as the activity is visible. Registers {#code ConnectionCallbacks}
* and {#code OnConnectionFailedListener} on the
* activities itself.
*/
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
// Optionally, add additional APIs and scopes if required.
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
Log.d("test", "connect()");
mGoogleApiClient.connect();
}
/**
* Called when activity gets invisible. Connection to Play Services needs to
* be disconnected as soon as an activity is invisible.
*/
#Override
protected void onStop() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onStop();
}
/**
* Saves the resolution state.
*/
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_IN_RESOLUTION, mIsInResolution);
}
/**
* Handles Google Play Services resolution callbacks.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_RESOLUTION:
retryConnecting();
break;
}
}
private void retryConnecting() {
mIsInResolution = false;
if (!mGoogleApiClient.isConnecting()) {
Log.d("test", "connect()");
mGoogleApiClient.connect();
}
}
/**
* Called when {#code mGoogleApiClient} is connected.
*/
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "GoogleApiClient connected");
// TODO: Start making API requests.
if (mBitmapToSave != null) {
saveFileToDrive();
}
}
/**
* Called when {#code mGoogleApiClient} connection is suspended.
*/
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
retryConnecting();
}
/**
* Called when {#code mGoogleApiClient} is trying to connect but failed.
* Handle {#code result.getResolution()} if there is a resolution
* available.
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// Show a localized error dialog.
GooglePlayServicesUtil.getErrorDialog(
result.getErrorCode(), this, 0, new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
retryConnecting();
}
}
).show();
return;
}
// If there is an existing resolution error being displayed or a resolution
// activity has started before, do nothing and wait for resolution
// progress to be completed.
if (mIsInResolution) {
return;
}
mIsInResolution = true;
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
retryConnecting();
}
}
private void saveFileToDrive() {
Log.i(TAG, "Creating new contents.");
Drive.DriveApi.newContents(mGoogleApiClient).setResultCallback(mSaveFileCallback);
}
private void showMessage(String message) {
Log.i(TAG, message);
// Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
private class EditFileAsyncTask extends AsyncTask<DriveApi.ContentsResult, Void, Boolean> {
#Override
protected Boolean doInBackground(DriveApi.ContentsResult... params) {
DriveApi.ContentsResult contentsResult = params[0];
if (!contentsResult.getStatus().isSuccess()) {
showMessage("Failed to create new contents.");
return false;
}
showMessage("New contents created.");
OutputStream outputStream = contentsResult.getContents().getOutputStream();
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
mBitmapToSave.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
try {
outputStream.write(bitmapStream.toByteArray());
} catch (IOException e) {
showMessage("Unable to write file contents.");
e.printStackTrace();
}
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("image/jpeg")
.setTitle("some_image.jpg")
.build();
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialContents(contentsResult.getContents())
.build(mGoogleApiClient);
try {
startIntentSenderForResult(intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
showMessage("Failed to launch file chooser.");
e.printStackTrace();
}
return true;
}
#Override
protected void onPostExecute(Boolean result) {
if (!result) {
showMessage("Error while editing contents");
return;
}
showMessage("Successfully edited contents");
}
}
}
By the way, most of the code in this class was auto-generated by Android Studio, because when I created the project I marked the initial class to be a google services class.
It,s simple. After I trying hard, I found the solution.
private String mFileName = null;
File folder = new File(Environment.getExternalStorageDirectory() +
"/FolderFile");
if (!folder.exists()) {
folder.mkdir();
}
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/FolderFile/a.mp3";
After the audio is recorded. You must
buildGoogleSignInClient()
createFileWithIntent(mFileName);
private void createFileWithIntent(String I) {
final String audio = I;
final Task<DriveFolder> rootFolderTask = getDriveResourceClient().getRootFolder();
final Task<DriveContents> createContentsTask = getDriveResourceClient().createContents();
Tasks.whenAll(rootFolderTask, createContentsTask)
.continueWithTask(new Continuation<Void, Task<DriveFile>>() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public Task<DriveFile> then(#NonNull Task<Void> task) throws Exception {
DriveFolder PASTA = rootFolderTask.getResult();
DriveContents DADOS = createContentsTask.getResult();
File file = new File(audio);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
FileInputStream fis = new FileInputStream(file);
for (int readNum; (readNum = fis.read(buf)) != -1;) {
baos.write(buf, 0, readNum);
}
OutputStream outputStream = DADOS.getOutputStream();
outputStream.write(baos.toByteArray());
MetadataChangeSet TIPO = new MetadataChangeSet.Builder()
.setMimeType("audio/mp3")
.setTitle("audio.mp3")
.setStarred(true)
.build();
return getDriveResourceClient().createFile(PASTA, TIPO, DADOS);
}
});
}