KeyCharacterMap to use from code only - android

I need to insert a special character into my Android app that is not included in any the existing KeyCharacterMap files. Generating key events is the only way I see to get any active control without knowing which one.
To load this map in order to generate the KeyEvent from I have to specify the map's id but this ID comes from an InputDevice and there is no such device for my newly generated kcm file.
What is the best way to either use this keymap without an existing inputdevice or fake the inputdevice?

I believe that you can generate special key with this solution :
char[] szRes = szStringText.toCharArray(); // Convert String to Char arra
KeyCharacterMap CharMap;
if(Build.VERSION.SDK_INT >= 11) // My soft runs until API 5
CharMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
else
CharMap = KeyCharacterMap.load(KeyCharacterMap.ALPHA);
KeyEvent[] events = CharMap.getEvents(szRes);
for(int i=0; i<events.length; i++)
MainWebView.dispatchKeyEvent(events[i]); // MainWebView is webview
You can build the string[] szStringText with "!/§)". Normally, the code convert charactere. Source : https://www.codota.com/code/java/classes/android.view.KeyCharacterMap

Related

Android: How to interpret pwi (Power Use Item) from battery stats dumpsys

I am currently trying to understand the output of my batterystats after following the instructions listed here by Google: https://developer.android.com/studio/command-line/dumpsys#inspect_machine-friendly_output
In the identifiers section there is something call "pwi" or Power Use Item and it mentions that it can be read as label/mAh, but when I look at my output I do not seem to understand what it is telling me.
10254 l pwi uid 84.8 0 51.0 112
Is 84.8 the label and 0 is the mAh? What kind of information can I learn from this?
So what I've been able to find is that the line is being printed in: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/os/BatteryStats.java
search for POWER_USE_ITEM_DATA using the search webpage Find button tool. I think what you are seeing is dumpLine on line #4563,
private static final String POWER_USE_ITEM_DATA = "pwi";
final ProportionalAttributionCalculator proportionalAttributionCalculator =
new ProportionalAttributionCalculator(context, stats);
final List<UidBatteryConsumer> uidBatteryConsumers = stats.getUidBatteryConsumers();
for (int i = 0; i < uidBatteryConsumers.size(); i++) {
UidBatteryConsumer consumer = uidBatteryConsumers.get(i);
dumpLine(pw, consumer.getUid(), category, POWER_USE_ITEM_DATA, "uid",
formatCharge(consumer.getConsumedPower()),
proportionalAttributionCalculator.isSystemBatteryConsumer(consumer) ? 1 : 0,
formatCharge(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)),
formatCharge(
proportionalAttributionCalculator.getProportionalPowerMah(consumer)));
}
which appears to have the right number of fields and the '0' you are referring to is a boolean flag (system process==1 perhaps), otherwise the later items represent mAh.
In the code search site, you can click on ProportionalAttributionCalculator class to see the method's source code. I believe that file is where the other battery stats are output, so your output may require context values displayed elsewhere.

AWS DynamoDB Scan failing on iOS but works on Android

