BluetoothDevice.getUuids() returns null - java

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.

Related

How can you execute a repeating JSoup task which will work even if the app is in background in android

For my app I need values which are parsed by jSoup from a website and then returned to the user using a notification, these values change ~ every minute, so to be up-todate with the values I set up a task using a handler, this works good when the app is in foreground, but as soon as the user goes to the homescreen the app will return multiple exceptions like e.g. java.net.UnknownHostException or java.net.SocketTimeoutException, in the code this happens when jSoup is connecting to the specified site, I already tried using Services and AsyncTasks instead of threads, but it was always the exact same problem, I also searched for people with similar experiences, but I guess my issue is quite specific.
This is the code for the handler:
private final static int INTERVAL = 1000 * 60;
Handler mHandler = new Handler();
Runnable mHandlerTask = new Runnable()
{
#Override
public void run() {
try {
wakeLock.release();
} catch (RuntimeException e) {
e.printStackTrace();
}
if (!isUpdating) {
isUpdating = true;
App.shouldUpdate = true;
System.out.println("update");
final TinyDB tinydb = new TinyDB(getApplicationContext());
TextView priceEditText = loadedLayouts.get(1).findViewById(R.id.priceTextView);
TextView increaseEditText = loadedLayouts.get(1).findViewById(R.id.increaseTextView);
updatePricesStock(tinydb.getString("current_isin"), priceEditText, increaseEditText);
}
wakeLock.acquire(2*60*1000L /*10 minutes*/);
}
mHandler.postDelayed(mHandlerTask, INTERVAL);
}
}
};
and this is the code for the updateStockPrices method (I will not include updatePricesWarrant and updatePricesKnockout since they are essentially doing the same things and also throw the same exceptions)
public void updatePricesStock(final String ISIN, TextView priceText, TextView increaseText) {
final TinyDB tinydb = new TinyDB(getApplicationContext());
final Thread thread = new Thread(new Runnable() {
#Override
public void run() {
TinyDB tinydb = new TinyDB(getApplicationContext());
try {
Document doc = Jsoup.connect("https://www.ls-tc.de/de/aktie/" + ISIN).get();
System.out.println(ISIN);
increase = doc.selectFirst("#page_content > div > div:nth-child(1) > div > div.mpe_bootstrapgrid.col-md-8 > div > div:nth-child(3) > div > span:nth-child(3)").text().replace(" ", "");
tinydb.putString(ISIN + "notification_price", doc.selectFirst("#page_content > div > div:nth-child(1) > div > div.mpe_bootstrapgrid.col-md-8 > div > div:nth-child(3) > div > span:nth-child(1)").text() + "€");
} catch (IOException e) {
e.printStackTrace();
tinydb.putString(ISIN + "notification_price", "Error Scraping Price");
}
}
});
if(!thread.isAlive()) {
thread.start();
}
try{
thread.join();
}catch (Exception ex){
ex.printStackTrace();
}
if(!thread.isAlive()) {
notificationCompat = NotificationManagerCompat.from(getApplicationContext());
System.out.println("done");
System.out.println(tinydb.getString(ISIN + "notification_price"));
priceText.setText(tinydb.getString(ISIN + "notification_price"));
increaseText.setText(increase);
System.out.println("Text Updated " + priceText.getText().toString());
if(tinydb.getBoolean(ISIN + "_notification_status")) {
Notification notification = new NotificationCompat.Builder(getApplicationContext(), App.notificationChannel)
.setSmallIcon(R.drawable.ic_baseline_attach_money_24).setContentTitle(tinydb.getString(ISIN + "notification_name")).setContentText(tinydb.getString(ISIN + "notification_price")).setPriority(NotificationCompat.PRIORITY_MAX).setCategory(NotificationCompat.CATEGORY_STATUS).setOnlyAlertOnce(true).build();
notificationCompat.notify(tinydb.getInt(ISIN + "_notification_id"), notification);
}
isUpdating = false;
}
}
finnally these are the stacktraces I get:
W/System.err: java.net.SocketTimeoutException: timeout
W/System.err: at com.android.okhttp.okio.Okio$3.newTimeoutException(Okio.java:225)
at com.android.okhttp.okio.AsyncTimeout.exit(AsyncTimeout.java:263)
W/System.err: at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:217)
at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:317)
at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:311)
W/System.err: at com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:207)
W/System.err: at com.android.okhttp.internal.http.Http1xStream.readResponse(Http1xStream.java:388)
at com.android.okhttp.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:146)
W/System.err: at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:900)
at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:772)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:493)
W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:429)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:560)
W/System.err: at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:734)
W/System.err: at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:706)
W/System.err: at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:299)
W/System.err: at org.jsoup.helper.HttpConnection.get(HttpConnection.java:288)
at de.xliquid.stockwatchultimate.MainActivity$4.run(MainActivity.java:266)
W/System.err: at java.lang.Thread.run(Thread.java:919)
W/System.err: Caused by: java.net.SocketException: socket is closed
at com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:588)
at com.android.okhttp.okio.Okio$2.read(Okio.java:145)
at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:213)
W/System.err: ... 18 more
java.net.UnknownHostException: Unable to resolve host "www.onvista.de": No address associated with hostname
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:156)
W/System.err: at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
at java.net.InetAddress.getAllByName(InetAddress.java:1152)
at com.android.okhttp.Dns$1.lookup(Dns.java:41)
W/System.err: at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:178)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:144)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:86)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:192)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:144)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:106)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:400)
W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:333)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:483)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:429)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:560)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:734)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:706)
at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:299)
at org.jsoup.helper.HttpConnection.get(HttpConnection.java:288)
W/System.err: at de.xliquid.stockwatchultimate.MainActivity$6.run(MainActivity.java:371)
at java.lang.Thread.run(Thread.java:919)
W/System.err: Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
W/System.err: at libcore.io.Linux.android_getaddrinfo(Native Method)
W/System.err: at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:74)
at libcore.io.BlockGuardOs.android_getaddrinfo(BlockGuardOs.java:200)
at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:74)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:135)
W/System.err: ... 22 more
Also this app is solely for me so I don't really bother if the solution isn't the cleanest or drains the battery faster.
The problem was energy saving mode, if it is turned on the phone won't do requests in background / idle mode, no matter the wakelock, I solved my problem by adding a permission, so the app can request data even when the phone is in energy saving standby.

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.

