Handle Long Press of Media Button Play/Pause on bluetooth device - android

I am working on a project for which I want to handle long press of my play button on bluetooth device.
For now it is working for a single click.
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (event.getKeyCode() == 126 || event.getKeyCode() == 127) {
// do something
if (action == KeyEvent.ACTION_DOWN) {
Toast.makeText(context,"BUTTON PRESSED!", Toast.LENGTH_LONG).show();
if(event.isLongPress()==true)
{
Toast.makeText(context,"Finally long press worked!!", Toast.LENGTH_LONG).show();
}
}
}
}
The method isLongPress() always returns false.
Please let me what modification can make this program work.
Thanks in advance :)

check the instruction of your BT device. Longpress calling key on headset usually means rejecting an incoming call. I am not sure if longpress Play key on headset is defined in AVRCP.

Related

Read data from a bluetooth barcode reader in Android

I want to read barcodes using a bluetooth barcode scanner.
I don't want to use Bluetooth Keyboard Emulation (HID) mode, because is too hard to point to a textbox before any scan.
I read this developer.android.com/guide/topics/connectivity/bluetooth.html but I don't found yet something usable.
Must listen for an write event with a end-code delimiter (CR, LF, etc).
If your bluetooth barcode scanner does not have a switch* for change HID mode to SSP mode, then you can't connect with him. (* hardware or software switch)
Android connect natively with HID bluetooth (Human Interface Device) and don't let them go :).
So, I solve my problem reading and overriding a keyboard event.
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (barCodeRadearIsOn && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER || (event.getKeyCode() >= 7 && event.getKeyCode() <= 16))) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (event.getAction() == KeyEvent.ACTION_UP){
Toast.makeText(context, barCode, Toast.LENGTH_LONG).show();
....... .......
barCode = "";
}
} else {
if (event.getAction() == KeyEvent.ACTION_UP){
barCode = barCode + (char)event.getUnicodeChar();
}
}
return true;
} else {
return super.dispatchKeyEvent(event);
}
}
Notes:
barCodeRadearIsOn - users have a switch on/off
This code "intercept" only Enter and numeric characters from 0 to 9.

android get barcode scanner input without edittext

I have a physical barcode scanner and I want to get it's input, i.e the barcode, in the app without having a focused EditText.
I tried adding a KeyListener in my Activity. However, none of its implemented methods (onKeyUp, onKeyDown etc) was called.
Then I added the dispatchKeyEvent, which worked, but is never called as many times as the barcode length. Instead, before the barcode is read, some random button in my view gets focus from the barcode scanner.
String barcode = "";
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
char pressedKey = (char) e.getUnicodeChar();
barcode += pressedKey;
if (e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
Toast.makeText(getApplicationContext(), "barcode--->>>" + barcode, Toast.LENGTH_LONG)
.show();
}
return super.dispatchKeyEvent(e);
}
I've seen a few questions out there in SO but none really gave a concrete answer.
For me, for a barcode scanner (USB, reference STA pcs) works the next code:
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if(e.getAction()==KeyEvent.ACTION_DOWN){
Log.i(TAG,"dispatchKeyEvent: "+e.toString());
char pressedKey = (char) e.getUnicodeChar();
barcode += pressedKey;
}
if (e.getAction()==KeyEvent.ACTION_DOWN && e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
Toast.makeText(getApplicationContext(),
"barcode--->>>" + barcode, Toast.LENGTH_LONG)
.show();
barcode="";
}
return super.dispatchKeyEvent(e);
}
First, thank you all.
Since my App has to look up the barcode in the DB I had to not add the ENTER_KEY input to the Barcode String, also to prevent any focused button of going off I made the Method return false.
String barcode = "";
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if(e.getAction()==KeyEvent.ACTION_DOWN
&& e.getKeyCode() != KeyEvent.KEYCODE_ENTER){ //Not Adding ENTER_KEY to barcode String
char pressedKey = (char) e.getUnicodeChar();
barcode += pressedKey;
}
if (e.getAction()==KeyEvent.ACTION_DOWN
&& e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
Log.i(TAG,"Barcode Read: "+barcode);
barcodeLookup(barcode);// or Any method handling the data
barcode="";
}
return false;
}
Using kotlin
private val barcode = StringBuffer()
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
if (event?.action == KeyEvent.ACTION_DOWN) {
val pressedKey = event.unicodeChar.toChar()
barcode.append(pressedKey)
}
if (event?.action == KeyEvent.ACTION_DOWN && event?.keyCode == KeyEvent.KEYCODE_ENTER) {
Toast.makeText(baseContext, barcode.toString(), Toast.LENGTH_SHORT).show()
barcode.delete(0, barcode.length)
}
return super.dispatchKeyEvent(event)
}
e.getCharacters() should give you the complete barcode.
This works for me on a PL-40L device with embedded 2d barcode reader, running Android 5.1
dispatchKeyEvent(KeyEvent e) is triggered once for each read barcode, not for each character in the barcode
Hope this helps
DispatchKeyEvent Hardware key events are always delivered to the View currently in focus. They are dispatched starting from the top of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View) currently has focus, then you can see the event travel through the dispatchKeyEvent() method. In short, dispatchKeyEvent() will be only called if TextView/EditText is in focus.
You can do it even without any focused View. You need to subscribe for broadcast intent like this:
const val QR_ACTION: String = "android.intent.ACTION_DECODE_DATA"
const val QR_EXTRA: String = "barcode_string"
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
try {
Timber.d("Get intent ${intent.action}")
if (QR_ACTION == intent.action) {
if (intent.hasExtra(QR_EXTRA)) {
val code = intent.getStringExtra(QR_EXTRA)
Timber.d("New QR code $code")
// now you have qr code here
}
} }
} catch (t: Throwable) {
// handle errors
}
}
}
Please check QR_ACTION and QR_EXTRA in your scanner settings first, it can be different for different brands.

