BLE with MiBand 3 - java

This is my first time asking so please forgive if I happen to show mistakes.
Simply put, I want to create app that able to interact with Mi Band 3. The interaction I'm able to make is just reading battery info. What I truly want is enabling the real-time heart rate and steps scan.
What have I done before?
I've seen and tried https://github.com/pangliang/miband-sdk-android . It was actually this library that made me think that enabling heart scan from Android is possible to do. I tried following with my Mi Band 3 but failed: setHeartRateScanListener, startHeartRateScan, getBatteryInfo.
I've seen, cloned, and tampered a little with https://github.com/Freeyourgadget/Gadgetbridge . It is amazing, It can interact with my Mi Band 3, but the problem is Gadgetbridge do not have heart rate scan feature and I kinda overwhelmed with the code.
Of course, I've tried https://developer.android.com/guide/topics/connectivity/bluetooth-le . After reading the Pangliang's and Gadgetbridge's code I did following to do heart rate scan.
First, I know that I should put listener right? So here's the function
public void listenHeartRate() {
BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb")).getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"));
bluetoothGatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
descriptor.setValue(new byte[] {0x01, 0x00});
if(!bluetoothGatt.writeDescriptor(descriptor)) {
Log.d(TAG, "tesListenHeartRate: failed");
}
}
And then, I start the scanning with this.
public void startHeartRate() {
Log.d(TAG, "tesHeartRate: start");
BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb")).getCharacteristic(UUID.fromString("00002a39-0000-1000-8000-00805f9b34fb"));
characteristic.setValue(new byte[]{21, 2, 1});
if (!bluetoothGatt.writeCharacteristic(characteristic)) {
Log.d(TAG, "tesStartHeartRate: failed");
}
}
The problem with this is that writeCharacteristic always returning status 3 which means GATT_WRITE_NOT_PERMITTED.
So, where did I go wrong? Thank you very much.

"(...) I nearly gave up, but then realized that I was missing out something. Authentication. Yes, I missed authentication! Thanks to Andrey Nikishaev,
He has explained very well how mi band is being paired and authenticated. That gave me a good head start. And here are the Authentication steps: (...)"
Whole article: https://medium.com/#yogeshojha/i-hacked-xiaomi-miband-3-and-here-is-how-i-did-it-43d68c272391

Related

Player*First*JoinEvent how should i do that?

