I am working with samsung t365(android 4.4.4) and it is communicate with one uart quite good. But I need to use multiple (two) uart to communicate with one android device's only one port. When I use usb hub (S-LİNK SL-U602 USB 2.0) and use uart term application from play market I can see both uart by selecting ports. Question is:
Is it possible to use com ports programmatically choosing and do the work,
What might be challange (with multiple uarts)
Thank you.
Try with android-serialport-api library.
As per RS232 standard, only one device per COM port is allowed.
In FTdriver.java there is a begin method which can help to connect multi device. But, in default it is setted for first device. as you can see in comment line. It should be modified for multi connection.
reference: https://github.com/ksksue/FTDriver/blob/master/FTDriver/src/jp/ksksue/driver/serial/FTDriver.java
// Open an FTDI USB Device
public boolean begin(int baudrate) {
for (UsbDevice device : mManager.getDeviceList().values()) {
Log.i(TAG, "Devices : " + device.toString());
getPermission(device);
if (!mManager.hasPermission(device)) {
return false;
}
// TODO: support any connections(current version find a first
// device)
if (getUsbInterfaces(device)) {
break;
}
}
if (mSelectedDeviceInfo == null) {
return false;
}
if (mDevice == null) {
return false;
}
if (mDevice.getDeviceClass() == UsbConstants.USB_CLASS_COMM) {
isCDC = true;
} else {
isCDC = false;
}
mFTDIEndpointIN = new UsbEndpoint[mSelectedDeviceInfo.mNumOfChannels];
mFTDIEndpointOUT = new UsbEndpoint[mSelectedDeviceInfo.mNumOfChannels];
if (isCDC) {
if (!getCdcEndpoint()) {
return false;
}
} else {
if (!setFTDIEndpoints(mInterface,
mSelectedDeviceInfo.mNumOfChannels)) {
return false;
}
}
if (isCDC) {
initCdcAcm(mDeviceConnection, baudrate);
} else {
initFTDIChip(mDeviceConnection, baudrate);
}
Log.i(TAG, "Device Serial : " + mDeviceConnection.getSerial());
return true;
}
Related
My project is to read button inputs from my car's steering wheel controls and convert them (using a Teensy 3.2 Arduino-alike) into android system actions of my choosing (e.g. Volume Up, Next Track, OK Google).
I have tried several different modes that the Teensy provides in order to solve this, initially as a keyboard emulation, followed by Joystick emulation and now finally a Raw HID device. All of these modes work flawlessly on Windows and Linux but do not work on android (I've tried on the target device running Android 4.1 and an Android 5 device, neither work).
The closest I've managed to get this working is as a RawHID Device with a small app i wrote to decode the packets and convert to system actions. This actually works...for about 2-5 button presses. Then nothing. In order to get my next 2-5 button presses i have to unplug the device and restart the program. The program halts on thisConnection.requestWait() forever. In an older version i used bulkTransfer and it has a similar effect, returning -1 and no data perpetually after 2-5 button presses.
Code for OpenConnection:
public boolean OpenConnection(UsbManager pUsbManager)
{
if(ActiveDevice == null) return false;
if(!hasPermission) return false;
if(ActiveConnection != null && ActiveEndpoint != null) return true;
if(hasAssociatedUsbDevice()) {
ActiveInterface = ActiveDevice.getInterface(InterfaceIndex);
ActiveEndpoint = ActiveInterface.getEndpoint(EndpointIndex);
ActiveConnection = pUsbManager.openDevice(ActiveDevice);
ActiveConnection.claimInterface(ActiveInterface, true);
ActiveRequest = new UsbRequest();
ActiveRequest.initialize(ActiveConnection,ActiveEndpoint);
return true;
}
return false;
}
Code for the device loop (run on a separate low priority thread)
private void deviceLoop(Config.HIDDevice pHIDDevice)
{
try
{
if (!pHIDDevice.OpenConnection(mUsbManager)) return;
ByteBuffer dataBufferIn = ByteBuffer.allocate(64);
//String activeAppName = mAppDetector.getForegroundAppName(); //TODO: Refactor, causing excessive memory alloc
String activeAppName = null;
Config.AppProfile activeProfile = pHIDDevice.getAppProfile(activeAppName);
while (!mExitDeviceThreads)
{
UsbDeviceConnection thisConnection = pHIDDevice.getActiveConnection();
if (thisConnection == null) break; //connection dropped
UsbRequest thisRequest = pHIDDevice.getActiveRequest();
if (thisRequest == null) break; //connection dropped
thisRequest.queue(dataBufferIn, dataBufferIn.capacity());
if (thisConnection.requestWait() == thisRequest)
{
byte[] dataIn = dataBufferIn.array();
for (Config.ButtonPacketMapping thisButtonMapping : pHIDDevice.getButtonPacketMappings())
{
if (thisButtonMapping.Update(dataIn))
{
for (Config.ButtonAction thisButtonAction : activeProfile.getButtonActions(thisButtonMapping.getName()))
{
if (thisButtonMapping.getLastValue() == false && thisButtonMapping.getValue() == true)
{
if (thisButtonAction.buttonAction == Config.ButtonAction.eButtonActionType.Press)
{
thisButtonAction.Set();
}
}
else if (thisButtonMapping.getLastValue() == true && thisButtonMapping.getValue() == false)
{
if (thisButtonAction.buttonAction == Config.ButtonAction.eButtonActionType.Release)
{
thisButtonAction.Set();
}
}
}
}
}
}
else
{
break; //Connection dropped or something went very wrong
}
}
}
finally
{
pHIDDevice.CloseConnection();
}
}
So my question more succinctly is:
Has anyone managed to get a Teensy Arduino to interface with Android in any way at all over USB? Is there anything wrong with my HID approach to cause this "stalling" problem?
In the end, I switched to an Arduino Pro Micro which has native USB support, and used the Project-HID library using the "Consumer Device" method. This works perfectly with any OS/Hardware combo that I've tried.
I want to detect in my Android application if a HDMI cable is connected.
I found a way how to do that:
private boolean isHdmiSwitchSet() {
// The file '/sys/devices/virtual/switch/hdmi/state' holds an int -- if it's 1 then an HDMI device is connected.
// An alternative file to check is '/sys/class/switch/hdmi/state' which exists instead on certain devices.
File switchFile = new File("/sys/devices/virtual/switch/hdmi/state");
if (!switchFile.exists()) {
switchFile = new File("/sys/class/switch/hdmi/state");
}
try {
Scanner switchFileScanner = new Scanner(switchFile);
int switchValue = switchFileScanner.nextInt();
switchFileScanner.close();
return switchValue > 0;
} catch (Exception e) {
return false;
}
}
The problem now ist that I want to do something if HDMI is connected but I dont want to run a threat checking every second if the boolean has flipped. Is there a better way?
I am trying to play with BLE transmission on my device.
Here is the code I use and the output:
// check BLE support
Log.i(TAG, "BLE supported: " + getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)); // true
// check BLE transmission support
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
Log.i(TAG, "isMultipleAdvertisementSupported: " + mBluetoothAdapter.isMultipleAdvertisementSupported()); // false
Log.i(TAG, "isOffloadedFilteringSupported: " + mBluetoothAdapter.isOffloadedFilteringSupported()); // false
Log.i(TAG, "isOffloadedScanBatchingSupported: " + mBluetoothAdapter.isOffloadedScanBatchingSupported()); // false
BluetoothLeAdvertiser mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
Log.i(TAG, mBluetoothLeAdvertiser.toString()); //android.bluetooth.le.BluetoothLeAdvertiser#1c51f789
// check BLE transmission support
// android-beacon-library, https://github.com/AltBeacon/android-beacon-library
int result = BeaconTransmitter.checkTransmissionSupported(getApplicationContext());
Log.i(TAG, "ABL checkTransmissionSupported: " + result); // 0
I can not understand why mBluetoothLeAdvertiser is not null, since mBluetoothLeAdvertiser verifies that it is not false:
package android.bluetooth;
// ...
public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
if (getState() != STATE_ON) {
return null;
}
if (!isMultipleAdvertisementSupported()) {
return null;
}
synchronized(mLock) {
if (sBluetoothLeAdvertiser == null) {
sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
}
}
return sBluetoothLeAdvertiser;
}
// ...
public boolean isMultipleAdvertisementSupported() {
if (getState() != STATE_ON) return false;
try {
return mService.isMultiAdvertisementSupported();
} catch (RemoteException e) {
Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
}
return false;
}
Welcome to the world of Android, which is both open source and closed source at the same time! Your analysis of the open source BluetoothLeAdvertiser code above is correct. If that code is running on your mobile device, you would not see the output that your test in the top code snippet shows. Conclusion: the code shown in the second snippet must not be what is on the device.
Android device OEMs are free to fork the source code and modify it to make it work with their hardware. In this case, I know that Motorola did the same thing in this code for their Moto X and Moto G devices. These devices return a BluetoothLeAdvertiser despite the fact that isMultipleAdvertisementSupported() returns false. A Motorola engineer explained to me that they changed this because they wanted to support Advertising despite using a BLE chip that could support only one Advertisement at a time. Indeed, I have verified that Motorola devices can advertise, but if you try to get two advertisements going simultaneously, it fails.
I am trying to develop a small app where I can scan and connect to the WiFi hot-spots from scanned list of networks. But for both, Open and Secure networks I have written a password prompt and if the network is open (by knowing it beforehand) I do not enter password and keep the text blank and enter and then it connects. Can anyone tell how to identify programmatically open and secure wifi so that I won't ask for password for Open network and let it connect directly. (I won't be knowing which is Open and Which is secure network in future, so we need to identify open and secure network from SSID or something)
Here you have capabilities field which is used to identify the network type
WifiManager wifimanger = (WifiManager) getSystemService(Context.WIFI_SERVICE);
List<ScanResult> networkList = wifimanger.getScanResults();
if (networkList != null) {
for (ScanResult network : networkList) {
String capabilities = network.capabilities;
Log.w(TAG, network.SSID + " capabilities : " + capabilities);
if (capabilities.toUpperCase().contains("WEP")) {
// WEP Network
} else if (capabilities.toUpperCase().contains("WPA")
|| capabilities.toUpperCase().contains("WPA2")) {
// WPA or WPA2 Network
} else {
// Open Network
}
}
}
Use this filter function to differentiate.
private boolean isProtectedNetwork(String capability){
return (capability.contains("WPA") ||
capability.contains("WEP") ||
capability.contains("WPS")
);
}
So when you have hold of all the List. Just iterate through it and add them in two different lists. (One for open and one for secure networks).
Here is the code for that
private void filterScan(List<ScanResult> allScanResults){
List<ScanResult>openScans = new ArrayList<ScanResult>();
List<ScanResult>closeScans = new ArrayList<ScanResult>();
for(ScanResult result : allScanResults)
{
if(!isProtectedNetwork(result.capabilities))
{
openScans.add(result);
}
else {
closeScans.add(result);
}
}
}
Useful Resource:
You can find more related solutions on My Github Repository
Today I was looking for an answer to this same question, but the solution pointed out here and in other similar questions made me a little insecure. And if a new security mode is created in the future?
For now I prefer to do something like:
public WifiSecurityMode testAgainstSecurityModes(WifiSecurityMode... securities) {
for (WifiSecurityMode security : securities) {
if (this.capabilities.toUpperCase().contains(security.getName().toUpperCase())) {
return security;
}
}
return WifiSecurityMode.UNKNOWN;
}
public enum WifiSecurityMode {
WEP("WEP"), WPA("WPA"), WPA2("WPA2"),//....
UNKNOWN ("UNKNOWN");
private String name;
WifiSecurityMode (String name){
this.name = name;
}
public String getName() {
return name;
}
}
//to use it: (WifiInfo are just a class I create to encapsulate the values in a ScanResult object)
public List<WifiInfo> getOpenWifis() {
List<WifiInfo> open = new ArrayList<>();
for (WifiInfo w : wifiInfoList) {
if (w.testAgainstSecurityModes(WifiSecurityMode.WEP, WifiSecurityMode.WPA, WifiSecurityMode.WPA2).equals(WifiSecurityMode.UNKNOWN)) {
open.add(w);
}
}
return open;
}
After that, you do what you want with UNKNOWN return.
If a new security mode be created in the future, you will not need to change testAgainstSecurityModes method.
We have a Bluegiga Bluetooth module that is set up to work as hands free device.
After initial pairing, I need my application to initiate connection to it via HFP programmatically. Can this be achieved in Android?
Using hidden api works for me!
// get default bluetooth adapter
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
// get bounded device on Android
Set<BluetoothDevice> devices = mAdapter.getBondedDevices();
if (devices.size() > 0) {
for (Iterator<BluetoothDevice> it = devices.iterator(); it.hasNext();) {
BluetoothDevice device = it.next();
// treat the device the default buletooth device you needed
mCurrentDevice = device;
// break;
}
} else {
return;
}
// another method to get headset(HFP) profile
mAdapter.getProfileProxy(mContext, new BluetoothProfile.ServiceListener() {
#Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.e("log", "headset proxy connected");
try {
BluetoothHeadset mCurrentHeadset = (BluetoothHeadset) proxy;
// check whether or not current device hfp is connected or not, if not,
// try to connect the channel between phone and device using hidden api
if (mCurrentHeadset.getConnectionState(mCurrentDevice) != BluetoothHeadset.STATE_CONNECTED) {
Method connectMethod = mCurrentHeadset.getClass().getMethod("connect", mCurrentDevice.getClass());
connectMethod.setAccessible(true);
Boolean returnValue = (Boolean) connectMethod.invoke(proxy, mCurrentDevice);
Log.e("log", "headset proxy connected " + returnValue);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(int profile) {
Log.e(LogTag.TAG, "headset profile disconnected");
}
}, BluetoothA2dp.HEADSET);