I am pogramming a bluetooth device. I found when I tried to disconnect, the app will hang for some devices.
public class ConnectionThread extends Thread {
....
#Override
public void run() {
bReading = true;
while (bReading) {
try {
if (mInStream==null) break;
bytes = mInStream.read(buffer);
} catch (IOException e) {
cancel();
break;
}
}
}
public void cancel() {
bReading = false;
if (mInStream != null) {
try {
mInStream.close();
} catch (Exception e) {
e.printStackTrace();
}
mInStream = null;
}
So I call the cancel function to stop the while loop.
For above logic, there will be "thread dead" event, which is not good. For some device, the "thead dead" event will even cause the app hangs.
However, I dont know what wrong is the above code. I am not sure if it is caused any synchronous issue? How to improve the flow to remove the potential hang issue. any kind of advice is highly appreciated. Thanks.
To stop the communication you can close the socket :
"
while (true) {
try {
if (mInStream==null) break;
bytes = mInStream.read(buffer);
} catch (IOException e) {
break;
}
}
"
public void cancel(){
try{
mmSocket.close();
if(DEBUG_MODE){
Log.i(TAG, "socket closed");
}
}catch(IOException e){
Log.e(TAG, "socket close failed", e);
}
}
When the socket close the loop will naturally break, since the read will fail
Related
My app tries to record the sound by using the MediaRecorder API. My start recording method looks like this:
public void start() {
if(this.mRecorder == null) {
try{
this.mRecorder = new MediaRecorder();
this.mRecorder.setAudioSource(1);
this.mRecorder.setOutputFormat(1);
this.mRecorder.setAudioEncoder(1);
this.mRecorder.setOutputFile("/dev/null");
} catch (RuntimeException re) {
}
try {
this.mRecorder.prepare();
} catch (IllegalStateException var3) {
var3.printStackTrace();
} catch (IOException var4) {
var4.printStackTrace();
}
this.mRecorder.start();
this.mEMA = 0.0D;
}
}
But I get crash reports from users on the following line:
this.mRecorder.start();
The IllegalStateException stack trace is:
java.lang.RuntimeException:
atandroid.app.ActivityThread.performResumeActivity(ActivityThread.java:3493)
atandroid.app.ActivityThread.handleResumeActivity(ActivityThread.java:3533)
atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2791)
atandroid.app.ActivityThread.-wrap12(ActivityThread.java)
atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1532)
atandroid.os.Handler.dispatchMessage(Handler.java:102)
atandroid.os.Looper.loop(Looper.java:163)
atandroid.app.ActivityThread.main(ActivityThread.java:6342)
atjava.lang.reflect.Method.invoke(NativeMethod)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
atcom.android.internal.os.ZygoteInit.mai(ZygoteInit.java:770)
Causedby:java.lang.IllegalStateException:
atandroid.media.MediaRecorder.start(NativeMethod)
atmeasure.sound.decibels.SoundMeter.start(SoundMeter.java:43)
atmeasure.sound.decibels.MyActivity.start(MyActivity.java:138)
atmeasure.sound.decibels.MyActivity.onResume(MyActivity.java:521)
atandroid.app.Instrumentation.callActivityOnResume(Instrumentation.java:1270)
atandroid.app.Activity.performResume(Activity.java:6960)
atandroid.app.ActivityThread.performResumeActivity(ActivityThread.java:3470)
The app is crashing for users. Any help!
I am trying to sending and receiving image to display in ImageView using Server-socket, I want to decrypt image using server-socket but its not working.
Image url like this :
http://localhost:4545/sdcard0/emulated/test.img;
Service :
public class ImageDecrptService extends Service {
private ServerSocket serverSocket;
private Socket socket;
void acceptRequestNDecryptFile() {
try {
try {
serverSocket = new ServerSocket(4545);
} catch (Exception e) {
}
while (true) {
Log.e("", "thread called true");
socket = serverSocket.accept();
//some thing code
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
acceptRequestNDecryptFile();
Log.e("", "thread called ");
} catch (Exception e) {
e.printStackTrace();
}
}
});
#Override
public void onCreate() {
super.onCreate();
try {
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
How can pass image url to server socket?
Note : I do not want use Bitmap to display image.
If you have a http url of an image on a webserver then you would need a client to grab the image.
So your ServerSocket is of no use.
Also a client-Socket would not be the right way to go.
You need to use a http component or library to download the image.
Or invoke the DownloadManager.
I want to write audio data that comes from the microphone to a file.
I have 2 threads: one "listen" for the audio data and send it to the second thread(the consumer) which stores it in a queue. The consumer thread constantly polls the queue and writes on the file the audioData as byte[].
I use RandomAccessFile for the writing. Considering that everything is syncronized in my code, should I use some non-thread-safe class like FileChannel?
below is some code snippets:
Read audio data
private void read(){
// fill the buffer with the mic input
readFully(buffer, 0, buffer.length);
// creates audioData from this buffer
WAVData audioData = new WAVData(buffer.length);
audioData.arrayCopy(buffer);
// add it to the consumer
mAudioWritter.add(audioData);
}
Write audio data - the consumer clas
public void add(WAVEntity audioEntity){
mQueue.add(audioEntity);
synchronized (mLock) {
mLock.notify();
}
}
#Override
public void run() {
synchronized (mLock) {
while(!isFinalized){
//wait if queue is empty
while(mQueue.isEmpty()){
try {
mLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
WAVEntity entity = mQueue.poll();
if(entity != null){
try {
entity.writeOnFile(file);
} catch (AudioRecorderError e) {
// error handling
}
}
}
}
callback.threadFinished(this);
// try closing this file
try {
file.close();
} catch (IOException e) {
Log.e(getClass().getName(), e.getMessage(), e);
}
}
#Override
public boolean writeOnFile(RandomAccessFile fWriter) throws AudioRecorderError {
synchronized (data) {
//write on the file
try {
fWriter.write(data);
} catch (Exception e) {
AudioRecorderError error = new AudioRecorderError(e, "Data chunck was not written. See stack trace.");
throw error;
}
}
return false;
}
I'm writing a library project for multiple APPs to use. And for some reason, I must make a function mutual exclusion for different APPs, so I need a cross-process lock. But as far as I know, in android APPs can only write to it's own file's directory in internal storage, and external storage is unreliable because some device don't have one. So file lock seems not applicable for me, so is there any other way to implement cross-process lock?
thanks~
If you do not want to (or you can not) use flock or fcntl, maybe you can use LocalServerSocket to implement a spinlock.
For example:
public class SocketLock {
public SocketLock(String name) {
mName = name;
}
public final synchronized void tryLock() throws IOException {
if (mServer == null) {
mServer = new LocalServerSocket(mName);
} else {
throw new IllegalStateException("tryLock but has locked");
}
}
public final synchronized boolean timedLock(int ms) {
long expiredTime = System.currentTimeMillis() + ms;
while (true) {
if (System.currentTimeMillis() > expiredTime) {
return false;
}
try {
try {
tryLock();
return true;
} catch (IOException e) {
// ignore the exception
}
Thread.sleep(10, 0);
} catch (InterruptedException e) {
continue;
}
}
}
public final synchronized void lock() {
while (true) {
try {
try {
tryLock();
return;
} catch (IOException e) {
// ignore the exception
}
Thread.sleep(10, 0);
} catch (InterruptedException e) {
continue;
}
}
}
public final synchronized void release() {
if (mServer != null) {
try {
mServer.close();
} catch (IOException e) {
// ignore the exception
}
}
}
private final String mName;
private LocalServerSocket mServer;
}
I'm trying to develop an Android application which transfers images from one device to another. The received image would then be shown on the ImageView inside my application. To achieve my task, I thought to send a byte array of the bitmap. I'm able to get the first image on the imageview. But, as soon as I click on the button to send another image the application fails to send the bitmap. It shows me an exception "java.io.IOException: Service fiscovery failed." To send any image successfully I need to restart my application on the receiving/remote device. Can anyone please suggest a solution to mu problem. The logcat has also been included below.
Code to establish the connection:
private class StartConnectionThread extends Thread{
private final BluetoothSocket bluetoothSocket;
private final BluetoothDevice bluetoothDevice;
public StartConnectionThread(BluetoothDevice device){
BluetoothSocket tempBluetoothSocket=null;
bluetoothDevice=device;
try
{
System.out.println(uuid);
tempBluetoothSocket=device.createRfcommSocketToServiceRecord(uuid);
}
catch(IOException ioException)
{
}
bluetoothSocket=tempBluetoothSocket;
}
#Override
public void run() {
// TODO Auto-generated method stub
bluetoothAdapter.cancelDiscovery();
try
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bluetoothSocket.connect();
}
catch(IOException ioException)
{
System.out.println("bluetoothSocketInThread failed");
try
{
bluetoothSocket.close();
}
catch(IOException cancelIOException)
{
}
return;
}
manageConnectedSocket(bluetoothSocket);
}
public void cancel()
{
try
{
bluetoothSocket.close();
}
catch(IOException ioException)
{
}
}
}
Code to accept the connection:
private class AcceptConnectionThread extends Thread
{
private final BluetoothServerSocket bluetoothServerSocket;
public AcceptConnectionThread() {
// TODO Auto-generated constructor stub
System.out.println("constructor");
BluetoothServerSocket tempBluetoothServerSocket=null;
try
{
tempBluetoothServerSocket=bluetoothAdapter.listenUsingRfcommWithServiceRecord("My Souvenirs", uuid);
}
catch(IOException ioException)
{
}
bluetoothServerSocket=tempBluetoothServerSocket;
}
#Override
public void run() {
// TODO Auto-generated method stub
BluetoothSocket bluetoothSocket=null;
while(true)
{
try
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(bluetoothServerSocket);
if(bluetoothServerSocket!=null)
{
bluetoothSocket=bluetoothServerSocket.accept();
}
System.out.println("accept");
}
catch(IOException ioException){
break;
}
if(bluetoothSocket!=null)
{
manageConnectedSocket(bluetoothSocket);
try {
bluetoothServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
public void cancel()
{
try{
bluetoothServerSocket.close();
}
catch(IOException ioException){
}
}
}
Code to manage the connection:
private class ManageConnectedDevicesThread extends Thread
{
private final BluetoothSocket connectedBluetoothSocket;
public ManageConnectedDevicesThread(BluetoothSocket socket) {
// TODO Auto-generated constructor stub
connectedBluetoothSocket=socket;
InputStream tempInputStream=null;
OutputStream tempOutputStream=null;
try
{
tempInputStream=socket.getInputStream();
tempOutputStream=socket.getOutputStream();
}
catch(IOException ioException)
{
}
inputStream=tempInputStream;
outputStream=tempOutputStream;
}
#Override
public void run() {
// TODO Auto-generated method stub
byte[] buffer=new byte[1024*8];
int bytes;
while(true)
{
try
{
bytes=inputStream.read(buffer);
handler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
System.out.println("handler");
}
catch(IOException ioException)
{
System.out.println("for handler:" +ioException);
break;
}
}
}
public void write(byte[] bytes)
{
try
{
outputStream.write(bytes);
}
catch(IOException ioException){
System.out.println("exception in wrie tatement of managing connections");
}
}
public void close()
{
try {
connectedBluetoothSocket.close();
} catch (IOException e) {
// TODO: handle exception
}
}
}
Code to reset the connection:
void resetConnection()
{
if(inputStream!=null)
{
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(outputStream!=null)
{
try {
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(startConnectionThread!=null)
{
System.out.println("start wala active tha");
startConnectionThread.cancel();
}
if(acceptConnectionThread!=null)
{
System.out.println("accept wala active tha");
acceptConnectionThread.cancel();
}
if(manageConnectedDevicesThread!=null)
{
System.out.println("manage wala active tha");
manageConnectedDevicesThread.close();
}
}
}
code for handler is shown below:
private final Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
System.out.println("MESSAGE_READ");
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
byte[] b=readMessage.getBytes();
Bitmap bitmap1=BitmapFactory.decodeByteArray(readBuf, 0, readBuf.length);
imageView.setImageBitmap(bitmap1);
break;
}
};
The logcat shows the following:
01-25 14:49:31.800: D/dalvikvm(9451): Debugger has detached; object registry had 1 entries
01-25 14:49:38.380: V/BluetoothSocket.cpp(9451): initSocketNative
01-25 14:49:38.380: V/BluetoothSocket.cpp(9451): ...fd 40 created (RFCOMM, lm = 26)
01-25 14:49:38.380: V/BluetoothSocket.cpp(9451): initSocketFromFdNative
01-25 14:49:40.420: D/BluetoothUtils(9451): isSocketAllowedBySecurityPolicy start : device null
01-25 14:49:41.680: I/System.out(9451): bluetoothSocketInThread failed
01-25 14:49:41.680: V/BluetoothSocket.cpp(9451): abortNative
01-25 14:49:41.680: V/BluetoothSocket.cpp(9451): ...asocket_abort(40) complete
01-25 14:49:41.680: V/BluetoothSocket.cpp(9451): destroyNative
01-25 14:49:41.680: V/BluetoothSocket.cpp(9451): ...asocket_destroy(40) complete
Thanks in advance.
Maybe you can try adding thread.sleep for a second? See this discussion:
"The only way I've been able to fix the problem is by adding a
thread.sleep for a second before closing the connection."
also see dan's two consecutive comments on this thread:
"I was able to get this to run only after separating the calls to
findBT(); openBT();
Otherwise, mmSocket.connect(); throws an exception, “Service discovery
failed”
but if I put findBT() in onCreate() and just use the button for
openBT(); it works fine.
Or, if I make a second button, one for each, it works fine.
Suggestions?"
the excerpts from the second comment:
Set pairedDevices = mBluetoothAdapter.getBondedDevices();
mmDevice = mBluetoothAdapter.getRemoteDevice(“00:06:66:46:5A:91″);
if (pairedDevices.contains(mmDevice))
{
statusText.setText(“Bluetooth Device Found, address: ” + mmDevice.getAddress() );
Log.d(“ArduinoBT”, “BT is paired”);
}
where I entered the address of my Bluetooth device. The original code
finds the device and returns the correct address, but
mmSocket.connect(); generates an exception “java.io.IOException:
Service discovery failed”
Suggestions?