Android MediaRecorder Crashes - java

UPDATED:
Ok, after a few days of testing and debugging... I GOT IT TO WORK, but not the way I want.
The reason it crashed previously was because of "reorientation" of the camera during lockscreen, apparently, that crashes often.
Once I forced it to use landscape mode, it works. However, I don't want it to use landscape mode; I want it to work in portrait mode.
The code is taken directly from Android Studio's sample (Media -> MediaRecorder). The sample had the code working in landscape mode, and I can't figure how to get it to use portrait mode so I can avoid re-orientation and thus avoid the crashes?
There's nothing in the onPause, onResume code and the stacktrace pointed toward this method being called.
Easy Reproduce:
1) Use Android Studio to get the MediaRecord Sample app
2) In the manifest, change, android:screenOrientation="landscape"> to Portrait.
3) The App won't launch now.
I added mCamera.setDisplayOrientation(90), same issue.
Code:
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private boolean prepareVideoRecorder(){
// BEGIN_INCLUDE (configure_preview)
mCamera = CameraHelper.getDefaultCameraInstance();
// We need to make sure that our preview and recording video size are supported by the
// camera. Query camera to find all the sizes and choose the optimal size given the
// dimensions of our preview surface.
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSizes,
mPreview.getWidth(), mPreview.getHeight());
// Use the same size for recording profile.
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
profile.videoFrameWidth = optimalSize.width;
profile.videoFrameHeight = optimalSize.height;
// likewise for the camera object itself.
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setParameters(parameters);
try {
// Requires API level 11+, For backward compatibility use {#link setPreviewDisplay}
// with {#link SurfaceView}
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
} catch (IOException e) {
Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
return false;
}
// END_INCLUDE (configure_preview)
// BEGIN_INCLUDE (configure_media_recorder)
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(profile);
// Step 4: Set output file
mMediaRecorder.setOutputFile(CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).toString());
mMediaRecorder.setOrientationHint(90);
// END_INCLUDE (configure_media_recorder)
MediaScannerConnection.scanFile(this, new String[] { CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).getPath() }, new String[] { "video/mp4" }, null);
// Step 5: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
Logs:
06-27 02:18:08.244 25734-25752/com.watchdawg.watchdawg E/MediaRecorder﹕ start failed: -22
06-27 02:18:08.253 25734-25752/com.watchdawg.watchdawg E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.watchdawg.watchdawg, PID: 25734
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:304)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.start(Native Method)
at com.watchdawg.watchdawg.RecordActivity$MediaPrepareTask.doInBackground(RecordActivity.java:276)
at com.watchdawg.watchdawg.RecordActivity$MediaPrepareTask.doInBackground(RecordActivity.java:267)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)

Whenever the application is removed from the recent task list, process will not be cleaned up completely, it is just that the UI will be cleaned up. So it is app responsibility to cleanup the resource held by your activity or app. Hence, you need to override onTaskRemoved() method in your service(Android service) component and perform cleanup(releasing mediaplayer instance etc).

try this way:
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoFrameRate(24);
mMediaRecorder.setVideoSize(720,480);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mPreview.setRotation(90);
instead of mMediaRecorder.setProfile(profile);
hope it works!

Related

BluetoothDevice.getUuids() returns null

