i am developing an android app, and this app need an information about ExternalStoarage State(this mean, USB, Not a SdCard).
so i thought this code could get a USB Mounted State
Environment.getExternalStorageState()
But it always return about SdCard. I don't know how to access to USB Storage in Android Device. but almost Android device is a Phone so i cannot find about my case
Here is a code block from the official Android guide:
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
..
val deviceList: HashMap<String, UsbDevice> = manager.deviceList
deviceList.values.forEach { device ->
//your code
}
private lateinit var bytes: ByteArray
private val TIMEOUT = 0
private val forceClaim = true
...
device?.getInterface(0)?.also { intf ->
intf.getEndpoint(0)?.also { endpoint ->
usbManager.openDevice(device)?.apply {
claimInterface(intf, forceClaim)
bulkTransfer(endpoint, bytes, bytes.size, TIMEOUT) //do in another thread
}
}
}
It will help you to find your USB connected device and communicate with it. Please check the link above for more information.
Related
I encountered a strange problem when trying to unpair and pair again with my smartphone. Currently I write a C# application on UWP (Windows 10) for BLE connection with a remote device. I use my smartphone with nRF Connect App as the peripheral.
After being paired for a while (and being inactive), when unpairing and pairing again, the application gets stuck when trying to pair again.
I broke everything down to the most basal application I could create. This is a Console App that scans the existing devices and then unpairs and pairs with the selected device:
using BLE_Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
Dictionary<ulong, string> uuidDict = BleModule.Scan().Result;
Console.WriteLine("Devices found:");
int i = 0;
foreach (var uuid in uuidDict.Keys)
Console.WriteLine(string.Format("ID: {0}, UUID: {1}, Local Name: {2}", i++, uuid, uuidDict[uuid]));
Console.WriteLine("Select ID!");
int id = int.Parse(Console.ReadLine());
ulong selectedUuid = (uuidDict.ElementAt(id)).Key;
await BleModule.Unpair(selectedUuid);
await BleModule.Pair(selectedUuid);
Console.ReadLine();
}
}
}
It calls an UWP DLL called "BLE_Test" with the class "BleModule":
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
namespace BLE_Test
{
public class BleModule
{
public static async Task<Dictionary<ulong, string>> Scan()
{
var uuidDict = new Dictionary<ulong, string>();
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += (BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
=> AddAdvertisement(eventArgs, uuidDict);
watcher.Start();
await Task.Delay(10000);
watcher.Stop();
return uuidDict;
}
private static void AddAdvertisement(BluetoothLEAdvertisementReceivedEventArgs eventArgs, Dictionary<ulong, string> uuidDict)
{
if (uuidDict.ContainsKey(eventArgs.BluetoothAddress) == false)
uuidDict.Add(eventArgs.BluetoothAddress, eventArgs.Advertisement.LocalName);
}
public static async Task Pair(ulong uuid)
{
Console.WriteLine("Pairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested += (DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) => args.Accept(); // We auto-accept numeric comparison result for the sake of simplicity
DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmPinMatch);
Console.WriteLine("Pairing Result: " + result.Status.ToString());
}
public static async Task Unpair(ulong uuid)
{
Console.WriteLine("Unpairing...");
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
if (bluetoothLEDevice == null)
{
Console.WriteLine("UUID not found!");
return;
}
DeviceUnpairingResult result = await bluetoothLEDevice.DeviceInformation.Pairing.UnpairAsync();
Console.WriteLine("Unpairing Result: " + result.Status.ToString());
}
}
}
If I start the program for the first time, the pairing works fine (the unpairing will be ignored as the devices are not paired yet). If I start it immediately again afterwards, it also works fine. Unpairing and pairing will both take place. But if I wait a while (typically 5-10 minutes) while not doing anything, when I start the program again, it will unpair, but then it will wait indefinitely for PairAsync() to return. No coupling request will show on the nRF Connect App, and no PairingRequested event will appear.
Aborting the stuck program and restarting it won't help. In this case, even though the smartphone is found by the BluetoothLEAdvertisementWatcher, BluetoothLEDevice.FromBluetoothAddressAsync(uuid) will return null and the device can't be paired anymore. This can only be resolved by restarting the computer or switching off and on the advertisement in the nRF Connect App, as in this case a new random BLE Address is created for the device.
I have taken a snapshot of the BLE events using Btetlparse and Wireshark. It seems that there is a problem with a malformed package:
However, I don't really understand what is going wrong. Is this a problem of the nRF Connect App? Or the UWP commands? Or did I do something wrong? I tried two different smartphones (a Samsung Galaxy and an Oppo), so I doubt that it is a problem of the smartphone. I also added a DeviceWatcher, but this didn't change anything. Can anyone help me here?
Trying to send esp32 chip wifi credentials from android app (built with ionic). Using Ionic capacitor/bluetooth-le plug in to write to esp32, using the write function:
await BleClient.write(device.deviceId, GATT Service ID, Characteristic ID, textToDataView('wifi_ssid,wifi_password'));
Code for BleClient.write:
async write(deviceId: string, service: string, characteristic: string, value: DataView): Promise<void> {
service = validateUUID(service);
characteristic = validateUUID(characteristic);
return this.queue(async () => {
if (!value?.buffer) {
throw new Error('Invalid data.');
}
let writeValue: DataView | string = value;
if (Capacitor.getPlatform() !== 'web') {
// on native we can only write strings
writeValue = dataViewToHexString(value);
}
await BluetoothLe.write({
deviceId,
service,
characteristic,
value: writeValue,
});
});
}
How to pass wifi credentials as value argument to the write function so it's correctly received by ESP32?
On the ESP32 side, I'm using the wifi_prov_mgr example code, which in turn uses google protocol buffer (I'm very new to protobuf and don't really understand how it works). ESP uses wifi_config.c (Espressif wifi_provisioning component). When I send wifi credentials from the app using BleClient.write, it shows up in wifi_config.c as inbuf with value wifi_ssid,wifi_password:��Z�?�Z�?
Here's the relevant code for wifi_config.c:
esp_err_t wifi_prov_config_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, uint8_t **outbuf, ssize_t *outlen, void *priv_data)
{
ESP_LOGI(TAG ,"Wifi config payload inbuf value: %s", inbuf);
WiFiConfigPayload *req;
WiFiConfigPayload resp;
esp_err_t ret;
req = wi_fi_config_payload__unpack(NULL, inlen, inbuf);
if (!req) {
ESP_LOGE(TAG, "Unable to unpack config data");
return ESP_ERR_INVALID_ARG;
}
I'm having a very hard time understanding how wi_fi_config_payload_unpack processes the inbuf argument. This is where the code gets into protobuf code generated by the proto files. The proto file for wifi config data looks like this:
message CmdSetConfig {
bytes ssid = 1;
bytes passphrase = 2;
bytes bssid = 3;
int32 channel = 4;
}
message WiFiConfigPayload {
WiFiConfigMsgType msg = 1;
oneof payload {
CmdGetStatus cmd_get_status = 10;
RespGetStatus resp_get_status = 11;
CmdSetConfig cmd_set_config = 12;
RespSetConfig resp_set_config = 13;
CmdApplyConfig cmd_apply_config = 14;
RespApplyConfig resp_apply_config = 15;
}
}
So my question is - how do I pass the wifi credentials in BleClient.write so it is correctly recognized by wifi_config.c on the ESP32 side?
I thought about using the Android app developed by Espressif to pass wifi credentials to the ESP32 chip, but then I don't know how to integrate native Android code with ionic code, since I need my app to do more than just credential the ESP32.
Resolved this issue by using Google's protocol buffer code for javascript. Here's code that worked for me:
import * as goog from 'google-protobuf';
export class SetupPage implements OnInit {
messages = require('../../assets/proto-js/wifi_config_pb.js');
connectedDevice: BleDevice;
bleScan: any;
wifiSSID: Promise<any>;
scanResults: Promise<[]>;
wifiCredentials: string;
uint8String: Uint8Array;
buffer: Uint8Array;
ngOnInit() {
async getBLE(){
await BleClient.initialize();
var cmdSetMessage = new this.messages.CmdSetConfig();
var wifiConfigPayloadMessage = new this.messages.WiFiConfigPayload;
message.setSsid('wifiid');
message.setPassphrase('password');
wifiConfigPayloadMessage.setCmdSetConfig(cmdSetMessage);
wifiConfigPayloadMessage.setMsg(2); //this is ESP32 BLE specific
let bytesOfStuff = await wifiConfigPayloadMessage.serializeBinary();
this.connectedDevice = await BleClient.requestDevice();
await BleClient.connect(this.connectedDevice.deviceId);
BleClient.writeWithoutResponse(this.connectedDevice.deviceId, '021a9004-0382-
4aea-bff4-6b3f1c5adfb4', '021aff52-0382-4aea-bff4-6b3f1c5adfb4',
bytesOfStuff)
//After this, you need to send wifiConfigPayloadMessage.setMsg(4) to ESP32 to apply wifi credentials and connect to the selected wifi
}
}
Before this code can function, you need to install google-protobuf from npm or other package installer and protoc or another compiler for the proto files in order to generate pb.js files (since I'm working with javascript) for each proto file. In this example, the proto file is called wifi_config.proto, and the corresponding pb.js file (created by running protoc) is called wifi_config_pb.js.
Functions used to create the data to be transferred are defined in the pb.js files and correspond to objects defined in the proto files. The following references will help a lot if you don't have a good understanding of how this mechanism works:
https://developers.google.com/protocol-buffers/docs/proto3 (google protocol-buffer tutorial)
Protocol Buffers in Ionic (stack question)
I'm developing an application to pair with two kind of sensors with the app and also these sensors are pairing with each other, we developed our custom bluetooth communication protocol. The connection is working great usually, but there are still some errors that I'm having hard time to fix it.
Sensor 1 paring alone is working great, but every time I'm pairing both of them, then i close the app, pair it again with first sensor, I got disconnected with status 19 just after the connection is established, after I try again one or two times the connection will be established properly. I was thinking that was a problem with Gatt refresh, but I already tried one solution found here and I keep reproducing this error every time.
fun connectToDevice(device: BraincareDevice, pairColor: Int) {
BleLogHelper.writeLog("Connecting to ${device.name}")
isConnecting = true
val deviceType = if (device is Sensor) DeviceType.SENSOR else DeviceType.DONGLE
if (deviceType == DeviceType.SENSOR) {
sensorConnectionSubscription?.dispose()
} else {
dongleConnectionSubscription?.dispose()
}
val connectionSubscription = device.device.establishConnection(false)
.flatMapSingle { connection ->
if (device is Sensor) {
sensorConnection = connection
connectedSensor = device
} else if (device is Dongle) {
dongleConnection = connection
connectedDongle = device
}
connection.queue(CustomRefresh())
?.observeOn(Schedulers.io())
?.doOnComplete{
BleLogHelper.writeLog("GATT REFRESHED")
}
?.subscribe ({
BleLogHelper.writeLog("GATT REFRESHED")
},{
BleLogHelper.writeLog("FAIL REFRESHING GATT")
})
BleLogHelper.writeLog("Send Request Connection Command $deviceType")
val command = BraincareBluetoothCommandProtocol.createRequestConnectionCommandFrame(deviceType)
connection.writeCharacteristic(BraincareBluetoothProtocol.rxCharacteristicUUID, command)
}
.delay(300, TimeUnit.MILLISECONDS)
.subscribe({
BleLogHelper.writeLog("Connection Established ${device.type}")
val iscon= this.isConnecting
startBlinkingDeviceLed(deviceType, pairColor)
connectionFlowListeners.forEach { it.onConnectionEstablished(device) }
}, {
BleLogHelper.writeError("Connection Lost ${device.type}", it)
BleLogHelper.writeError("Retrying...", it)
val iscon= this.isConnecting
if (isMonitoring || isConnecting || deviceType == DeviceType.DONGLE){
connectionStateListeners.forEach {
if (deviceType == DeviceType.SENSOR) {
sensorNotificationSubscription?.dispose()
sensorRssiSubscription?.dispose()
blinkingDeviceLedsSubscription?.dispose()
disconnectFromDevice(DeviceType.SENSOR)
} else {
dongleRssiSubscription?.dispose()
disconnectFromDevice(DeviceType.DONGLE)
}
isConnecting = false
it.onConnectionLost(device)
}
}else{
reconnectToDevice(device, pairColor)
}
})
if (deviceType == DeviceType.SENSOR) {
sensorConnectionSubscription = connectionSubscription
} else {
dongleConnectionSubscription = connectionSubscription
}
}
The exception is firing just after connection.writeCharacteristic(BraincareBluetoothProtocol.rxCharacteristicUUID, command)
Log error:
2019-05-21 10:54:11.816 11797-11889/io.b4c.brain4care.debug E/BLEBC: 21/05/2019 10:54:11.810 - Connection Lost SENSOR
com.polidea.rxandroidble2.exceptions.BleDisconnectedException: Disconnected from D4:57:4F:53:44:E7 with status 19 (UNKNOWN)
at com.polidea.rxandroidble2.internal.connection.RxBleGattCallback$2.onConnectionStateChange(RxBleGattCallback.java:77)
at android.bluetooth.BluetoothGatt$1$4.run(BluetoothGatt.java:268)
at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:789)
at android.bluetooth.BluetoothGatt.-wrap0(Unknown Source:0)
at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:264)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70)
at android.os.Binder.execTransact(Binder.java:682)
status=19 is GATT_CONN_TERMINATE_PEER_USER. This library since version 1.8.1 lists the reason properly. It is always advised to use the newest available version of basically any library as they bring improvements over time.
There is no clear question in the post. With the provided information it is not possible to tell more than the above — the peripheral you use disconnects from the app. Why this happens is up to your peripheral and you can possibly find an answer in the documentation.
Bear in mind that newer Android versions do not allow concurrent pairing procedures to more than one BLE device at a time. Pairing of two devices should be performed sequentially i.e.
Peripheral A starts pairing
Peripheral A finishes pairing
Peripheral B starts pairing
Peripheral B finishes pairing
Peripherals may be connected at the same time but only a single pairing procedure may be held at a time.
How do I know if device has Infra-red hardware in android pragmatically?
I want to have some things to be done based on this. I tried using something like below, but no luck.
this.getPackageManager().hasSystemFeature( .. various constants ..)
Use ConsumerIrManager.hasIrEmitter()
Try Following Code
Kotlin:
val irManager: ConsumerIrManager = getSystemService(CONSUMER_IR_SERVICE) as ConsumerIrManager
// Check whether IrEmitter is available on the device.
if (irManager.hasIrEmitter()) {
Log.i("IR_Testing", "found IR Emitter")
}else{
Log.i("IR_Testing", "Cannot found IR Emitter on the device")
}
Java:
private ConsumerIrManager irManager ;
irManager = (ConsumerIrManager) getSystemService(CONSUMER_IR_SERVICE);
if (irManager.hasIrEmitter()) {
Log.i("IR_Testing", "found IR Emitter");
} else {
Log.i("IR_Testing", "Cannot found IR Emitter on the device");
}
I can't seem to get net stream to work on my adobe air application. Android or desktop.
Here is the code with the valid link. The link works on VLC.
Any suggestions?
public function Main() {
url = "rtmp://s1p2w2yhnipjkt.cloudfront.net/cfx/st/mp4:demo.mp4?Expires=1594281188&Signature=AW0M39xRqX5bjhlw4EPMvdPzum8~gbK6Wsl7vkI3av6cWDXQ36lCfTlnpOXse6qiP9RSbuT-jhor84DHvZg7yPmvnnlPgAEQlndtgsBvzwUj~kGXES~~VWvHGVuUHTDnK~rAWcOmzpbRi-jWPpN71Ks2wnJeri596lqh2dOkUcg_&Key-Pair-Id=APKAI7XWAS4L22TVE3HA";
_netConnection = new NetConnection();
_netConnection.addEventListener(NetStatusEvent.NET_STATUS, onConnect);
_netConnection.client = {onBWDone:onNetConnectionBWDone};
_netConnection.connect(url);
_netConnection.connect("rtmp://s1p2w2yhnipjkt.cloudfront.net/cfx/st");
trace("connect")
}
private function onConnect(event:NetStatusEvent):void {
trace(event.info.code);
if(event.info.code == "NetConnection.Connect.Success")
{
_netStream = new NetStream(_netConnection);
_netStream.client = {onMetaData:onMetaData, onPlayStatus :onPlayStatus};
var video:Video = new Video();
video.attachNetStream(_netStream)
_netStream.play("mp4:demo.mp4");
addChild(video);
}
}
I tested your stream in my android device and it's working fine, and I think that your forgot to use the params with your stream, so you can do like this :
var url:String = 'rtmp://s1p2w2yhnipjkt.cloudfront.net/cfx/st',
// or rtmp://s1p2w2yhnipjkt.cloudfront.net:80/cfx/st
stream:String = 'mp4:demo.mp4?Expires=1594281188&Signature=AW0M39xRqX5bjhlw4EPMvdPzum8~gbK6Wsl7vkI3av6cWDXQ36lCfTlnpOXse6qiP9RSbuT-jhor84DHvZg7yPmvnnlPgAEQlndtgsBvzwUj~kGXES~~VWvHGVuUHTDnK~rAWcOmzpbRi-jWPpN71Ks2wnJeri596lqh2dOkUcg_&Key-Pair-Id=APKAI7XWAS4L22TVE3HA';
// ...
_netConnection.connect(url);
// ...
_netStream.play(stream);
Of course you have to add the INTERNET permission to your app to be able to get the stream, and also to be sure that your device can connect to the video server via the port 1935 or 80 (at worst).
Hope that can help.