Android bluetooth IOException: read failed, socket might closed or timeout, read ret: -1

I have a problem with connecting my client socket in the Android bluetooth API.
I already read these posts: this one, this one, this one and this one
According to these posts I made my code like the following but it still not work:
class MainActivity : AppCompatActivity()
{
private val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
private var connectThread: ConnectThread? = null
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (bluetoothAdapter != null)
{
if (!bluetoothAdapter.isEnabled)
bluetoothAdapter.enable()
val devices = bluetoothAdapter.bondedDevices.toTypedArray()
if (devices.isNotEmpty())
{
connectThread = ConnectThread(devices[0])
connectThread!!.run()
}
}
else
Log.i("BluetoothTest", "No bluetooth supported")
}
override fun onDestroy()
{
super.onDestroy()
connectThread!!.cancel()
}
private inner class ConnectThread(device: BluetoothDevice) : Thread()
{
//private val socket = device.createRfcommSocketToServiceRecord(UUID.fromString ("00001101-0000-1000-8000-00805F9B34FB"))
private val socket = device.javaClass.getMethod("createRfcommSocket", (Int::class
.javaPrimitiveType)).invoke(device, 2) as BluetoothSocket
override fun run()
{
bluetoothAdapter.cancelDiscovery()
socket.connect()
}
fun cancel()
{
socket.close()
}
}
}
Here is the logs with the returned error that comes on socket.connect():
--------- beginning of crash
05-15 15:59:19.553 24176-24176/com.bluetoothtest E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.bluetoothtest, PID: 24176
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bluetoothtest/com.bluetoothtest.MainActivity}: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:685)
at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:697)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:374)
at com.bluetoothtest.MainActivity.onCreate(MainActivity.kt:36)
at android.app.Activity.performCreate(Activity.java:6999)
at android.app.Activity.performCreate(Activity.java:6990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
It seems that the problem appeared after Android 4.3 because of the port value of the socket
I am on Android 7.1 and 8.1
Does someone knows how to make bluetooth work on Android ?
Finally, the root cause was because the socket's inputStream couldn't be read. That's because there was no open socket with the same UUID on the server side.
See https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r30/core/java/android/bluetooth/BluetoothSocket.java
So to fix the problem we need a listening socket with the same UUID on the other side, for me it was a raspberry in python:
from bluetooth import *
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "YOUR UUID"
advertise_service( server_sock, "SampleServer", service_id = uuid, service_classes = [ uuid, SERIAL_PORT_CLASS ], profiles = [ SERIAL_PORT_PROFILE ])
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")
from https://github.com/karulis/pybluez/blob/master/examples/simple/rfcomm-server.py

AccountManagerFuture issue

I want to retrieve an user token. This is my code:
AccountManager am = AccountManager.get(mActivity);
AccountManagerFuture<Bundle> bundleAccountManagerFuture = am.getAuthTokenByFeatures(ACCOUNT_TYPE, AUTHORIZATION_TOKEN_TYPE, null, mActivity, null, null, null, null);
try {
Bundle result = bundleAccountManagerFuture.getResult(30, TimeUnit.SECONDS);
if (result!=null) {
OTTCache.getInstance().authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
}
} catch (OperationCanceledException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (AuthenticatorException e) {
e.printStackTrace();
}
But the process stop in this line:
Bundle result = bundleAccountManagerFuture.getResult();
Some idea?
Thank you very much
Exception:
android.accounts.OperationCanceledException W/System.err: at
android.accounts.AccountManager$AmsTask.internalGetResult(AccountManager.java:1985)
W/System.err: at
android.accounts.AccountManager$AmsTask.getResult(AccountManager.java:1997)
W/System.err: at
android.accounts.AccountManager$AmsTask.getResult(AccountManager.java:1995)
W/System.err: at
com.fr.apps.cliente.tv.task.LoginTask.doInBackground(LoginTask.java:83)
W/System.err: at
com.fr.apps.cliente.tv.task.LoginTask.doInBackground(LoginTask.java:25)
W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:304)
W/System.err: at
java.util.concurrent.FutureTask.run(FutureTask.java:237) W/System.err:
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
W/System.err: at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
W/System.err: at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
W/System.err: at java.lang.Thread.run(Thread.java:761)
Using getResult() attempts to call on the variable, and the code continues immediately. I'm assuming you're trying to retrieve it from a server or something, rather than from being stored on the device? In that case you need to wait for .isDone() (android doc here) to become true before you process the result.
From Documentation of AccountManagerFuture for .getResult() method -
This
* call will block until the result is available. In order to check if the result is
* available without blocking, one may call {#link #isDone()} and {#link #isCancelled()}.
EDIT 1: You can use getResult(long timeout, TimeUnit unit) which will timeout after a specified time if the request is blocked. After this, you can check if task was successfully done or not using .isDone() and accordingly, proceed.
I found the problem:
The package name of my application do not match exactly with the package name of my other app (This app have the login). Now, i signed both with the same key.

Android AudioRecord fails to initialise(Other solutions not working)

I have checked and tried all the other threads for multiple hours today and none of the solutions work.
I have tried filtering through all avaible audio options. I have given the proper permissions to the app.
Goal: I am trying to get this audio stream so I can get the frequency of the audio.
My stuff
public int audioSource = MediaRecorder.AudioSource.MIC;
public int channelConfig = AudioFormat.CHANNEL_IN_MONO;
public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
public AudioRecord audioRecord = null;
private Thread recordingThread = null;
public int blockSize = 256; // deal with this many samples at a time
public int sampleRate = 8000; // Sample rate in Hz
later on...
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding);
AudioRecord audioeeeeRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); // The RAW PCM sample recording
audioRecord = audioeeeeRecord;
if (audioRecord != null && audioRecord.getState() != AudioRecord.STATE_INITIALIZED)
try {
throw new Exception("AudioRecord init failed"); //audioRecord = findAudioRecord();
} catch (Exception e) {
e.printStackTrace();
}
final short[] buffer = new short[blockSize];
try {
audioRecord.startRecording();
} catch (Exception e) {
e.printStackTrace();
}
This throws the following error (http://pastebin.com/raw/3wmA4cku):
AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.
W/System.err: java.lang.Exception: AudioRecord init failed
W/System.err: at app.mobile.mobileecg.MainActivity.startReading(MainActivity.java:102)
W/System.err: at app.mobile.mobileecg.MainActivity$1.onClick(MainActivity.java:58)
W/System.err: at android.view.View.performClick(View.java:5697)
W/System.err: at android.view.View$PerformClick.run(View.java:22526)
W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:158)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7229)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
W/System.err: java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
W/System.err: at android.media.AudioRecord.startRecording(AudioRecord.java:943)
W/System.err: at app.mobile.mobileecg.MainActivity.startReading(MainActivity.java:114)
W/System.err: at app.mobile.mobileecg.MainActivity$1.onClick(MainActivity.java:58)
W/System.err: at android.view.View.performClick(View.java:5697)
W/System.err: at android.view.View$PerformClick.run(View.java:22526)
W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:158)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7229)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Step 1) Check your manifest to ensure add RECORD_AUDIO permission under application section. e.g.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.colibri.audioloopback">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
Step 2) If your device is M or later, you need to grant the permssion from Settings->App->Your App->Permissions.
Step 3) Refer to below code snippet if still doesn't work.
public void audioRecordLoop() throws Exception {
Log.e(TAG,"start audioRecordLoop");
int channelConfig = mChannels == 2?
AudioFormat.CHANNEL_IN_STEREO:
AudioFormat.CHANNEL_IN_MONO;
int bufferSize = AudioRecord.getMinBufferSize(
mSampleRateHz, channelConfig, mAudioEncoding);
mAudioRecord = new AudioRecord(
mAudioSource, mSampleRateHz, channelConfig, mAudioEncoding, bufferSize);// The RAW PCM sample recording
if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
Log.e(TAG,"AudioRecord init failed");
return;
}
final short[] buffer = new short[mBlockSize];
mAudioRecord.startRecording();
int len = 0;
while (mbExit == false) {
len = mAudioRecord.read(buffer, 0, mBlockSize);
if (len < 0) {
Log.e(TAG,"read error " + len);
return;
}
}
mAudioRecord.stop();
mAudioRecord.release();
}
It should work now!
I think the problem may be that you had tied up the audio resources with a previous attempt, then got the code correct and now it doesn't work because there are no audio resources available. See this SO question. Also, you are throwing an exception when the constructor returns an uninitialized AudioRecord, but you catch your own exception and this results in a second exception (... called on uninitialized AudioRecord ...) in the log that can be ignored as it is a result of the first.
You might need to put some try/finally sections and/or an OnDestroy and or OnPause method in your activity to ensure that the audioRecord gets released when no longer used.
Once you have the cleanup code in place, you may need to kill off your app and/or reboot your phone to free the audio resources.
Of course it is possible that you left another app running that is holding the microphone but I doubt it.
This is the answer. It is stupid that this isn't something that android has.
https://stackoverflow.com/a/33769527/6530367
I know this is a very old question but in Android Marshmallow you have to go on "Settings > Apps > Your App > Permissions" and enble Microphone permission.

Categories