I am currently working on an app which requires a Bluetooth laser meter. So i tried a few lines of code and went through a loads of failures. The last error I get is an NPE because i try to access the array returned by getUuids().
I also tried to connect the app to my airPods and everything worked well.
I am at minSdk 27 and targetSdk 31
All bluetooth permissions (bluetooth, bluetooth_admin) are granted.
the fact is, the laser thing requires an app to work and i wonder if the constructor could have blocked some functionalities. if so, i'll look to buy another one from another brand, if someone could provide me a link to buy a device working for my app.
Here's my bluetooth connect code (pretty generic I guess)
I also tried the static UUID suggested in this post but i now get this socket error which (i think) mean the uuid's not working either:
BluetoothAdapter blueAdapter = BluetoothAdapter.getDefaultAdapter();
if (blueAdapter != null) {
if (blueAdapter.isEnabled()) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
Const.requestAllAppPermissions(this);
return;
}
Set<BluetoothDevice> bondedDevices = blueAdapter.getBondedDevices();
if (bondedDevices.size() > 0) {
Object[] devices = bondedDevices.toArray();
BluetoothDevice device = (BluetoothDevice) devices[0];
System.out.println(device.getName());
if (device.fetchUuidsWithSdp()) {
ParcelUuid[] uuids = device.getUuids();
BluetoothSocket socket = null;
try {
//socket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid());
socket = device.createRfcommSocketToServiceRecord(
UUID.fromString("00001101-0000-1000-8000-00805f9b54fb"));
socket.connect();
} catch (IOException e) {
e.printStackTrace();
}
}
//outputStream = socket.getOutputStream();
// inStream = socket.getInputStream();
} else {
}
} else {
System.out.println("bluetooth disabled");
}
} else {
System.out.println("No bluetooth built-in");
}
here's the static UUID stacktrace:
W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
W/System.err: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
W/System.err: at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:920)
W/System.err: at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:934)
W/System.err: at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:494)
W/System.err: at com.adici.activities.PlanActivity.lambda$defButton$13$com-adici-activities-PlanActivity(PlanActivity.java:409)
W/System.err: at com.adici.activities.PlanActivity$$ExternalSyntheticLambda10.onClick(Unknown Source:2)
W/System.err: at android.view.View.performClick(View.java:7346)
W/System.err: at android.view.View.performClickInternal(View.java:7312)
W/System.err: at android.view.View.access$3200(View.java:846)
W/System.err: at android.view.View$PerformClick.run(View.java:27794)
W/System.err: at android.os.Handler.handleCallback(Handler.java:873)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
W/System.err: at android.os.Looper.loop(Looper.java:214)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7100)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
I'm open to any suggestion
Looking at the user manual for the Leica DISTO D2 it states the device uses Bluetooth Smart, also known as Bluetooth Low Energy (BLE). You won't be able to connect to it using Bluetooth Sockets (Bluetooth Classic).
Please follow the Android documentation on BLE to develop your app. To debug the connection beforehand, please install a generic BLE scanner such as nRF Connect and investigate the services and characteristics the device offers.

Android Fido2PendingIntent().launchPendingIntent fail first time, and works successive times

