IOIO board on Android: Working with external interrupts and change notifications - android

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

Related

What is the best way to execute asynchronous code inside CameraX analyze()?

I'm using CameraX's image analysis use case that keeps calling the analyze() method in my custom Analyzer class. Inside analyze(), before doing anything else, I need to send a request to a connected device and wait for its response; the latency is very low and I'm already doing it synchronously with no issues, but I was told it's better to make it asynchronous just in case the device responds too slowly.
I know that MLKit's process() returns a Task<List<T>> and I already call onSuccessListener { } on it, so I was wondering if I can use a similar approach (I can't return a Task<T> from my function, how do I create one?). Otherwise would you suggest threads, or coroutines, or something else?
Edit: below there's a simplified example of what I'm trying to do. For a given frame sent by the camera I just need to perform only the current analysis in line, then I return so that analyze() will be called again with the next frame, on which it will perform the next analysis.
It might look hacky but it's for an app that continuously runs in foreground on a single-purpose device (let's call it Dev A) with no user interaction provided by touch or other conventional means, so it needs some kind of trigger to start doing what is required.
The trigger might as well be when the first image analysis in line is successful, but running MLKit or TFLite models from real time camera feed all day long makes Dev A overheat excessively. The best solution so far seems to be waiting for the trigger to come from an external device (Dev B) that operates independently.
Since Dev B may respond with some delay I need to communicate with it asynchronously, hence the reason for the question in the first place. While there are certainly several architectural nuances to discuss, the current root of the problem is that I can't decide (or rather I don't know) how to handle the repeating "connection" with Dev B in a non-blocking way.
I mean, can I just treat this issue like any other case where multithreading is needed, or the fact that the camera is involved might pose additional threats? The backpressure strategy is set to STRATEGY_KEEP_ONLY_LATEST, so in theory if the current call to analyze() hasn't finished yet the new frames are dropped and nothing bad happens even if inside the method I'm still waiting for the async call to Dev B to finish, or am I missing something?
var connected = false
lateinit var result: Boolean
var analysis1 = true
var analysis2 = true
override fun analyze() {
if (!connected) {
result = connectToDevice() // needs to be async
connected = true
}
// need positive result to proceed, otherwise start over
if (!result) {
connected = false
return
}
if (analysis1) {
// perform analysis #1...
analysis1 = false
// when an analysis is done, exit early and perform next analysis on next frame
return
}
if (analysis2) {
// perform analysis #2...
analysis2 = false
// same as above
return
}
// when all analyses are done, reset all flags to start over
connected = false
analysis1 = true
analysis2 = true
}

How to run a built-in call app when a device gets incoming call in onCallAdded(InCallService) function?

When a phone is ringing ( by an incoming call) If the phone number is a specific number I want to show my custom UI. If It is not, I want to pass it to the (built-in) system call app(Or any other call app is okay).
I should use 'InCallService' and the device set my app as 'a default call app' so that even when the phone screen is locked my custom-UI-activity be shown. The following kotlin source code is my goal.
override fun onCallAdded(call: Call) {
//app should receive a new incoming call via 'onCallAdded'
super.onCallAdded(call)
val phoneNumber = getPhoneNumber(call)
if (isMyTargetNumber(phoneNumber)) {
//show my custom UI
} else {
//run a built-in call app
}
}
The problem that I want to solve is how to run a built-in call app appropriately. I mean I want to complete to wirte the blank of 'else'
else {
//run a built-in call app
}
Apps on the android market like 'truecaller' or 'whosecall' works well the way I want to acheive. I want to make my app such apps. Please help me and advise something to me.

Setting sound configuration for Socket device

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.

State Machine inside Android - Stop onActivityResult breaking game while loop flow

I am trying to implement a State Machine into my Android game (note that it is not a game that needs to be constantly redrawn with a UI as it just works using standard Android Activity structure). I have found this example below of how you can implement a State Machine with a switch statement:
main() {
while(true) {
collectInput(); // deal with common code for filling in keyboard queues, determining mouse positions, etc.
preBookKeeping(); // do any other work that needs constant ticks, like updating streaming/sound/physics/networking receives, etc.
runLogic(); // see below
postBookKeeping(); // again any stuff that needs ticking, but would want to take into account what happened in runLogic this frame, e.g. animation/particles/networking transmit, etc
drawEverything(); // any actual rendering actions you need to take
}
}
runLogic() {
// this is where you actually have a state machine
switch (state) {
case WaitingForInput:
// look at the collected input and see if any of it is actionable
case WaitingForOpponent:
// look at the input and warn the player that they are doing stuff that isn't going to work right now e.g. a "It's not your turn!" notification.
// otherwise, use input to do things that might be valid when it's not the player's turn, like pan around the map.
case etc:
// a real game would have a ton more actual states, including transition states, start/end/options screens, etc.
}
}
Whilst transitioning my game from the loop below to the State Machine, I am having issues. If say from this main game Activity, I launch another Activity in order to ask the player a question (happens inside playTurn()), I will then obviously utilise onActivityResult() and return the player's answer to the main game Activity. How should I handle the return of the player's answer and allow the code to then continue running in playTurn(), inside the main playGame() loop, without breaking the while loop flow? The only way I actually can figure out is by utilising a while loop inside playTurn() that simply keeps looping whilst the answer is 0 but that seems horrifically wasteful. Thanks in advance, any help is appreciated!
public void playGame() {
initialise();
boolean finished = false;
while (!finished) {
playTurn();
// Check if there is a winner after each turn is played
boolean winner = winner();
if (winner) {
finished = true;
}
}
}

Intercept joystick input events

I am developing an android IME for joysticks. It consists of a Thread that is constantly listening events from a specific device, and then if some conditions are true decides to do something. Is there a way to exclusively bind input events from this device to my IME, so that they won't propagate to applications?
I tried using ioctl(fd,EVIOCGRAB,1) inside a native library to take exclusive control of my device but it doesn't seem to work.
Update: EVIOCGRAB works fine and that's how I solved the problem!
For who's interested I finally found the way to do it:
use this on your "source" device (it is native code that you can use together with libEventInjector):
int fd = open("/dev/input/eventX", O_RDONLY);
if(fd<0) return;
if(ioctl(fd,EVIOCGRAB,1) <0) return;
if everything goes ok the library will have exclusive access to the device, now in your IME start a thread that keeps reading /dev/input/eventX so that you can read the events but they won't propagate to elsewhere.
UPDATE: EVIOCGRAB gives exclusive control only to an instance of a function of your Java class. The best way to intercept events without blocking the device when you close your program is this:
public class Class extends Thread{
boolean running = true;
public void run(){
mySourceDevice.getExclControl();
while(running){
}
mySourceDevice.releaseExclControl();
}
public void interrupt(){
runing=false;
super.interrupt();
}
}

Categories

Resources