Android: Key Event from Android Box remote controller

I was interested to know how can i catch key/button events from Android TV Box remote controller?
For example, i want a popup menu to show when i click the OK button from remote controller. And i want to catch the next/back key events from remote controller.
Should i use the Key Event class from Android, if yes how should i implement it?
I came across this function but i cannot really make sense of it.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_A:
{
//your Action code
return true;
}
}
return super.onKeyDown(keyCode, event);
}
Thanks in advance.
You should catch key event on dispatchKeyEvent
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
Log.e(TAG, "Key down, code " + event.getKeyCode());
} else if (event.getAction() == KeyEvent.ACTION_UP) {
Log.e(TAG, "Key up, code " + event.getKeyCode());
}
return true;
}
Edit:
First, you should know key map of your remote (it is not the same for all kind of Android TV box), the code above will help you know code of key that you press on the remote. For example, i got key code 3 when i press button BACK on remote.
Then, i want when back key pressed, a Toast message will be show:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
// You should make a constant instead of hard code number 3.
if (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode == 3) {
Toast.makeText(this, "Hello, you just press BACK", Toast.LENG_LONG).show();
}
return true;
}

How to shield POWER button at a activity UI

Now, I want to implement a function like this: at a activity, shield all hardware buttons, like HOME, VOLUME_UP,VOLUME_DOWM. But, only POWER button can't shield. Is there a way?
You cannot intercept certain keys in Android like power and home e.g. Home key cannot be intercepted as this will allow any malicious application to over ride the functionality.
The only way you can intercept the home key is if your application is the home app replacement itself by using android.intent.category.HOME in the manifest.
You can catch other keys e.g. volume up/down and back as follows
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
if (action == KeyEvent.ACTION_UP) {
//handle the key event
}
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (action == KeyEvent.ACTION_DOWN) {
//handle the key event
}
return true;
default:
return super.dispatchKeyEvent(event);
}
}
Read the following post on the Android Developer blogpost
Android Developer: Back and other hard keys-three stories

Making Android game, key input registered weirdly on X10 Mini Pro

Hey, I've just started to learn Android development and ran into a problem.
Controls in the game I'm making work on virtual device, but not on phone:
I have an Xperia X10 Mini Pro
I'm making a basic Pong game to learn droid software development
The game works just fine on my Android virtual device, you can move the paddles up and down smoothly
On my phone I've figured that the onKeyDown event doesn't run until I release the button or after I've held down the button for a second or two, but then it only registers it as a brief press of the button, not like if I was holding it down
I believe that it's a feature of my phone to quickly access special characters, because some keys register different key codes when pressed quickly and when held down
The problems this results in is that I can not move the paddles, but I can do single press things, like pause the game
I can also add:
Game is heavily built around sample app LunarLander from the SDK
Lunar lander works fine in virtual device but has same issues as my pong when put in my phone
How could I force my phone to register onKeyDown events like it should? (Or at least like the virtual device does?)
Code from my view class that extends surfaceView:
#Override
public boolean onKeyDown(int keyCode, KeyEvent msg) {
return thread.doKeyDown(keyCode, msg);
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent msg) {
return thread.doKeyUp(keyCode, msg);
}
Code from within the thread:
boolean doKeyDown(int keyCode, KeyEvent msg) {
synchronized (mSurfaceHolder) {
mP1Score = keyCode;//For debugging
boolean okStart = false;
if (keyCode == KeyEvent.KEYCODE_SPACE) okStart = true;
if (mMode == STATE_PAUSE && okStart) {
setState(STATE_RUNNING);
return true;
} else if (mMode == STATE_READY && okStart) {
setState(STATE_RUNNING);
return true;
} else if (mMode == STATE_GOAL && okStart) {
return true;
}else if (mMode == STATE_END_GAME && okStart) {
doStart();
return true;
} else if (mMode == STATE_RUNNING) {
if (keyCode == KeyEvent.KEYCODE_Q) {
mP1dY = -PLAYER_SPEED;//Player 1 up
return true;
} else if (keyCode == KeyEvent.KEYCODE_A) {
mP1dY = PLAYER_SPEED;//Player 1 down
return true;
} else if (keyCode == KeyEvent.KEYCODE_O) {
mP2dY = -PLAYER_SPEED;//Player 2 up
return true;
} else if (keyCode == KeyEvent.KEYCODE_L) {
mP2dY = PLAYER_SPEED;//Player 2 down;
return true;
} else if (keyCode == KeyEvent.KEYCODE_SPACE) {
pause();//Space is pressed in game
return true;
}
}
return false;
}
}
boolean doKeyUp(int keyCode, KeyEvent msg) {
boolean handled = false;
mP2Score = keyCode;//For debugging
synchronized (mSurfaceHolder) {
if (mMode == STATE_RUNNING) {
if (keyCode == KeyEvent.KEYCODE_Q
|| keyCode == KeyEvent.KEYCODE_A) {
mP1dY = 0;
handled = true;
} else if (keyCode == KeyEvent.KEYCODE_O
|| keyCode == KeyEvent.KEYCODE_L) {
mP2dY = 0;
handled = true;
}
}
}
return handled;
}
Complete source available here
Here's a sort-of-solution:
The problem is SE's default input method on the X10 Mini Pro. By installing a different input method on the phone (HTC_IME in my case) I can get controls to work like they do on the virtual device.
Now I only need to figure out how to make it work with the default input method and I'll have a complete solution.

Categories

Resources