I'm trying to get Mouse Button Events on Android NDK and Android Platform API Level 30
In the handle_input_event callback, I use
// LOGI is just a macro for __android_log_print
case AINPUT_EVENT_TYPE_MOTION:
{
int32_t source = AInputEvent_getSource(event);
if(source & AINPUT_SOURCE_CLASS_POINTER)
{
int32_t button_state = AMotionEvent_getButtonState(event);
LOGI("Button State: %d", button_state); // Logs 0 for everything
if (button_state & AMOTION_EVENT_BUTTON_PRIMARY)
{
LOGI("Left Click");
return 1;
}
else if (button_state & AMOTION_EVENT_BUTTON_SECONDARY)
{
LOGI("Right Click");
return 1;
}
else
{
return 0;
}
}
}
I'm testing the app on the Android Emulator provided by Google
The AMotionEvent_getButtonState is returning 0 for everything
I tried clicking and scrolling with the trackpad on my laptop and a USB Mouse
Even the extra buttons on the mouse, return 0
Every time I click/scroll, it returns 0
Why is this happening?
How can I fix this?
Related
int main(int argc, char* argv[]) {
char* p;
struct inotify_event *event;
int sd, gd, fd;
char buffer[BUF_LEN];
fd = inotify_init();
if( fd < 0) {
return 1;
}
gd = inotify_add_watch(fd, "/sys/devices/system/cpu/cpu2/cpufreq/interactive", IN_MODIFY);
sd = inotify_add_watch(fd, "/sys/class/graphics/fb0/show_blank_event", IN_MODIFY);
for(;;) {
read(fd, buffer, BUF_LEN); //Thread block here. Waits for event triggering
event = (struct inotify_event *) buffer; //Get the event
if(event->mask & IN_MODIFY) {
if(event->wd == sd) {
printf("Handle screen event\n");
//pthread_create(&handle_screen_event, NULL, handleScreenEvent, (void*)NULL);
}
if(event->wd == gd) {
printf("Handle gov event\n"); //This is not triggered after some time of being in standby (screen off) mode. Yet the screen event trigger is always fired
//pthread_create(&handle_gov_event, NULL, handleGovEvent, (void*)NULL);
}
}
}
return 0;
}
So here is the code. I call inotify_add_watch() but after a few minutes with the screen off the "handle gov event" never triggers again. "Handle screen event" always triggers though. I have no idea why its behaving this way. I did add a check for IN_IGNORE to see if the file was getting deleted but it never triggered. I just don't understand how one is working but not the other.
I am running this on an android device. Galaxy S7.
Thanks all.
I've hit a bit of a roadblock with my project. I've tried for hours and can't seem to find out what is causing my problem.
I'm trying to create a box that, when it's closed I can use bluetooth commands and arduino will play a response.
When you open the box, it will play a unique audio clip.
The problem is, the LDR works fine as in the unique clip plays whenever I open the box, however when the box is closed, the bluetooth responses don't play as expected, they just play a tiny snippet of the unique response from when it's open?
So once I open the box, the unique clip plays and the bluetooth responses work as expected.
I've tried using switch cases and for loops but to no avail.
Your help will be much appreciated!
//Coded By: Angelo Casimiro (4/27/14)
//Voice Activated Arduino (Bluetooth + Android)
//Feel free to modify it but remember to give credit
//PCM library used to turn voice file into a string of text for the speaker.
//Credit to HighTechLowTech
#include <SD.h> // need to include the SD library
//#define SD_ChipSelectPin 53 //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 4 //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h> // also need to include this library...
#include <SPI.h>
TMRpcm tmrpcm; // create an object for use in this sketch
int ldrPin = A2; //declared LDR on analog pin 2
int ldrValue = 0; //reading different values from the LDR
//declare voice as a string of data
String voice;
void setup() {
//Speaker pin
tmrpcm.speakerPin = 9;
Serial.begin(9600);
if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
Serial.println("SD fail");
return; // don't do anything more if not
}
}
//-----------------------------------------------------------------------//
void loop() {
while (Serial.available()){ //Check if there is an available byte to read
delay(50); //Delay added to make thing stable
char c = Serial.read(); //Conduct a serial read
if (c == '#') {break;} //Exit the loop when the # is detected after the word
voice += c; //Shorthand for voice = voice + c
}
if (voice.length() > 0) {
Serial.println(voice);
}
//LDR variable defined from analog pin 2
ldrValue = analogRead(ldrPin);
//define LDR value ranges and map them to cases
//if voice string is "marco" then playback the sample array
if(voice == "*marco") {tmrpcm.play("Polo!.wav");}
else if(voice == "*hello") {tmrpcm.play("Hello!.wav");}
else if(voice == "*where") {tmrpcm.play("here.wav");}
else if(voice == "*who") {tmrpcm.play("Scott.wav");}
else if(voice == "*knock knock") {tmrpcm.play("Who.wav");}
else if(ldrValue > 500) {tmrpcm.play("Burp.wav");}
voice="";
delay(1);
}
It might be easier to see in this sketch using switch cases.
Basically, when the box is closed i can see in the serial monitor that case 2 is active which is what I want.
When the box is open, case 1 is active, but it's not playing 'Burp.wav' until I close it again and it switches back to case 2
//Coded By: Angelo Casimiro (4/27/14)
#include <SD.h> // need to include the SD library
//#define SD_ChipSelectPin 53 //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 4 //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h> // also need to include this library...
#include <SPI.h>
TMRpcm tmrpcm; // create an object for use in this sketch
//declare voice as a string of data
String voice;
//LDR value Range
const int sensorMin = 100;
const int sensorMax = 480;
void setup()
{
//Speaker pin
tmrpcm.speakerPin = 9;
Serial.begin(9600);
if (!SD.begin(SD_ChipSelectPin))
{
// see if the card is present and can be initialized:
Serial.println("SD fail");
return; // don't do anything more if not
}
}
//-----------------------------------------------------------------------//
void loop()
{
while (Serial.available())
{
//Check if there is an available byte to read
delay(50); //Delay added to make thing stable
char c = Serial.read(); //Conduct a serial read
if (c == '#')
{
break; //Exit the loop when the # is detected after the word
}
voice += c; //Shorthand for voice = voice + c
}
if (voice.length() > 0)
{
Serial.println(voice);
}
//LDR variable defined from analog pin 2
int sensorReading = analogRead(A2);
Serial.println(sensorReading);
//define LDR value ranges and map them to cases
int range = map(sensorReading, sensorMin, sensorMax, 1, 2);
Serial.println(range);
switch (range)
{
case 1:
{
tmrpcm.play("Burp.wav");
}
break;
case 2:
//if voice string is "marco" then playback the sample array
if (voice == "*marco")
{
tmrpcm.play("Polo!.wav");
}
else if (voice == "*hello")
{
tmrpcm.play("Hello!.wav");
}
else if (voice == "*where")
{
tmrpcm.play("here.wav");
}
else if (voice == "*who")
{
tmrpcm.play("Scott.wav");
}
else if (voice == "*knock knock")
{
tmrpcm.play("Who.wav");
}
voice = "";
break;
}
delay(50);
Serial.println();
}
I have the following strange issue that only occurs on Android 4.1: When the virtual keyboard is opened and the user presses the BACK button, my app just freezes and doesn't react any longer. After a while a system dialog box pops up informing me that the app has died and will be closed. I can hardly imagine that this is a bug in Android because hiding the keyboard by pressing the BACK button is elementary functionality that should just work. Still, my code is so small that I can almost completely rule out an error in my code.
Here is my code for you to review:
static int quit = 0;
static void engine_handle_cmd(struct android_app *app, int32_t cmd)
{
switch(cmd) {
case APP_CMD_TERM_WINDOW:
quit = 1;
break;
}
}
static int32_t engine_handle_input(struct android_app *app, AInputEvent *event)
{
switch(AInputEvent_getType(event)) {
case AINPUT_EVENT_TYPE_MOTION: {
int action = AMotionEvent_getAction(event);
if((action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) showkeyboard(app);
break;
}
}
return 0;
}
void android_main(struct android_app* state)
{
int events, fd;
struct android_poll_source *source;
app_dummy();
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
while(!quit) {
if(ALooper_pollOnce(-1, &fd, &events, (void **) &source) >= 0) {
if(source) source->process(state, source);
}
}
exit(0);
}
The showkeyboard() function is implemented in JNI like this:
static void showkeyboard(struct android_app* state)
{
// Attaches the current thread to the JVM.
jint lResult;
jint lFlags = 0;
JavaVM *lJavaVM = state->activity->vm;
JNIEnv *lJNIEnv = state->activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
jobject lNativeActivity, INPUT_METHOD_SERVICE;
jclass ClassNativeActivity, ClassContext;
jfieldID FieldINPUT_METHOD_SERVICE;
JNIEnv *env;
int attached = 0;
// must check if we're already attached!
switch((*lJavaVM)->GetEnv(lJavaVM, (void**) &env, JNI_VERSION_1_6)) {
case JNI_OK:
break;
case JNI_EDETACHED:
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "NativeThread";
lJavaVMAttachArgs.group = NULL;
lResult = (*lJavaVM)->AttachCurrentThread(lJavaVM, &lJNIEnv, &lJavaVMAttachArgs);
if(lResult == JNI_ERR) return;
attached = 1;
break;
case JNI_EVERSION:
return; // Invalid Java version
}
// Retrieves NativeActivity.
lNativeActivity = state->activity->clazz;
ClassNativeActivity = (*lJNIEnv)->GetObjectClass(lJNIEnv, lNativeActivity);
// Retrieves Context.INPUT_METHOD_SERVICE.
ClassContext = (*lJNIEnv)->FindClass(lJNIEnv, "android/content/Context");
FieldINPUT_METHOD_SERVICE = (*lJNIEnv)->GetStaticFieldID(lJNIEnv, ClassContext, "INPUT_METHOD_SERVICE", "Ljava/lang/String;");
INPUT_METHOD_SERVICE = (*lJNIEnv)->GetStaticObjectField(lJNIEnv, ClassContext, FieldINPUT_METHOD_SERVICE);
{
// Runs getSystemService(Context.INPUT_METHOD_SERVICE).
jclass ClassInputMethodManager = (*lJNIEnv)->FindClass(lJNIEnv, "android/view/inputmethod/InputMethodManager");
jmethodID MethodGetSystemService = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassNativeActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
jobject lInputMethodManager = (*lJNIEnv)->CallObjectMethod(lJNIEnv, lNativeActivity, MethodGetSystemService, INPUT_METHOD_SERVICE);
// Runs getWindow().getDecorView().
jmethodID MethodGetWindow = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassNativeActivity, "getWindow", "()Landroid/view/Window;");
jobject lWindow = (*lJNIEnv)->CallObjectMethod(lJNIEnv, lNativeActivity, MethodGetWindow);
jclass ClassWindow = (*lJNIEnv)->FindClass(lJNIEnv, "android/view/Window");
jmethodID MethodGetDecorView = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassWindow, "getDecorView", "()Landroid/view/View;");
jobject lDecorView = (*lJNIEnv)->CallObjectMethod(lJNIEnv, lWindow, MethodGetDecorView);
// Runs lInputMethodManager.showSoftInput(...).
jmethodID MethodShowSoftInput = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassInputMethodManager, "showSoftInput", "(Landroid/view/View;I)Z");
(*lJNIEnv)->CallBooleanMethod(lJNIEnv, lInputMethodManager, MethodShowSoftInput, lDecorView, lFlags);
if(attached) {
// Finished with the JVM.
(*lJavaVM)->DetachCurrentThread(lJavaVM);
}
}
}
To reproduce, you just have to compile the app, put it onto the emulator with an Android 4.1 image, then click somewhere and the virtual keyboard will be shown. Now try to close the keyboard using the BACK button. The app will freeze now.
Note that this error only occurs on Android 4.1. It works fine on 2.3, 3.0 and 4.0. Could this be a major bug in Android itself? I really have no other explanation because my code is really just a primitive main loop that doesn't do anything at all. But still, trying to close the virtual keyboard will crash the app.
Thanks a lot for help on this issue! I have been grappling with this for hours now :(
UPDATE 1:
The issue also appears on Android 4.2. A ticket has been opened on the Android issues site. Everybody who experiences the same problem should comment on the ticket so that the Android developers become aware of it. Here is the link:
http://code.google.com/p/android/issues/detail?id=43817&thanks=43817&ts=1359632204
Thanks for asking this, it helped me.
I was seeing the freezes too. It seems to be coming from AInputQueue_preDispatchEvent in process_input in android_native_app_glue.c. To work around it, I changed:
LOGI("New input event: type=%d\n", AInputEvent_getType(event));
if (AInputQueue_preDispathEvent(app->inputQueue, event)) {
return;
}
int32_t handled = 0;
to:
int32_t type = AInputEvent_getType(event);
LOGI("New input event: type=%d\n", type);
if (!g_iShowingSoftKeyboard || (type != AINPUT_EVENT_TYPE_KEY)
|| (AKeyEvent_getKeyCode(event) != AKEYCODE_BACK))
{
if (AInputQueue_preDispathEvent(app->inputQueue, event)) {
return;
}
}
int32_t handled = 0;
of course g_iShowingSoftKeyboard is the global that I am using that is true if the soft keyboard is showing.
Edit: and I close the soft keyboard where I handle the back press in my input handler.
I tried to get the SLDeviceVolumeItf interface of the RecorderObject on Android but I got the error: SL_RESULT_FEATURE_UNSUPPORTED.
I read that the Android implementation of OpenSL ES does not support volume setting for the AudioRecorder. Is that true?
If yes is there a workaround? I have a VOIP application that does not worl well on Galaxy Nexus because of the very high mic gain.
I also tried to get the SL_IID_ANDROIDCONFIGURATION to set the streamType to the new VOICE_COMMUNINCATION audio-source but again I get error 12 (not supported).
// create audio recorder
const SLInterfaceID id[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
result = (*engine)->CreateAudioRecorder(engine, &recorderObject, &audioSrc, &audioSnk, 2, id, req);
if (SL_RESULT_SUCCESS != result) {
return false;
}
SLAndroidConfigurationItf recorderConfig;
result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDCONFIGURATION, &recorderConfig);
if(result != SL_RESULT_SUCCESS) {
error("failed to get SL_IID_ANDROIDCONFIGURATION interface. e == %d", result);
}
The recorderObject is created but I can't get the SL_IID_ANDROIDCONFIGURATION interface.
I tried it on Galaxy Nexus (ICS), HTC sense (ICS) and Motorola Blur (Gingerbread).
I'm using NDK version 6.
Now I can get the interface. I had to use NDK 8 and target-14.
When I tried to use 10 as a target, I had an error compiling the native code (dirent.h was not found).
I had to use target-platform-14.
I ran into a similar problem. My results were returning the error code for not implemented. However, my problem was that I wasn't creating the recorder with the SL_IID_ANDROIDCONFIGURATION interface flag.
apiLvl = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
SLint32 streamType = SL_ANDROID_RECORDING_PRESET_GENERIC;
if(apiLvl > 10){
streamType = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
I("set SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION");
}
result = (*recorderConfig)->SetConfiguration(recorderConfig, SL_ANDROID_KEY_RECORDING_PRESET, &streamType, sizeof(SLint32));
if (SL_RESULT_SUCCESS != result) {
return 0;
}
Even i tried to find a way to change the gain in OpenSL, looks like there is no api/interface for that. i implemented a work around by implementing a simple shift gain multiplier
void multiply_gain(void *buffer, int bytes, int gain_val)
{
int i = 0, j = 0;
short *buffer_samples = (short*)buffer;
for(i = 0, j = 0; i < bytes; i+=2,j++)
{
buffer_samples[j] = (buffer_samples[j] >> gain_val);
}
}
But here the gain is multiplied/divided (based on << or >>) by a factor or 2. if you need a smoother gain curve, you need to write a more complex digital gain function.
Does anyone know how the RIL (/hardware/reference/reference-ril/) determines what gets mounted in /dev/ when the baseband radio gets initiated?
In older phones and in other documentation, GSM phones use /dev/smd0. Not all phones use /dev/smd0. I am trying to determine a way to find out what gets mounted regardless of the type of radio and vendor.
If someone can specifically identify where in the /hardware/reference/reference-ril/ I can see where this is set and where it's pulling the info from upon initialization, that would be perfect.
RIL is in your application Framework.
if you want to see the RIL and Implements the functionality with use of command prompt it is done.
There is below command :
void (*RIL_RequestFunc) (int request, void *data, size_t datalen, RIL_Token t);
I found this from here:
you are serious about this please go through link:
RIL Study LInk
If you want to know about example :
GIT HUB
It actually depends on what interface you are using to connect. You might use USB, UART or SPI interface to connect the upper layer with the modem. The paramter passed in the RIL_Init function determines the device you are trying to connect to. If you want to know specifically where this is done, please see the RIL_Init function in reference-ril.c.
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
int ret;
int fd = -1;
int opt;
pthread_attr_t attr;
s_rilenv = env;
while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
switch (opt) {
case 'p':
s_port = atoi(optarg);
if (s_port == 0) {
usage(argv[0]);
return NULL;
}
RLOGI("Opening loopback port %d\n", s_port);
break;
case 'd':
s_device_path = optarg;
RLOGI("Opening tty device %s\n", s_device_path);
break;
case 's':
s_device_path = optarg;
s_device_socket = 1;
RLOGI("Opening socket %s\n", s_device_path);
break;
default:
usage(argv[0]);
return NULL;
}
}
if (s_port < 0 && s_device_path == NULL) {
usage(argv[0]);
return NULL;
}
sMdmInfo = calloc(1, sizeof(ModemInfo));
if (!sMdmInfo) {
RLOGE("Unable to alloc memory for ModemInfo");
return NULL;
}
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
return &s_callbacks;
}
I hope things are clear now.