so i tried to make a simple PlayerJoinEvent (AKA. PlayerFirstJoinEvent) for my server. Is there a way to do that? I want to run my code when player joins the server first time. I have tried multiple options like using if(player.hasPlayedBefore()) but it doesent want to work! So, do you have an idea how to fix it or do it with a different method? Thanks to everyone for help!
You haven't probably deleted player data! If new player joins, new player data are created, only then does Spigot know, that the player is new to the server!
To do so:
Shutdown your server
Go to server-folder/world/playerdata/*player-uuid*.dat
Delete player-uuid.dat
Start the server
Warning: This deletes player inventory!
If your server is in offline mode, and you don`t know what your UUID is, use this online tool.
If your server is in online mode, and you don't know your UUID, use namemc
Code to test the event:
#EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
if(!event.getPlayer().hasPlayedBefore()) {
event.getPlayer().sendMessage("Hi!");
}
}
Don't forget to register this event in your main class!
So i solved it and Thanks to everyone for help there wasnt any problem with hasPlayedBefore().

Fixing Unsuccessful Transaction on Payment Gateway using Midtrans (Android)

So I recently just trying to understand deeper into Payment Gateway (Android). I already read the documentation and try to implement it into my Android project. So here's the thing, couple times even until now, I'm always getting a message "Transaction unsuccessful. Please try again with another card or with a different payment method" when I try to click a button called Pay. So this Pay button when I clicked it, it supposed to open a new tab (page) to show all of the Payment Method. But again that page never showed up, and showing those errors only.
Can anyone help me fixing this problem? I'm gonna send u guys the code if u guys need it. BIG THANKS :)
This is my button code looks like. How did I can get a page that showing PaymentUiFlow (Payment Method Page)? I already try to configure it out with many different ways but still showing the same error.
private void actionButton() {
MidtransSDK.getInstance().setTransactionRequest(DataCustomer.transactionRequest(
"1",
getIntent().getIntExtra("price", 0),
getIntent().getIntExtra("qty", 0),
getIntent().getStringExtra("name")));
MidtransSDK.getInstance().startPaymentUiFlow(ProductOrderActivity.this, PaymentMethod.BANK_TRANSFER_MANDIRI);
}

Java set MIDI Out receiver

Hey I am trying to send MIDI data from a Java class to a MIDI device connected via USB. I did this once like 2 years ago and it worked, but I somehow can't find the project anymore.
The example Java code runs fine;
myMsg = new ShortMessage();
myMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, 93);
timeStamp = -1;
Receiver rcvr = MidiSystem.getReceiver();
rcvr.send(myMsg, timeStamp);
Simple stuff. 5 lines of code and the message appears on the device. The problem is, that this way, only the standard device is set up and ready to receive MIDI. I can't ask my users to set the device of desire as standard device every time they want to use my application. (the Receiver acts as output destination/port to the input of the physical device I am connected to)
I am now trying to set up the Receiver by doing the following:
MidiDevice.Info[] infoA=MidiSystem.getMidiDeviceInfo();//array where all the device info goes
for (int x=0;x<infoA.length;x++){
System.out.println("in "+infoA[x]); //this displays all the devices
}
MidiSystem.getMidiDevice(infoA[d]); //d is set to an integer that represents the item number on the device list of the device I wanna send MIDI to
System.out.println(infoA[d]);//last check if the correct device is selected
MidiDevice MidiOutDevice = MidiSystem.getMidiDevice(infoA[d]); //setting this to "my" device in order to set the Receiver
maschineReceiver= MidiOutDevice.getReceiver();
Sequencer MidiOutSequencer = MidiSystem.getSequencer();
MidiOutSequencer.getTransmitter().setReceiver(maschineReceiver); //probably unnecessary last 2 line but I gave this a try in case it helps
if I now do maschineReceiver.send(myMsg, timeStamp);, nothing happens at all. I also tried different devices but it didn't get any better. I am sure it can't be a very hard difficult thing to do as it something I actually achieved 2 years ago when my coding skills were awful but I just can't find the mistake right now, no matter how often I reread the Java documentation, it just won't work whatever I do.
Thanks in advance
To actually reserve a device for your program, you need to use the MidiDevice method open:
if (!(device.isOpen())) {
try {
device.open();
} catch (MidiUnavailableException e) {
// Handle or throw exception...
}
}

How can I implement Google Play Licensing for an Android app? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I saw the stock Android-Developer licensing library instructions, but the overview seems to omit several key steps in the process and fails to fully explain how to get something working.
Can someone provide an explicit set of operations that worked to get the licensing library set up on an Android app so it checks to ensure that a user has paid for an app in Google Play before allowing use?
I have been working on implementing licensing in my app for some time now and finally have it working. I wanted to share some of the things I found helpful for getting started and some problems and solutions that I found with everyone. The android dev tutorial I have linked below is ok, but it wasn't that useful for me, so I decided to make a tutorial. Enjoy, and I hope it helps you!
Link to developer page here.
1. Getting started
Things you will need.
1.1 Your Base64 unique application key
How to get it:
a. Go to your developer console. Link.
b. If you haven't already created an application draft for your app, do it now.
c. Once you have created the draft, it is a good idea to upload your .apk as Alpha or Beta. Leave it unpublished.
d. Click Services & APIs
e. Scroll down and find YOUR LICENSE KEY FOR THIS APPLICATION
f. Copy the key into your app like this:
private static final String BASE64_PUBLIC_KEY = "YOUR LICENSE KEY FOR THIS APPLICATION";
Make sure that there are no spaces.
1.2 A salt
a. What is a salt?
A salt is random data that is additional input when hashing a password. They are used to defend against dictionary attacks and rainbow table attacks.
b. How do I get one?
This is a good link to generate a random salt. There should be exactly 20 random integers, so put 20 in for the amount of random strings to generate, each string should be 2 characters long (used for this example, it doesn't have to be). Check numeric digits, and check Identical strings are allowed. They can be negative numbers too. Try to remove any redundancy, e.g. 00 -> 0, for the sake of consistency.
c. Where do I put the salt?
When declaring variables just put this code in, except with your random salt.
private static final byte[] SALT = new byte[] {YOUR RANDOM SALT, COMMA SEPARATED, 20 INTEGERS};
2. Importing the LVL (Licensing) library into Eclipse and the code you need
2.1 Importing the library
a. Open Android SDK Manager
b. Go to Extras
c. Install Google Play Licensing Library
d. Find your SDK install path which is listed at the top of the SDK manager.
e. Once you are there, navigate to: <sdk>/extras/google/play_licensing
f. In eclipse, click file then import, then Existing Android Code Into Workspace and when it asks you for the file path, navigate to the play_licensing folder and click on library.
g. Once the project named library has been imported, right click it, then hit properties. Click Android on the left and navigate to the bottom and check Is Library, then hit apply. This lets eclipse know that you can use this project code as a library.
h. Right click on your app that you are adding licensing to, and click properties, then hit Android. Go to the bottom and click library and add it to the build path. This should import the library to the Android Dependencies folder.
i. Your project is set up to go to the next step.
2.2 Variables to declare along with your SALT and KEY
private Handler mHandler;
private LicenseChecker mChecker;
private LicenseCheckerCallback mLicenseCheckerCallback;
boolean licensed;
boolean checkingLicense;
boolean didCheck;
2.3 The code
Paste this code near the bottom of your app. This implementation will notify the user if the license is not valid and prompt them to buy the app or exit it.
private void doCheck() {
didCheck = false;
checkingLicense = true;
setProgressBarIndeterminateVisibility(true);
mChecker.checkAccess(mLicenseCheckerCallback);
}
private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
#Override
public void allow(int reason) {
// TODO Auto-generated method stub
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
Log.i("License","Accepted!");
//You can do other things here, like saving the licensed status to a
//SharedPreference so the app only has to check the license once.
licensed = true;
checkingLicense = false;
didCheck = true;
}
#SuppressWarnings("deprecation")
#Override
public void dontAllow(int reason) {
// TODO Auto-generated method stub
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
Log.i("License","Denied!");
Log.i("License","Reason for denial: "+reason);
//You can do other things here, like saving the licensed status to a
//SharedPreference so the app only has to check the license once.
licensed = false;
checkingLicense = false;
didCheck = true;
showDialog(0);
}
#SuppressWarnings("deprecation")
#Override
public void applicationError(int reason) {
// TODO Auto-generated method stub
Log.i("License", "Error: " + reason);
if (isFinishing()) {
// Don't update UI if Activity is finishing.
return;
}
licensed = true;
checkingLicense = false;
didCheck = false;
showDialog(0);
}
}
protected Dialog onCreateDialog(int id) {
// We have only one dialog.
return new AlertDialog.Builder(this)
.setTitle("UNLICENSED APPLICATION DIALOG TITLE")
.setMessage("This application is not licensed, please buy it from the play store.")
.setPositiveButton("Buy", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(
"http://market.android.com/details?id=" + getPackageName()));
startActivity(marketIntent);
finish();
}
})
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNeutralButton("Re-Check", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
doCheck();
}
})
.setCancelable(false)
.setOnKeyListener(new DialogInterface.OnKeyListener(){
public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent) {
Log.i("License", "Key Listener");
finish();
return true;
}
})
.create();
}
2.4 Getting your device id
There has been some debate about this in the past about whether or not to use the sim serial or TelephonyManager.getDeviceId(); but it is generally recommended you use the following code to get the ANDROID_ID of your device for maximum compatibility.
String deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
Log.i("Device Id", deviceId); //AN EXAMPLE OF LOGGING THAT YOU SHOULD BE DOING :)
2.5 Creation of the license checker
a. Before you call doCheck(); you must put this code in your app to make sure everything gets created properly.
mHandler = new Handler();
mLicenseCheckerCallback = new MyLicenseCheckerCallback();
mChecker = new LicenseChecker(this, new ServerManagedPolicy(this, new AESObfuscator(SALT, getPackageName(), deviceId)), BASE64_PUBLIC_KEY);
When I was doing my implemetation of LVL, I read that if you are having problems with Licensing, you can change the first this in the mChecker = new LicenseChecker(this... to getApplicationContext(), mine seemed to work without it, but just in case.
2.6 Adding permissions
a. There are two permissions that you need to add to your applications manifest file.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.vending.CHECK_LICENSE"/>
2.7 Make sure you have the proper imports!
You have probably already done this, but I figured it would be a good place for you to check.
2.8 How to call the license to be checked
a. Simply call doCheck(); whenever you want to check the license. For example if the app is on its first run, do the check.
3. How do I test the licensing to make sure it works before publishing it?
3.1 Configuring the testing device
a. I have my personal phone that I also use for testing. It is recommended that there be only one Google account registered on the phone, historically it makes things a little easier. You can check the accounts by going to Settings -> Accounts.
3.2 Configuring the developer console
a. Open your developer console and go to Settings on the left hand side.
b. Find License Testing
c. Make sure that your email address is listed under Gmail accounts with testing access
d. Now, you can change the test response to whatever you like for testing purposes. The app should respond accordingly. Remember that if you are saving the data via SharedPrefs you will need to clear your app data every time you test it. Make sure that you click save after you change the test response or nothing will happen! I forgot about this multiple times and I ended up with a migraine, then I saw that stinking save button. Lol.
4. Things to try
4.1 Conditional license checking
a. You can try this code if you are saving the didCheck data in SharedPreferences.
if(didCheck==false){
Toast.makeText(this, "Checking application license...", Toast.LENGTH_SHORT).show();
doCheck();
Log.i("Checking!", "Checking license!");
}
4.2 Encrypting your SharedPreferences using SecurePreferences
a. Go to this link.
b. Copy and paste the code from SecurePreferences.java into a class with the exact same name into your project.
c. Read the ReadMe.md for info on implementing this.
5. Troubleshooting
Licensing can be one heck of a headache to troubleshoot, simply because there are many more things that can go wrong. For example, there could be network problems or server problems that make you want to rip your hair out. Use of proper logging will help with this, you can also get the server response codes if there is a problem and you can trace it to the server or your app. I have had to do this on multiple occasions.
5.1 I can't get my app to return anything from the server
Possible Fixes:
a. Make sure that your app has the correct KEY.
b. Make sure you are logging each step of the progress
c. Check your log for anything from the licensing service. It can be useful for figuring out where something went wrong.
d. Make sure allow() and dontAllow() and applicationError() have #Override tags.
5.2 My app always says LICENSED or NOT_LICENSED no matter what I set it to in the test response
a. The best cure I have for this is just to wait. It seems that if you do lots of testing in a short period of time, it will always send you server code 291 which is the retry code. I waited overnight and everything worked fine the next morning.
b. You can clear the data (not just cache) of the Google Play app and the Google Play Services app. Then open play back up and accept all the licenses and try again.
c. Clear your app data.
5.3 List of server response codes for debugging
You should get these decimal values for int reason if you log them. Use this table to reference what the server is actually sending to your app.
LICENSED = Hex: 0x0100, Decimal: 256
NOT_LICENSED = Hex: 0x0231, Decimal: 561
RETRY = Hex: 0x0123, Decimal: 291
LICENSED_OLD_KEY = Hex: 0x2, Decimal: 2
ERROR_NOT_MARKET_MANAGED = Hex: 0x3, Decimal: 3
ERROR_SERVER_FAILURE = Hex: 0x4, Decimal: 4
ERROR_OVER_QUOTA = Hex: 0x5, Decimal: 5
ERROR_CONTACTING_SERVER = Hex: 0x101, Decimal: 257
ERROR_INVALID_PACKAGE_NAME = Hex: 0x102, Decimal: 258
ERROR_NON_MATCHING_UID = Hex: 0x103, Decimal: 259
5.4 Room for more! They will come!
I hope this helps you guys! I tried to share my headaches and fixes with you guys as best I can and I hope this helps!
If I made any errors, be sure to tell me about them so I can get them fixed ASAP!

Playing sound on BlackBerry gives an error

I'm having trouble getting a short MP3 file to play in a very small app I'm writing to learn how to develop for the BlackBerry.
Because I'm a newbie at BlackBerry development, I've uploaded my Eclipse project for the app to http://stroke.sampablokuper.com/stroke.zip because I don't know if the problem's with my Java programming, or the way I've laid out the resources in my project, or something else.
It's a very small project - only one Java file & three media files - so please help me by seeing if you can run it without errors in the Curve 8520 simulator on your computer. (It's designed for the 8520, because that's the phone a friend of mine has; I don't have a BB myself - yet!)
The idea is that when the user presses/scrolls "down" on the trackball/pad, a sound will be played, but currently instead of the sound, I just get an error message: javax.microedition.media.MediaException .
I've tried to debug this, but as I say, I'm a total newbie to BB development, so I don't really know how to make sense of the information I get from the breakpoints I've set.
Please can you tell me where I've gone wrong?
I really want to finish this before Christmas; please help!
Thanks in advance :)
EDIT: here's the relevant portion of the code, stripped down as much as possible:
public boolean navigationMovement(int dx, int dy, int status, int time) {
if (dx == 0 && dy == 1)// DOWN
{
makeNoise("growl");
}
return true;
}
private void makeNoise(String action) {
if (action == "growl") {
Dialog.alert("GROWL");
try
{
Player p = javax.microedition.media.Manager.createPlayer("growl.mp3");
p.realize();
VolumeControl volume = (VolumeControl)p.getControl("VolumeControl");
volume.setLevel(30);
p.prefetch();
p.start();
}
catch(MediaException me)
{
Dialog.alert(me.toString());
}
catch(IOException ioe)
{
Dialog.alert(ioe.toString());
}
}
invalidate();
}
Further edit I've removed the link to download the project, since the problem did indeed appear to be with the code, and is now solved anyway.
if you have mp3 file on SDCard your URI should be file:///SDCard/<file>.mp3 but if you are playing it from application then getResourceAsStream is the answer
The problem turned out to be that the string passed to the .createPlayer method needs to be a URI.
I tried many variations along the lines file:///growl.mp3 before eventually giving up (if anyone knows the correct URI syntax for pointing to a file within a BlackBerry App, please comment!) and settling on this:
InputStream is = getClass().getResourceAsStream("growl.mp3");
Player p = javax.microedition.media.Manager.createPlayer(is,"audio/mp3");
It's a bit crufty by comparison, but at least it works!

Categories

Resources