Why IntentReceiverLeaked? - java

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.

Related

Send a string through WiFi-Direct between two android devices

It is now over a month that I'm trying to send a string using WiFi-Direct between two android devices, but I'm still struggling hard to understand what I'm doing wrong.
I've looked around forums but they often don't give much detail on how to achieve what I want.
I also went through those two guides from the android developer's website:
Create P2P connections with Wi-Fi Direct
Wi-Fi Direct (peer-to-peer or P2P) overview
I'm using one activity - ActivityConnection - where I toggle the visibility of views depending on whether the user previously chose to send or to receive the string.
Immediatly, on the client side, discoverPeers() looks for any device with WiFi-Direct turned on and displays them on a ListView. Once the user chooses a device and presses the send button, the connection makes itself and the string is sent.
On the server side, the server is immediatly launched using my AsyncServerTask class. There, it waits for a client to connect and to retrieve its sent string.
My main problem is that, after choosing the device and tapping on the send button, the server side isn't receiving anything.
My second problem is that, sometimes, devices aren't being discovered and the listview stays empty.
Am I missing something? Or maybe doing something wrong?
Here's my current code.
I took the liberty to get rid of any line I thought to be out of context to make it easier to read.
ActivityConnection
public class ActivityConnection extends AppCompatActivity implements NewPeersListener {
public static final String CONNECTION_ACTOR = "actor";
public static final String SEND_INFO = "send";
public static final String RECEIVE_INFO = "receive";
ListView listViewDevices;
private IntentFilter intentFilter;
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
private WiFiDirectBroadcastReceiver receiver;
public List <WifiP2pDevice> listDevices;
private WifiP2pDevice selectedDevice;
#Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
confirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
connectToSelectedDevice();
}
});
Intent intent = this.getIntent();
String actor = intent.getStringExtra(CONNECTION_ACTOR);
this.intentFilter = new IntentFilter();
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
this.intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
this.manager = (WifiP2pManager) this.getSystemService(Context.WIFI_P2P_SERVICE);
this.channel = this.manager.initialize(this, this.getMainLooper(), null);
this.receiver = new WiFiDirectBroadcastReceiver(this.manager, this.channel, this);
this.listDevices = new ArrayList <> ();
if (actor.equals(SEND_INFO)) {
DeviceAdapter adapter = new DeviceAdapter(ActivityConnection.this, R.layout.device_item, this.listDevices);
this.listViewDevices.setAdapter(adapter);
this.listViewDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedDevice = listDevices.get(position);
}
});
this.discoverPeers();
}
else if (actor.equals(RECEIVE_INFO)) {
new ServerAsyncTask(this).execute();
}
}
#Override
protected void onResume() {
super.onResume();
this.receiver = new WiFiDirectBroadcastReceiver(this.manager, this.channel, this);
this.registerReceiver(this.receiver, this.intentFilter);
}
#Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.receiver);
}
public void resultReceived (String result) {
Toast.makeText(ActivityConnection.this, "Received! :)", Toast.LENGTH_SHORT).show();
}
private void discoverPeers () {
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// The discovery process succeeded
}
#Override
public void onFailure(int reason) {
// The discovery process DID NOT succeed
Toast.makeText(ActivityConnection.this, "Discovery process DID NOT succeed. Please verify that WiFi-Direct is active.", Toast.LENGTH_LONG).show();
}
});
}
private void connectToSelectedDevice () {
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = this.selectedDevice.deviceAddress;
this.manager.connect(this.channel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// Send string
Intent serviceIntent = new Intent(ActivityConnection.this, TransferService.class);
serviceIntent.setAction(TransferService.ACTION_SEND_STRING);
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_ADDRESS, getMacAddress());
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_PORT, 8090);
startService(serviceIntent);
onBackPressed();
}
#Override
public void onFailure(int reason) {
Toast.makeText(ActivityConnection.this, "Connection failed. Try again.", Toast.LENGTH_SHORT).show();
}
});
}
#NonNull
private String getMacAddress () {
try {
List <NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder result = new StringBuilder();
for (byte b : macBytes) {
result.append(String.format("%02X:",b));
}
if (result.length() > 0) {
result.deleteCharAt(result.length() - 1);
}
return result.toString();
}
} catch (Exception e) {
}
return "02:00:00:00:00:00";
}
#Override
public void newPeers (WifiP2pDeviceList wifiP2pDeviceList) {
this.listDevices = new ArrayList <> (wifiP2pDeviceList.getDeviceList());
DeviceAdapter adapter = new DeviceAdapter(ActivityConnection.this, R.layout.device_item, this.listDevices);
this.listViewDevices.setAdapter(adapter);
}
}
WiFiDirectBroadcastReceiver
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
private ActivityConnection activity;
private List <NewPeersListener> listeners;
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel, ActivityConnection activity) {
super();
this.manager = manager;
this.channel = channel;
this.activity = activity;
this.listeners = new ArrayList <> ();
this.listeners.add(activity);
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wi-Fi P2P is enabled
} else {
// Wi-Fi P2P is not enabled
Toast.makeText(this.activity, "Please turn on WiFi-Direct (or WiFi-P2P).", Toast.LENGTH_SHORT).show();
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// Request available peers from the wifi p2p manager.
if (this.manager != null) {
this.manager.requestPeers(this.channel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
for (NewPeersListener listener : listeners) {
listener.newPeers(peers);
}
}
});
}
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
// Respond to new connection or disconnections
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
}
}
}
ServerAsyncTask (server)
public class ServerAsyncTask extends AsyncTask<Void, Void, String> {
private ServerSocket serverSocket;
private Socket clientSocket;
private DataInputStream stream;
private WeakReference <Context> contextWeakReference;
ServerAsyncTask (Context context) {
this.contextWeakReference = new WeakReference <> (context);
}
#Override
protected String doInBackground (Void... params) {
try {
this.serverSocket = new ServerSocket(8090);
this.clientSocket = this.serverSocket.accept();
this.stream = new DataInputStream(this.clientSocket.getInputStream());
String received = this.stream.readUTF();
this.serverSocket.close();
return received;
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
return null;
} finally {
if (this.stream != null) {
try {
this.stream.close();
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
}
}
if (this.clientSocket != null) {
try {
this.clientSocket.close();
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
}
}
if (this.serverSocket != null) {
try {
this.serverSocket.close();
} catch (IOException e) {
Log.e(TransferService.TAG, Objects.requireNonNull(e.getMessage()));
}
}
}
}
/*
* (non-Javadoc)
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute (String result) {
super.onPostExecute(result);
((ActivityConnection) this.contextWeakReference.get()).resultReceived(result);
}
}
TransferService (client)
public class TransferService extends IntentService {
public static final String TAG = "WIFI_DIRECT";
private static final int SOCKET_TIMEOUT = 5000;
public static final String ACTION_SEND_STRING = "sendString";
public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";
public TransferService (String name) {
super(name);
}
public TransferService () {
super("TransferService");
}
#Override
protected void onHandleIntent (Intent intent) {
Context context = getApplicationContext();
if (intent.getAction().equals(ACTION_SEND_STRING)) {
String toSend = "string to send";
String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
Socket socket = null;
DataOutputStream stream = null;
try {
// Create a client socket with the host, port, and timeout information.
socket = new Socket();
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.d(TAG, "Client connected socket - " + socket.isConnected());
// Send string
stream = new DataOutputStream(socket.getOutputStream());
stream.writeUTF(toSend);
stream.close();
Toast.makeText(context, "Sent! :)", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, Objects.requireNonNull(e.getMessage()));
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}
In the ActivityConnetion class, I was giving a MAC address instead of an IP address. I don't know why I didn't see this, nor why I did it in the first place. So I looked around this forum and found out how to get the IP address of the WiFi-Direct's group owner: Wifi Direct Group Owner Address .
To get the code running, I went into the ActivityConnetion class, delete the getMacAddress() method and replaced this line:
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_ADDRESS, getMacAddress());
with this line:
serviceIntent.putExtra(TransferService.EXTRAS_GROUP_OWNER_ADDRESS, "192.168.49.1");
As the group owner's IP is always the same, one can write it down directly. As doing so can stop working if the IP changes, I would recommend looking for the group owner's IP instead. The link above show's how to do it.

How to prevent Bluetooth Disconnected when moving Fragment

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

Sending string from PC to android app using bluetooth Dongle

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.

Connection is not created (failed or aborted) exception thrown during Bluetooth connection in Android

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?

Google Drive Android API how to upload a audio file to my drive ? How to sync drive files?

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

Categories