I am using DynamoDB as back-end database for my mobile app, and the schema etc are identical across Android & iOS. For a particular use-case, I have to perform a Scan, based on two attributes which are not indexed. For iOS Objective C, I am using the following code:
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
scanExpression.limit = [NSNumber numberWithInt:maxCount];
scanExpression.filterExpression = #"#l = :location AND event = :event";
scanExpression.expressionAttributeNames = #{#"#l":#"location"};
scanExpression.expressionAttributeValues = #{#":location":location,
#":event":EVENT_TASTING};
Both location and event are Strings. EVENT_TASTING is a String constant. This scan keeps returning zero results, even though I have validated that for the provided entries I should be receiving the results. I use the following code in Android Java:
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
scanExpression.setLimit(maxCount);
scanExpression.addFilterCondition("location",
new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(location)));
scanExpression.addFilterCondition("event",
new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(Constants.EVENT_TASTING)));
The scan works as expected in Android. What needs to change in iOS to make it work there too? I updated iOS SDK to 2.3.6 but it has not made a difference. This is the only scan operation I am doing in my code.
Is there an error in my scanExpression for iOS? Is there a way I can use the Android-style syntax to make this work on iOS?
Update
I tried the following changes:
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
AWSDynamoDBAttributeValue *locationVal = [AWSDynamoDBAttributeValue new];
locationVal.S = location;
AWSDynamoDBAttributeValue *eventVal = [AWSDynamoDBAttributeValue new];
eventVal.S = EVENT_TASTING;
scanExpression.limit = [NSNumber numberWithInt:maxCount];
scanExpression.filterExpression = #"#l = :location AND event = :event";
scanExpression.expressionAttributeNames = #{#"#l":#"location"};
scanExpression.expressionAttributeValues = #{#":location":locationVal,
#":event":eventVal};
But now I am getting an error:
The request failed. Error: [Error Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "(null)" UserInfo={message=ExpressionAttributeValues contains invalid value: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes for key :location, __type=com.amazon.coral.validate#ValidationException}]
Thanks to the hint from #YosukeMatsuda, I was able to fix this by calling Scan repeatedly until LastEvaluatedKey is empty. I am posting this as answer because unfortunately Mike's answer is not pointing out the correct issue and is misleading.
Here's how I changed the code in iOS:
// In a different method (for first call):
AWSDynamoDBScanExpression *scanExpression = // See code in original question
// In a new method that can be called recursively:
// DynamoDBObjectMapper scan:class-for-model expression:scanExpression
// continueWithBlock -> if (task.result):
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
if (paginatedOutput.items.count != 0)
// Append the paginatedOutput.items to the cumulative array
else
// Replace the cumulative array with paginatedOutput.items
if (paginatedOutput.lastEvaluatedKey.count == 0) {
// Scan is complete - handle results
} else {
// Check if you have sufficient results
// In my case I had asked for 25 results but was getting 39
// So it doesn't seem to obey the scanExpression.limit value
// If more results are needed, continue the scan
[scanExpression setExclusiveStartKey:paginatedOutput.lastEvaluatedKey];
// Call this method recursively
}
If there is a more elegant solution I'd love to hear it. But at least it works now.
There are several differences between the Android code you're using and the ObjectiveC version.
in the Android Version you're using the older Filter Condition API while in the ObjectiveC you're using the more modern Filter Expression API; this doesn't necessarily make the newer one fail but it's just something to point out
in the case of ExpressionAttributeValues, the values for location and event that you're passing in should be of type AWSDynamoDBAttributeValue *, not strings; if you make this change your query will most likely start working.
I hope this answers your question but can't be certain because you only say "this works as expected in Android - how can I make it work in iOS" but you're not telling us what's broken.

Android support of dictionary based BreakIterator

I have the following same code run in API level 16 vs API level 21, and I found that in API level 16, the dictionary based iterator (tokenizer) seems not working, while in API level 21, the dictionary based iterator is working properly.
BreakIterator it = BreakIterator.getWordInstance();
String txt = "我们一起";
it.setText(txt);
int start = it.first();
int end = it.next();
buf = new StringBuffer();
while (end != BreakIterator.DONE) {
String word = txt.substring(start,end).trim();
if (!word.isEmpty()) {
buf.append(word);
buf.append("+");
}
start = end;
end = it.next();
}
vw.setText(buf);
In API Level 21, the text view shows ("我们" is a word, "一起" is a word)
我们+一起+
However in API Level 16, it shows as below (each Chinese character is a word):
我+们+一+起+
So I suspect that the API level 21 has enabled the dictionary based iterator, while previous API versions not.
However, after I have a search in the C++ source code of Android, I found that the key function RuleBasedBreakIterator::checkDictionary is both there in rbbi.cpp, for both API levels. It gives me the hints that both API shall support dictionary based iterator. I also suspect that the difference is because of the different category value set for different char-set. However I am not able trace back how these values are set and whether there is difference.
My question is, how to further confirm that the API implementation is enhanced in API level 21?

Android /dev/uinput does not work

I'm trying to control Android by writing data into /dev/uinput. For example, if I enter 'A' on my desktop, the codes will write something according to key_code into uinput and Android should behave like I input an 'A' on the phone. I am following the codes in RemoteInput. I tested on Nexus 4 with JB 4.2 system. All the ioctls return positive results, which means it should work. However, when I put in an 'A', the Android only seems to refresh the virtual keyboard and does not input anything.
First, you need to "register" the supported keys using ioctl(m_fd, UI_SET_KEYBIT, key). For A, you should use KEY_A, which is defined in linux/input.h (#define KEY_A 30) and not KEYCODE_A, which is a different code. In my experience, /dev/uinput on Android works with Linux key codes.
You should:
open /dev/uinput
ioctl(m_fd, UI_SET_EVBIT, EV_KEY) - support EV_KEY event
ioctl(m_fd, UI_SET_EVBIT, EV_SYN) - support EV_SYN event
ioctl(m_fd, UI_SET_KEYBIT, key) - support key - for each keycode that you want to support
create uinput_user_dev structure and populate it, then write that structure to /dev/uinput file descriptor (see below)
call ioctl(m_fd, UI_DEV_CREATE) to create this device; the m_fd will now point to newly created device.
Do monitor logcat output and check if the device will be created successfully. It will take a generic keychar map and key layout, since no keymap is defined. If you want to define it, look into /system/usr/keychars and /system/usr/keylayout.
Create uinput device
uinput_user_dev uidev;
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-test");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1212;
uidev.id.product = 0xabab;
uidev.id.version = 3;
write(m_fd, &uidev, sizeof(uidev)

sendKeys - Send special characters

addressBar = (AutoCompleteTextView) mActivity.findViewById(package.R.id.addressBar);
TouchUtils.tapView(this, addressBar);
sendKeys("1"); //Works
sendKeys("G M A I L"); // Works - Result would be "gmail"
sendKeys("G M A I L . C O M"); // Doesn't work
sendKeys("{.}"); // Doesn't work
sendKeys("gmail") // Doesn't work
sendKeys("G M A I L {.} C O M") //Doesn't work
I am writing android test scripts using "InstrumentationTestCase2". I actually want to sendkeys - "gmail.com" but, unable to send special character "."(Dot)
For '.' (period or dot) you can try the int equivalent values of it.
Like,
sendKeys(56);
From Android-Docs
public static final int KEYCODE_PERIOD
Key code constant: '.' key.
Constant Value: 56 (0x00000038)
"The sequence of keys is a string containing the key names as specified in KeyEvent, without the KEYCODE_ prefix." (sendKeys documentation)
So you can use NUMPAD_DOT in the sendKeys string.
e.g.
sendKeys("G M A I L NUMPAD_DOT C O M");
For Further information see :
(http://developer.android.com/reference/android/test/InstrumentationTestCase.html#sendKeys(java.lang.String))
sendKeys(56); // for special character "." (Dot)
Have you tried the following:
getInstrumentation().sendStringSync("Do.You#Love.IT???");
works like magic and makes life a lot simpler!

Categories

Resources