I need to authenticate to BLE device that requires a key >SBIK12345< first all. I can't write any characteristic and service without the key before.
Some idea?
This is my connect method (from this repo BluLeGatt from Anlif)
public boolean connect(final String address)
{
if (mBluetoothAdapter == null || address == null)
{
System.out.println(TAG+"BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null)
{
System.out.println(TAG+"Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null)
{
System.out.println(TAG+"Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
try
{
device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(SampleGattAttributes.UUID_BLE_080));
}
catch (IOException e)
{
System.out.println("exc createInsecureRfcommSocketToServiceRecord "+e.getLocalizedMessage());
}
mBluetoothGatt = device.connectGatt(this, true, mGattCallback);
System.out.println(TAG+" Trying to create a new connection.");
BluetoothGattCharacteristic characteristic1 = new BluetoothGattCharacteristic(UUID.fromString(SampleGattAttributes.UUID_BLE_080),BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE,BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
characteristic1.setValue(">SBIK1234<");
mBluetoothGatt.writeCharacteristic(characteristic1);
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
And the static var is
public static String UUID_BLE_080 = "00000000-dc70-0080-dc70-a07ba85ee4d6";
Related
Following this demo: https://github.com/googlesamples/android-media-controller
I have this
if (playbackState == null) {
Log.e(TAG, "Failed to update media info, null PlaybackState.");
return null;
}
Map<String, String> mediaInfos = new HashMap<>();
mediaInfos.put(getString(R.string.info_state_string),
playbackStateToName(playbackState.getState()));
MediaMetadataCompat mediaMetadata = mController.getMetadata();
if (mediaMetadata != null) {
addMediaInfo(
mediaInfos,
getString(R.string.info_title_string),
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
addMediaInfo(
mediaInfos,
getString(R.string.info_artist_string),
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
addMediaInfo(
mediaInfos,
getString(R.string.info_album_string),
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM));
binding.controlsPage.mediaTitle.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
binding.controlsPage.mediaArtist.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
binding.controlsPage.mediaAlbum.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM));
final Bitmap art = mediaMetadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART);
if (art != null) {
binding.controlsPage.mediaArt.setImageBitmap(art);
} else {
binding.controlsPage.mediaArt.setImageResource(R.drawable.ic_album_black_24dp);
}
// Prefer user rating, but fall back to global rating if available.
RatingCompat rating =
mediaMetadata.getRating(MediaMetadataCompat.METADATA_KEY_USER_RATING);
if (rating == null) {
rating = mediaMetadata.getRating(MediaMetadataCompat.METADATA_KEY_RATING);
}
mRatingUiHelper.setRating(rating);
} else {
binding.controlsPage.mediaArtist.setText(R.string.media_info_default);
binding.controlsPage.mediaArt.setImageResource(R.drawable.ic_album_black_24dp);
mRatingUiHelper.setRating(null);
}
final long actions = playbackState.getActions();
`
I'm interested in getting the current pitch and changing it to the one I want.
I can see this api here https://developer.android.com/reference/androidx/media3/session/MediaController#setPlaybackParameters(androidx.media3.common.PlaybackParameters) does what I want, but it's only for the MediaController, not for the MediaControllerCompat.
I tried doing mController.getMediaController()
https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaControllerCompat#getMediaController() with no changes at all.
Any ideas?
My device has two ports USB, on one I have connected and read the name (this is GPS) and on the second port I connected a USB storage device and I want to read a file which is on it. Only on one of the device's storage I cannot perform a read like this:
Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
if (externalSdCard != null && externalSdCard.exists() && externalSdCard.listFiles() != null) {
for (File f : externalSdCard.listFiles()) {
if ("key.xml".equalsIgnoreCase(f.getName())) {
String path = f.getPath().replace(".xml", "_DUMP.xml");
File file11 = new File(path);
if (!file11.exists()) {
moveFile(file11, f);
}
return f;
}
}
}
And I think I should do this to read a file :
UsbManager usbManager = ((UsbManager)(GetSystemService(Context.UsbService)));
var deviceList = usbManager.DeviceList;
IEnumerable<UsbDevice> deviceIterator = deviceList.Values.AsEnumerable();
if ((deviceIterator.Count() > 0)) {
UsbDevice device = deviceIterator.ElementAt(0);
usbManager.RequestPermission(device, mPermissionIntent);
if (usbManager.HasPermission(device)) {
if (usbManager.HasPermission(device)) {
System.Diagnostics.Debug.WriteLine("HasPermission");
UsbDeviceConnection connection = usbManager.OpenDevice(device);
if ((connection != null)) {
System.Diagnostics.Debug.WriteLine(" connection is not null");
var model = device.DeviceName;
string inline = null;
BufferedReader reader = null;
reader = new BufferedReader(new FileReader("/mnt/media_rw/C227-875D/test/hello.txt"));
System.Diagnostics.Debug.WriteLine("no exception occured");
while ((reader.ReadLine() != null)) {
System.Diagnostics.Debug.WriteLine(inlne);
}
}
}
But can I have open two ports at the same time?
Hello i'm trying to fetch an rss feed with this code:
try {
URL url = new URL("http://investing_api.ambcrypto.com/feed/cryptolab/");
InputStream inputStream = url.openConnection().getInputStream();//error in this line
ArrayList<NewsModel> items = parseFeed(inputStream);
return items;
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
it´s wrapped by and AsyncTask and i'm getting this log:
07-22 23:23:03.090 11728-12314/com.mal.saul.coinmarketcap W/System.err: java.net.UnknownHostException: http://investing_api.ambcrypto.com/feed/cryptolab/
07-22 23:23:03.095 11728-13197/com.mal.saul.coinmarketcap I/FirebasePerformance: URL host is null or invalid
Unable to process an HTTP request/response due to missing or invalid values. See earlier log statements for additional information on the specific invalid/missing values.
07-22 23:23:03.110 11728-12314/com.mal.saul.coinmarketcap W/System.err: at libcore.net.http.HttpConnection$Address.<init>(HttpConnection.java:282)
07-22 23:23:03.120 11728-12314/com.mal.saul.coinmarketcap W/System.err: at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
Does anybody have any idea? i also have tried with google news rss feed (https://news.google.com/news/rss/headlines/section/topic/WORLD?ned=us&hl=en&gl=US) and it works well.
Method parseFeed():
public ArrayList<NewsModel> parseFeed(InputStream inputStream) throws XmlPullParserException,
IOException {
String title = null;
String link = null;
String imageUrl = null;
long pubDate = 0;
boolean isItem = false;
ArrayList<NewsModel> items = new ArrayList<>();
try {
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(inputStream, null);
xmlPullParser.nextTag();
while (xmlPullParser.next() != XmlPullParser.END_DOCUMENT) {
int eventType = xmlPullParser.getEventType();
String name = xmlPullParser.getName();
if(name == null)
continue;
if(eventType == XmlPullParser.END_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = false;
}
continue;
}
if (eventType == XmlPullParser.START_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = true;
continue;
}
}
Log.d("MyXmlParser", "Parsing name ==> " + name);
String result = "";
if (xmlPullParser.next() == XmlPullParser.TEXT) {
result = xmlPullParser.getText();
xmlPullParser.nextTag();
}
if (name.equalsIgnoreCase("title")) {
title = result;
} else if (name.equalsIgnoreCase("link")) {
link = result;
} else if (name.equalsIgnoreCase("url url")) {
imageUrl = result;
} else if (name.equalsIgnoreCase("pubDate")) {
pubDate = Long.parseLong(result);
}
if (title != null && link != null && imageUrl != null && pubDate != 0) {
if(isItem) {
NewsModel newsModel = new NewsModel();
newsModel.setPostTitle(title);
newsModel.setPostUrl(link);
newsModel.setPubDate(pubDate);
items.add(newsModel);
}
title = null;
link = null;
imageUrl = null;
isItem = false;
pubDate = 0;
}
}
return items;
} finally {
inputStream.close();
}
}
Check your API url it requires some values in it.
I have dug into the Android sources and found that under the hood, each time an Audio route event occurs, an AudioRoutesInfo object is based to the internal updateAudioRoutes method in MediaRouter:
void updateAudioRoutes(AudioRoutesInfo newRoutes) {
if (newRoutes.mMainType != mCurAudioRoutesInfo.mMainType) {
mCurAudioRoutesInfo.mMainType = newRoutes.mMainType;
int name;
if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADPHONES) != 0
|| (newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADSET) != 0) {
name = com.android.internal.R.string.default_audio_route_name_headphones;
} else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HDMI) != 0) {
name = com.android.internal.R.string.default_media_route_name_hdmi;
} else {
name = com.android.internal.R.string.default_audio_route_name;
}
sStatic.mDefaultAudioVideo.mNameResId = name;
dispatchRouteChanged(sStatic.mDefaultAudioVideo);
}
final int mainType = mCurAudioRoutesInfo.mMainType;
boolean a2dpEnabled;
try {
a2dpEnabled = mAudioService.isBluetoothA2dpOn();
} catch (RemoteException e) {
Log.e(TAG, "Error querying Bluetooth A2DP state", e);
a2dpEnabled = false;
}
if (!TextUtils.equals(newRoutes.mBluetoothName, mCurAudioRoutesInfo.mBluetoothName)) {
mCurAudioRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
if (mCurAudioRoutesInfo.mBluetoothName != null) {
if (sStatic.mBluetoothA2dpRoute == null) {
final RouteInfo info = new RouteInfo(sStatic.mSystemCategory);
info.mName = mCurAudioRoutesInfo.mBluetoothName;
info.mDescription = sStatic.mResources.getText(
com.android.internal.R.string.bluetooth_a2dp_audio_route_name);
info.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
sStatic.mBluetoothA2dpRoute = info;
addRouteStatic(sStatic.mBluetoothA2dpRoute);
} else {
sStatic.mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.mBluetoothName;
dispatchRouteChanged(sStatic.mBluetoothA2dpRoute);
}
} else if (sStatic.mBluetoothA2dpRoute != null) {
removeRouteStatic(sStatic.mBluetoothA2dpRoute);
sStatic.mBluetoothA2dpRoute = null;
}
}
if (mBluetoothA2dpRoute != null) {
if (mainType != AudioRoutesInfo.MAIN_SPEAKER &&
mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false);
} else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
a2dpEnabled) {
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false);
}
}
}
Unfortunately, the only thing I have found that is exposed about the device type in the MediaRouter callbacks, is the internal string resource name of the device (e.g. Phone or Headphones). However, you can see that under the hood, this AudioRoutesInfo object has references to whether the device was a headphone, HDMI etc.
Has anyone found a solution to get at this information? The best way I have found is to use the internal resource names, which is pretty ugly. God, if they would just provide the AudioRoutesInfo object all this information could be accessed without having to rely on a resource hack.
I am encountering a weird behavior when trying to see if two sets are equal. I have overridden the equals and hashcode:
public class Metric {
private String id;
private Sensor sensor;
private String metricName;
private String metricDescription;
//getters, setters, toString()...
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((metricDescription == null) ? 0 : metricDescription.hashCode());
result = prime * result + ((metricName == null) ? 0 : metricName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Metric other = (Metric) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (metricDescription == null) {
if (other.metricDescription != null)
return false;
} else if (!metricDescription.equals(other.metricDescription))
return false;
if (metricName == null) {
if (other.metricName != null)
return false;
} else if (!metricName.equals(other.metricName))
return false;
return true;
}
}
I have intentionally left the Sensor information out of the hashCode and equals, but in both so it should not make a difference.
Now, consider the following code:
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(datasource);
session.save(sensorType);
session.save(sensor);
session.save(metric1);
session.save(metric2);
session.getTransaction().commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
if (session.isOpen())
session.close();
}
try {
session = sessionFactory.getCurrentSession();
tx = session.beginTransaction();
sameSensor = (Sensor) session.get(Sensor.class, new String(sensor.getId()));
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
if (session.isOpen())
session.close();
}
// simply retrieve the metrics
Set<Metric> sensorMetrics = sensor.getMetrics();
Set<Metric> sameSensorMetrics = sameSensor.getMetrics();
System.out.println("SENSOR METRIC");
for(Metric m : sensorMetrics) {
System.out.println(m.getMetricName() + ":" + m.hashCode());
System.out.println(sameSensorMetrics.contains(m));
}
System.out.println("SAME SENSOR METRIC");
for(Metric m : sameSensorMetrics) {
System.out.println(m.getMetricName() + ":" + m.hashCode());
System.out.println(sensorMetrics.contains(m));
}
The two sets should be identical (and all the hascodes are), but I am getting the following result:
SENSOR METRIC
metric2name_addSensor_1393695505000:-1437647480
true
metric1name_addSensor_1393695505000:2040143911
true
SAME SENSOR METRIC
metric1name_addSensor_1393695505000:2040143911
false
metric2name_addSensor_1393695505000:-1437647480
false
Even though the metrics are the same (I have checked the equals on all the pairs, the results are correct) the metrics are contained in one set but not the other... I really can't explain this and would appreciate any help.
I have given code snippets that I believe are the important ones, if any more information is needed I will be more than happy to provide. Thanks.
EDIT:
1) The code where Sensor is initialized as dfb requested:
/*
* Create all the sensor-related information to insert
*/
DataSource datasource = new DataSource();
datasource.setDatasourceName(
createUniqueString("datasource","addSensor"));
datasource.setDatasourceDescription(
createUniqueString("datasource","addSensor","description"));
SensorType sensorType = new SensorType();
sensorType.setSensorTypeName(
createUniqueString("sensortype","addSensor"));
sensorType.setSensorTypeDescription(
createUniqueString("sensortype","addSensor","description"));
Sensor sensor = new Sensor();
sensor.setDatasource(datasource);
sensor.setSensorType(sensorType);
sensor.setSensorName(createUniqueString("sensorname","addSensor"));
sensor.setSensorDescription(createUniqueString("sensordesc","addSensor","description"));
Metric metric1 = new Metric();
metric1.setMetricDescription(
createUniqueString("metric1name","addSensor","description"));
metric1.setMetricName(
createUniqueString("metric1name","addSensor"));
metric1.setSensor(sensor);
Metric metric2 = new Metric();
metric2.setMetricDescription(
createUniqueString("metric2name","addSensor","description"));
metric2.setMetricName(
createUniqueString("metric2name","addSensor"));
metric2.setSensor(sensor);
sensor.addMetric(metric1);
sensor.addMetric(metric2);
And the Sensor constructor:
Sensor() {
this.metrics = new HashSet<Metric>();
}
2) The weird behavior seems to be the Sensor instance that was saved, not the one that was loaded:
Set<Metric> sensorMetrics2 = sensor.getMetrics();
Set<Metric> sensorMetrics = sensor.getMetrics();
System.out.println(sensorMetrics2.equals(sensorMetrics));
System.out.println(sensorMetrics.equals(sensorMetrics));
Set<Metric> sameSensorMetrics2 = sameSensor.getMetrics();
Set<Metric> sameSensorMetrics = sameSensor.getMetrics();
System.out.println(sameSensorMetrics2.equals(sameSensorMetrics));
System.out.println(sameSensorMetrics.equals(sameSensorMetrics2));
The results:
false
false
true
true
Following construct is problematic with Hibernate, because hibernate tends to create proxies for entities because of need for lazy loading:
if (getClass() != obj.getClass())
return false;
Proxy is subclass of Metrics and thats why code above does not work, but code likely does:
if (!(obj instanceof Metrics)) {
return false;
}
More instructions about overriding equals and hashcode for entities can be found from Hibernate documentation. Also instanceof can bring surprises, as is told in this blog post.