Why does Google's Fido2PendingIntent().launchPendingIntent method fail (no fingerprint/passcode prompt is displayed) on the first attempt with the error code:
SECURITY_ERR - The operation is insecure. The incoming request cannot be validated.
And, successive attempts typically result in the the above call working (fingerprint/passcode is prompt displayed), and no longer getting this error.
These are the main snippets of the code:
ListenerRegistration.java:
try {
// Get intent for FIDO2 operation.
Fido2ApiClient fido2ApiClient = Fido.getFido2ApiClient( this.activity );
Task<Fido2PendingIntent> task = fido2ApiClient.getRegisterIntent( pkcco );
// Send intent back to UI through callback.
Log.d( TAG, "LISTENERREGISTRATION.java IS NOW ATTEMPTING TO OPEN FINGERPRINT/SECRUITY PROMPT" );
this.fidoDelegate.launchFidoPrompt( Tasks.await( task ), FidoPromptCallback.FIDO2_REGISTRATION );
// Wait for authenticator to complete.
this.fidoAuthenticatorLock.acquire();
} catch( ExecutionException e ) {
// Threw exception while waiting for authenticator.
// Pass Fido2AuthenticatorException back to calling class so it can handle error appropriately.
throw new Fido2AuthenticatorException( this.sFido2AuthenticatorErrorMessage, this.fido2ErrorCode );
} catch( InterruptedException e ) {
// Threw exception while waiting for authenticator.
// Pass Fido2AuthenticatorException back to calling class so it can handle error appropriately.
throw new Fido2AuthenticatorException( this.sFido2AuthenticatorErrorMessage, this.fido2ErrorCode );
}
MainActivity.java:
// Instantiate class to handle VC functionality called by listener.
this.lo = new ListenerOperations(MainActivity.this, new FidoPromptCallback() {
#Override
public void launchFidoPrompt(Fido2PendingIntent fido2Intent, int iOperation) {
// Determine how to handle authenticator result.
int iCode;
if (iOperation == FidoPromptCallback.FIDO2_REGISTRATION) {
iCode = MainActivity.REQUEST_FIDO2_REGISTER;
} else if (iOperation == FidoPromptCallback.FIDO2_ASSERTION) {
iCode = MainActivity.REQUEST_FIDO2_ASSERTION;
} else {
// Invalid operation.
iCode = -1;
}
try {
// Launch the fingerprint dialog by launching the intent from FIDO2 API.
Log.d( TAG, "MAINACTIVITY.java IS NOW ATTEMPTING TO OPEN FINGERPRINT/SECRUITY PROMPT" );
fido2Intent.launchPendingIntent( MainActivity.this, iCode );
Log.d( TAG, "MAINACTIVITY.java HAS OPENNED FINGERPRINT/SECRUITY PROMPT WITH NO ERRORS" );
} catch( IntentSender.SendIntentException e ) {
// Error launching pending intent for register request.
Log.d(TAG, "SADFACE - FAILED TO OPEN FINGERPRINT FIDO DIALOG");
} catch (Exception e) {
Log.d( TAG, "GENERAL EXCEPTION OCCURRED WHEN CALLING fido2Intent.launchPendingIntent" );
e.printStackTrace();
}
Log.d( TAG, "MAINACTIVITY.java END OF launchFidoPrompt()" );
}
On failure (and success) the logs look like this (because no exception is ever thrown even after getting the SECURITY_ERR error):
other logs
...
10-01 10:31:36.289 14272 15728 D MainActivity.java: LISTENERREGISTRATION.java IS NOW ATTEMPTING TO OPEN FINGERPRINT/SECRUITY PROMPT
...
10-01 10:31:37.589 14974 15728 D MainActivity.java: MAINACTIVITY.java IS NOW ATTEMPTING TO OPEN FINGERPRINT/SECRUITY PROMPT
10-01 10:31:37.602 4053 4953 I ActivityManager: START u0 {act=null typ=null flg=0x0 cmp=ComponentInfo{com.google.android.gms/com.google.android.gms.fido.fido2.ui.Fido2FullScreenActivity}} from uid 10031
10-01 10:31:37.623 4053 4953 D CustomFrequencyManagerService: acquireDVFSLockLocked : type : DVFS_MIN_LIMIT frequency : 1560000 uid : 1000 pid : 4053 pkgName : AMS_APP_SWITCH#CPU_MIN#47
10-01 10:31:37.625 4053 4953 D ActivityManagerPerformance: AMP_acquire() APP_SWITCH
10-01 10:31:37.628 3633 3633 I SurfaceFlinger: id=56380 createSurf (3040x3040),2 flag=4, AppWindowToken{2800ead token=Token{77b3fc4 ActivityRecord{44bad7 u0 com.google.android.gms/.fido.fido2.ui.Fido2FullScreenActivity t7062}}}#0
10-01 10:31:37.636 4053 4953 D ActivityManager: Received ACTIVITY intent in key u0 {bcd25e2 act=nullstartActivity cmp=ComponentInfo{com.google.android.gms/com.google.android.gms.fido.fido2.ui.Fido2FullScreenActivity} res=0} from uid 10218
10-01 10:31:37.637 14974 15728 D MainActivity.java: MAINACTIVITY.java HAS OPENNED FINGERPRINT/SECRUITY PROMPT WITH NO ERRORS
10-01 10:31:37.637 14974 15728 D MainActivity.java: MAINACTIVITY.java END OF launchFidoPrompt()
The fact that my code does not get notified of any exceptions, leads me to believe that the issue lies inside the call to Fido2PendingIntent().launchPendingIntent.
Note that now exceptgion in this code:

Is there a way to write just a byte in BLE characteristic?

I am new to android. My BLE device expects only one byte(flag). I tried writing only one byte in a byte array but it never works. While writing an array to another characteristic where it expects 2 bytes works. Is there a way to solve my problem or do I have to ask for device code to be changed?
I am working with this project as my example
public void writeCustomCharacteristicStart() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("00001813-0000-1000-8000-00805f9b34fb"));
if(mCustomService == null){
Log.w(TAG, "Custom BLE Service not found");
return;
}
/*get the read characteristic from the service*/
byte pom= 1;
byte[] data= new byte[1];
data[0]=pom;
BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString("00002a4e-0000-1000-8000-00805f9b34fb"));
if((mWriteCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE)>0 ) {
Log.w(TAG,"Writing started");
mWriteCharacteristic.setValue(data)
}
if(!mBluetoothGatt.writeCharacteristic(mWriteCharacteristic)){
Log.w(TAG, "Failed to write characteristic");
}
Log.w(TAG,"Writing ending");
}
08-06 11:59:57.700 29279-29279/com.example.devicescanactivity E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.devicescanactivity, PID: 29279
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:4084)
at android.view.View.performClick(View.java:4858)
at android.view.View$PerformClick.run(View.java:20167)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5931)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:987)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.view.View$1.onClick(View.java:4079)
at android.view.View.performClick(View.java:4858) 
at android.view.View$PerformClick.run(View.java:20167) 
at android.os.Handler.handleCallback(Handler.java:815) 
at android.os.Handler.dispatchMessage(Handler.java:104) 
at android.os.Looper.loop(Looper.java:194) 
at android.app.ActivityThread.main(ActivityThread.java:5931) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:987) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782) 
Caused by: java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission: Neither user 10097 nor current process has android.permission.BLUETOOTH_PRIVILEGED.
at android.os.Parcel.readException(Parcel.java:1549)
at android.os.Parcel.readException(Parcel.java:1502)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.writeCharacteristic(IBluetoothGatt.java:1003)
at android.bluetooth.BluetoothGatt.writeCharacteristic(BluetoothGatt.java:1029)
at com.example.devicescanactivity.BluetoothLeService.writeCustomCharacteristic(BluetoothLeService.java:377)
at com.example.devicescanactivity.DeviceControlActivity.onClickWrite(DeviceControlActivity.java:332)
Here is the error, I don't get the BLUETOOTH_PRIVILEGED error, but I don't get any errors when I write to the characteristic that accepts 2 bytes.
First, to use bluetooth in your app, you need to add the following permissions to your app manifest :
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
It is possible to write a 1 byte value to a BLE characteristic, provided the device expects a 1 byte value.
If there is a length issue, you should see the error in the onCharacteristicWrite() callback:
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.i("TAG", "onCharacteristicWrite() status: " + status + " - UUID: " + characteristic.getUuid());
} else if (status == BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH) {
Log.e("TAG", "onCharacteristicWrite() A write operation failed due to invalid attribute length");
} else {
Log.e("TAG", "onCharacteristicWrite() A write operation failed. Status = " + status);
}
}
Also, I would move the writeCharacteristic() call inside your check for PROPERTY_WRITE to ensure the write operation can be done:
if((mWriteCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0 ) {
Log.i(TAG,"Writing started");
mWriteCharacteristic.setValue(data)
if(!mBluetoothGatt.writeCharacteristic(mWriteCharacteristic)){
Log.e(TAG, "Failed to write characteristic");
}
}
The problem wasn't in what I write in the characteristic it was what characteristic I used. I used HID Control Point which when tested on the computer nRF Connect app worked fine for my device but it would not work on android because of its predefined states. We just changed characteristic to Record Access Control Point and it works for now.

nullpointerexception error. trying to connect to the bitcoin server from my phone

I am fairly new to android, java, and mainly jsonrpc...
I have been stuck on this error for some time and i dont know if it is how i have coded it that is causing the issue or if i am trying to connect to the wrong server...
If you could help, it would be GREATLY appreciated.
here is the error code and the important code:
09-08 12:36:12.141: W/System.err(30361): Network exception: failed to connect to /10.10.11.75 (port 18332): connect failed: ECONNREFUSED (Connection refused)
09-08 12:36:12.151: W/dalvikvm(30361): threadid=11: thread exiting with uncaught exception (group=0x417df2a0)
09-08 12:36:12.151: E/AndroidRuntime(30361): FATAL EXCEPTION: AsyncTask #1
09-08 12:36:12.151: E/AndroidRuntime(30361): java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NullPointerException
at com.bitcoinapp.MainActivity.connect(MainActivity.java:219
at com.bitcoinapp.MainActivity.access$0(MainActivity.java:157)
at com.bitcoinapp.MainActivity$BitcoinConnect.doInBackground(MainActivity.java:143)
at com.bitcoinapp.MainActivity$BitcoinConnect.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-08 12:36:12.151: E/AndroidRuntime(30361): ... 5 more
this is the android code that i am using at the moment... all of which is run once the user presses the button on the application. I am working off my SAMSUNG S3 MINI and not an emulator.
I have had to omit some of the content, so showing line numbers wont help, but i have added in the ones that i think are important...
class Connection implements OnClickListener {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
new BitcoinConnect().execute();
}
}
private class BitcoinConnect extends AsyncTask<String, Integer, Object[]> {
#Override
protected Object[] doInBackground(String... params) {
// TODO Auto-generated method stub
connect();
return null;
}
}
public class BasicAuthenticator implements ConnectionConfigurator {
public void configure(HttpURLConnection connection) {
// add custom HTTP header
connection.addRequestProperty("myusername", "mypassword");
}
}
private void connect() { //(line 157)
//This is the code for the JSONRPC2-CLIENT iteraction
// The JSON-RPC 2.0 server URL
URL serverURL = null;
try {
serverURL = new URL("http://10.10.11.75:18332");
} catch (MalformedURLException e) {
// handle exception...
e.printStackTrace();
}
// Create new JSON-RPC 2.0 client session
JSONRPC2Session mySession = new JSONRPC2Session(serverURL);
mySession.setConnectionConfigurator(new BasicAuthenticator());
//This is for the bitcoin BASE interaction.
//for the Bitcoin Payment Request
String method = "getinfo";
Map<String,Object> params = new HashMap<String,Object>();
String id = "Request001";
JSONRPC2Request payment = new JSONRPC2Request(method, params, id);
String jsonString = payment.toString();
JSONRPC2Response response = null;
Log.i("Failed0", "Failed0");
try {
response = mySession.send(payment);
Log.i("response", String.valueOf(response));
mTextView.setText((CharSequence) response);
} catch (JSONRPC2SessionException e) {
System.err.println(e.getMessage());
// handle exception...
Log.i("response", String.valueOf(response));
}
// Print response result / error
if (response.indicatesSuccess()) { //(line 219)
System.out.println(response.getResult());
} else {
System.out.println(response.getError().getMessage());
}
}
I am using the JSONRPC2.0 libraries for the base code and the client code. I am trying to connect to the bitcoin testnet server. The IP there is one of many that i have tried...
I know that testnet is on port 18332 and the mainnet is 8332...
ive tried a localhost IP and that hasnt worked either.
I dont know if there is suppose to be other code that i must use in order for my phone to connect to the bitcoin server...
Please help me, thanks in advance
Lets apply some logical thinking.
According to the stack trace, the NullPointerException was thrown here:
if (response.indicatesSuccess()) {
That means response was null. (No other alternative!)
That means that the send call in
response = mySession.send(payment);
EITHER returned assigned null to response, OR it through a JSONRPC2SessionException that you caught.
I suspect it was the latter, and that the message "Network exception: failed to connect to /10.10.11.75 (port 18332): ..." was logged in the process. However, the evidence is not convincing. (There aren't any "I/..." lines in the logcat output ...)
In summary, what you have done is catch the exception that told you that the send has failed, and then proceed to try to process the non-existent response!
The underlying problem is that you app cannot connect to 10.10.11.75 on port 18332. I assume that you realize that 10.10.11.75 is a private IP address, and hence that you will only be able to connect to it if the server is on your local network.

Java.io.IOException, "bad file number" USB connection

I'm setting up a USB accessory connection between my Android phone and another device. Just sending bytes back and forth for now to test. I get some definite communication going at first, but it always ends up dying with Java.io.IOException: write failed: EBADF (Bad file number)" after a second or so. Sometimes the reading stays alive but the writing dies; others both die.
I'm not doing anything super fancy, reading and writing just like the Google documentation:
Initial connection (inside a broadcast receiver, I know this part works at least initially):
if (action.equals(ACTION_USB_PERMISSION))
{
ParcelFileDescriptor pfd = manager.openAccessory(accessory);
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
mIn = new FileInputStream(fd);
mOut = new FileOutputStream(fd);
}
}
Reading:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
byte[] buf = new byte[BUF_SIZE];
while (true)
{
try {
int recvd = mIn.read(buf);
if (recvd > 0) {
byte[] b = new byte[recvd];
System.arraycopy(buf, 0, b, 0, recvd);
//Parse message
}
}
catch (IOException e) {
Log.e("read error", "failed to read from stream");
e.printStackTrace();
}
}
}
});
thread.start();
Writing:
synchronized(mWriteLock) {
if (mOut !=null && byteArray.length>0) {
try {
//mOut.flush();
mOut.write(byteArray, 0, byteArray.length);
}
catch (IOException e) {
Log.e("error", "error writing");
e.printStackTrace();
return false;
}
}
else {
Log.e(TAG, "Can't send data, serial stream is null");
return false;
}
}
Error stacktrace:
java.io.IOException: write failed: EBADF (Bad file number)
W/System.err(14028): at libcore.io.IoBridge.write(IoBridge.java:452)
W/System.err(14028): at java.io.FileOutputStream.write(FileOutputStream.java:187)
W/System.err(14028): at com.my.android.transport.MyUSBService$5.send(MyUSBService.java:468)
W/System.err(14028): at com.my.android.transport.MyUSBService$3.onReceive(MyUSBService.java:164)
W/System.err(14028): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:781)
W/System.err(14028): at android.os.Handler.handleCallback(Handler.java:608)
W/System.err(14028): at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err(14028): at android.os.Looper.loop(Looper.java:156)
W/System.err(14028): at android.app.ActivityThread.main(ActivityThread.java:5045)
W/System.err(14028): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err(14028): at java.lang.reflect.Method.invoke(Method.java:511)
W/System.err(14028): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
W/System.err(14028): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
W/System.err(14028): at dalvik.system.NativeStart.main(Native Method)
W/System.err(14028): Caused by: libcore.io.ErrnoException: write failed: EBADF (Bad file number)
W/System.err(14028): at libcore.io.Posix.writeBytes(Native Method)
W/System.err(14028): at libcore.io.Posix.write(Posix.java:178)
W/System.err(14028): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
W/System.err(14028): at libcore.io.IoBridge.write(IoBridge.java:447)
W/System.err(14028): ... 13 more
I have logging all over the place and thus I know it's not anything too obvious, such as another permission request being received (and thus the file streams being reinitialized mid-read). The streams aren't closing either, because I never have that happen anywhere in my code (for now). I'm not getting any detached or attached events either (I log that if it happens). Nothing seems too out of the ordinary; it just dies.
I thought maybe it was a concurrency issue, so I played with locks and sleeps, nothing worked that I tried. I don't think it's a throughput issue either because it still happens when I sleep every read (on both ends), and read one single packet at a time (super slow bitrate). Is there a chance the buffer is being overrun on the other end somehow? How would I go about clearing this? I do have access to the other end's code, it is an Android device as well, using Host mode. In case that it matters, I can post that code too - standard bulk transfers.
Does the phone just have lackluster support for Android Accessory Mode? I've tried two phones and they both fail similarly, so I doubt it's that.
I'm wondering what causes this error in general when writing or reading from USB on Android?
I got same problem in my code, and I found that it happens because FileDescriptor object was GCed.
I fixed this issue by adding ParcelFileDescriptor field in Activity(or Service).
I checked your first code snippet and the code you based on, and latter has ParcelFileDescriptor field in Thread.
I think if you edit your code like below, it works well.
ParcelFileDescriptor mPfd;
...
if (action.equals(ACTION_USB_PERMISSION))
{
mPfd = manager.openAccessory(accessory);
if (mPfd != null) {
FileDescriptor fd = mPfd.getFileDescriptor();
mIn = new FileInputStream(fd);
mOut = new FileOutputStream(fd);
}
}
It ended up being a threading issue. I needed to more properly segregate even writing as well, instead of just reading.
I ended up using this code as a basis.
OK, a few things I noticed that just seemed different from what I do for Open Accessory Mode, which I followed the documentation for USB accessory mostly, so it should be very similar, is that your mIn.read(buf); should be mIn.read(buf, 0, 64); as far as I know.
Also, you should declare in your class declarations thread myThread;. Then within your BroadcastReceiver after creating the new FileInput/OutputStream, have myThread = new thread(myHandler, myInputStream); followed my myThread.start();.
Now I noticed that you are communicating directly with the UI from your thread. You should use a handler instead that the thread will communicate to and then that will communicate back to your UI, at least from what I had read.
Here is an example of my handler and thread:
final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg){
}
};
private class USB_Thread extends Thread {
Handler thisHandler;
FileInputStream thisInputStream;
USB_Thread(Handler handler, FileInputStream instream){
thisHandler = handler;
thisInputStream = instream;
}
#Override
public void run(){
while(true) {
try{
if((thisInputStream != null) && (dataReceived == false)) {
Message msg = thisHandler.obtainMessage();
int bytesRead = thisInputStream.read(USB_Data_In, 0, 63);
if (bytesRead > 0){
dataReceived = true;
thisHandler.sendMessage(msg);
}
}
}
catch(IOException e){
}
}
}
}
Also, there are some demo open accessory application here. They may help with your understanding of accessory mode.
And also there are known issues with an application not receiving the BroadcastReceiver for ACTION_USB_ACCESSORY/DEVICE_ATTACHED programmatically. It will only receive it via the manifest file. You can find more on this here and here.
I actually didn't test putting the dataReceived variable in the handler and only recently changed that part of my code. I tested it and it didn't work, so trying to remember what it was I had read, I think it was not about variables communicating within the threads, but trying to use something like .setText(). I have updated my code to include the dataReceived=true in the thread. The handler would then be used for updating items on the UI, such as TextViews, etc.
Thread
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
usbThread = new USB_Thread(mHandler, mInputStream);
usbThread.start();

Categories