Using the following code to attempt setting the sound on/off for a Socket 8ci...not quite working for me. Can you suggest a proper command? As you can see in the code I set the Sound frequency based on a preference boolean. Thanks!
DeviceInfo device = (DeviceInfo) _scanApiHelper.getDevicesList().lastElement();
short[] soundConfig = new short[3];
// default the sound to On
if(getBRSharedPreferenceBoolean(PreferencesActivity.PREF_SOCKET_SCANNER_BEEP, true)) {
soundConfig[0] = ISktScanProperty.values.soundFrequency.kSktScanSoundFrequencyHigh;
} else {
soundConfig[0] = ISktScanProperty.values.soundFrequency.kSktScanSoundFrequencyNone;
}
soundConfig[1] = 200;
soundConfig[2] = 100;
// set the scanner sound config
_scanApiHelper.postSetSoundConfigDevice(
device,
ISktScanProperty.values.soundActionType.kSktScanSoundActionTypeGoodScan,
soundConfig,
_onSetScanApiConfiguration);
The Problem
Sound Config Device
The sound config allows you to set 4 different "actions": kSktScanSoundActionTypeGoodScan, kSktScanSoundActionTypeGoodScanLocal, kSktScanSoundActionTypeBadScan, kSktScanSoundActionTypeBadScanLocal. The difference between GoodScan and BadScan is self-explanatory, but the difference between GoodScan and GoodScanLocal isn't very clear.
GoodScanLocal, by default, is the sound emitted when a barcode is scanned
GoodScan is only emitted when the host (e.g. Android, iOS, Windows) sends the scanner a GoodScan or BadScan notification (via kSktScanPropIdDataConfirmationDevice)
Note: If you are using GoodScan/BadScan to verify decoded data, you probably want to change the confirmation mode (see kSktScanPropIdDataConfirmationMode in the docs). Otherwise the scanner will beep/flash/vibrate twice per scan
The code snippet your snippet is based on uses the latter to demonstrate that the tone is both configurable and can be triggered by the host.
You select a tone, hit the confirm button and the scanner emits that tone. It's not clear at first glance, but if you change the tone using the dropdown in SingleEntry and hit confirm, the three tones are very distinct. However, if you change the tone using that same dropdown, the tone you hear when you scan a barcode should not change.
The Solution
The best and simplest way to achieve what you are trying to achieve is to set the Local Decode Action with the beep disabled
Local Decode Action
// import static com.socketmobile.scanapi.ISktScanProperty.values.localDecodeAction.*;
DeviceInfo device = (DeviceInfo) _scanApiHelper.getDevicesList().lastElement();
int decodeAction = kSktScanLocalDecodeActionFlash | kSktScanLocalDecodeActionRumble;
if(getBRSharedPreferenceBoolean(PreferencesActivity.PREF_SOCKET_SCANNER_BEEP, true)) {
decodeAction |= kSktScanLocalDecodeActionBeep;
}
_scanApiHelper.postSetDecodeAction(device, decodeAction)
For completeness sake, to achieve a similar result using the code you posted, you'd only need to change kSktScanSoundActionTypeGoodScan to kSktScanSoundActionTypeGoodScanLocal. Although I would not recommend it.
Related
I am trying to receive the scanned barcode result from a device paired via (Bluetooth/USB) to an android device.
so many topics said :
most plug-in barcode scanners (that I've seen) are made as HID profile devices so whatever they are plugged into should see them as a Keyboard basically.
source
So I am using this code to receive the result of the scan:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (viewModel.onTriggerScan()) {
//1
char pressedKey = (char) event.getUnicodeChar();
viewModel.addCharToCode(pressedKey);
//2
String fullCode = event.getCharacters();
viewModel.fullCode(fullCode);
//check if the scan is done, received all the chars
if (event.getAction() == EditorInfo.IME_ACTION_DONE) {
//does this work ?
viewModel.gotAllChars();
//3
String fullCode2 = event.getCharacters();
viewModel.fullCode(fullCode2);
}
return true;
} else
return super.dispatchKeyEvent(event);
}
Note: I don't have a barcode scanner device for the test.
which code will receive the result ?? (1 or 2 or 3 ?)
You won't ever see an IME_ACTION_DONE, that's something that's Android only and an external keyboard would never generate.
After that, it's really up to how the scanner works. You may get a full key up and key down for each character. You may not, and may receive multiple characters per event. You may see it finish with a terminator (like \n) you may not- depends on how the scanner is configured. Unless you can configure it yourself or tell the user how to configure it, you need to be prepared for either (which means treating the data as done either after seeing the terminator, or after a second or two once new data stops coming in.
Really you need to buy a configurable scanner model and try it in multiple modes and make ever mode works. Expect it to take a few days in your schedule.
Workaround solution but it works 100%.
the solution is based on clone edittext (hidden from the UI), this edit text just receives the result on it, adds a listener, and when the result arrives gets it and clears the edittext field. An important step, when you try to receive the result(trigger scan) make sure that edittext has the focus otherwise you wil not get the result.
Quick steps:
1- create editText (any text field that receives inputs) in your layout
2- set its visibility to "gone" and clear it.
3- add onValueChangeListener to your edittext.
4- focus your edittext when you start trigger the scan
5- each time you the listener call, get the result and clear edittext
Note: never miss to focus your edittext whenever you start trigger scan.
Note: this method work(99%) for all external scan device and any barcode type.
I am developing an Android application which controls some relays based on some sensors input. I have everything set up and code works just fine, except I don't like the fact that I have to poll for state changes in my activity.
My code is based on this example: https://github.com/ytai/ioio/blob/master/applications/HelloIOIO/src/main/java/ioio/examples/hello/MainActivity.java
For instance:
fun looper() {
// ...
DigitalInput in = ioio.openDigitalInput(exti1Pin, DigitalInput.Spec.Mode.PULL_DOWN);
boolean value = in.read();
// do something if true
// ...
} // looper
The PIC24 on the IOIO board comes with 5 external interrupts as well as change notifications on most pins. However I can't seem to find any way to set up interrupt handlers or change notifications.
Would appreciate any pointers/ideas/suggestions
I'm trying to identify what is the current audio usage for. I need to know if it is for music, movie, or game.
So far, this is how I'm trying to get the information from the AudioAttribute class but I don't get the expected results. Most of the time I get type=CONTENT_TYPE_MUSIC even if I'm playing a movie using the PrimeVideo app or I get usage=USAGE_MEDIA while playing a game.
List<AudioPlaybackConfiguration> configs = mAudioManager.getActivePlaybackConfigurations();
AudioPlaybackConfiguration config = configs.get(0);
int type = config.getAudioAttributes().getContentType();
int usage = config.getAudioAttributes().getUsage();
I would like to know if there any way to get this information even if I need to use a hidden method or installing the app in system/app
Im building a react-native application.
Im trying to meter the current sound level (in decibel).
Libraries in use: react-native-audio and react-native-sound.
There is anybody familiar with this feature?
Thank you.
With the react-native-audio library, you can get the count for the only iOS.
For the currentMetering in Android, you need to customize in a native module. I have updated it add the following things in your package.json file instead of your code. You will get the currentMetering count for the Android as well as iOS.
"react-native-audio": "git+https://github.com/Harsh2402/react-native-audio.git",
You can use react-native-audio currentMetering value - in order to get the sound level in real-time.
First, you will have to initialise your recorder (which i will assume youve done). I use prepareRecordingAtPath in a similar way to below
AudioRecorder.prepareRecordingAtPath(audioPath, {
SampleRate: 22050,
Channels: 1,
AudioQuality: "Low",
AudioEncoding: "aac",
MeteringEnabled: true
});
then once you've called AudioRecorder.startRecording(); (Note you have access to .pause() and .stop() methods also
Now for handling the audio level, you are going to have to retrieve the data that is returned by the onProgress method. From what i remember, there should be some currentMetering value that you can access. Note that defining this behaviour will trigger the action every time a different decibel reading is retrieved. Like so
AudioRecorder.onProgress = data => {
let decibels = Math.floor(data.currentMetering);
//DO STUFF
};
Hope this helps,
My application requires the ability to know the fundamental audio route the user has selected. On iOS this is trivial, as you just register for a callback and you know exactly where the audio is going.
On Android I was pleased to see the MediaRouter class, however to my dismay it turns out there is no predictable way to determine the route type. For example, when switching to a Bluetooth A2DP device, the only identifying item is the RouteInfo.getName() method, but this returns the friendly name of the A2DP device, so it is impossible to compare against.
I also have tried using the following broadcasts:
AudioManager.ACTION_AUDIO_BECOMING_NOISY
Intent.ACTION_HEADSET_PLUG
BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED
BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED
BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED
However this method is error prone. For example, if you are connected to Bluetooth A2DP, then you plug in headphones, it is easy to tell the route is "Headphones", but then when un-plugging the headphones you have to guess what route is still active, by recording the connected state from all Bluetooth events.
There are also difficulties in ascertaining the initial audio route when your application starts. HEADSET_PLUG is sticky, so that's good, but nothing else is...
Any suggestions on how to approach this and accurately detect this? And why is this such a difficult task in Android?
Here's a very hackish way of polling for the current route, which also supports detection of A2DP. Use at your own risk, as the interals of these classes could very well change in the future. It should work on Jellybean and Jellybean MR1, though.
String ouputDeviceName;
try {
MediaRouter mr = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE);
Class mediaRouterClass = Class.forName("android.media.MediaRouter");
Method getSystemAudioRouteMethod = mediaRouterClass.getMethod("getSystemAudioRoute");
RouteInfo ri = (RouteInfo)getSystemAudioRouteMethod.invoke(mr);
Class mediaRouterStaticClass = Class.forName("android.media.MediaRouter$Static");
Field staticField = mediaRouterClass.getDeclaredField("sStatic");
Field a2dpField = mediaRouterStaticClass.getDeclaredField("mBluetoothA2dpRoute");
AccessibleObject.setAccessible(new AccessibleObject[]{staticField}, true);
AccessibleObject.setAccessible(new AccessibleObject[]{a2dpField}, true);
Object a2dpRoute = a2dpField.get(staticField.get(null));
if (a2dpRoute != mr.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO)) {
// Phone, Headphone, HDMI, etc..
ouputDeviceName = "name: " + ri.getName().toString();
} else {
// Audio is routed to A2DP
ouputDeviceName = "name: A2DP";
}
} catch (Exception e) {
e.printStackTrace();
}