I need to use Android 2.2 (API 8) and I have seen that Normalizer.normalize(text, Normalizer.Form.NFD) is only available from Android API 9.
What can I add to my regex to ignore accents ?
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(text);
for (String keyword : keywords.keySet()) {
String caseInsensitiveRegex = "(?i)\\b" + keyword + "\\b";
Pattern pattern = Pattern.compile(caseInsensitiveRegex);
Matcher m = pattern.matcher(stringBuilder);
while (m.find()){
// Do some stuff
}
}
Thanks per advance for your help ;)
is only available from Android API 9
Android is open sourced project. There's nothing preventing you from grabbing that part of API 9 and putting directly in your app so you will no longer be API dependent and I at the moment I am not seeing any obstacles for doing this in your case.
Related
First of all, nice day to everyone!
My code needs to detect which android version is being used on by means of getprop ro.build.version.release. I do so using systems with root and python for android.
For the time being the devices I tested the code things were working nice but partially of course because I haven't taking into consideration the updates in between new os versions. I just added the new version I was testing on to a dictionary.
So let's say I have this dictionary:
VersionName = {'4.0':"Ice Cream Sandwich", '4.0.4':"Ice Cream Sandwich", '4.1':"Jelly Bean", '4.2':"Jelly Bean", '4.3':"Jelly Bean", '4.4':"KitKat", '5.0':"Lollipop", '5.1':'Lollipop', '6.0':"Marshmallow", '7.1.1':"Nougat"}
I would add:
'4.4.2':'KitKat'
To save and detect the new version I was working on but that's not going to work. To overcome this I just simply made a search to select the first and the last release of an android version.
VersionName = {'Ice Cream Sandwich':['4.0', '4.0.4'], 'Jelly Bean':['4.1', '4.3.1'], 'KitKat':['4.4', '4.4.4'], 'Lollipop':['5.0', '5.1.1'], 'Marshmallow':['6.0', '6.0.1'], 'Nougat':['7.0', '7.1.1']}
The problems comes if the update version is in between the two values.
Given {'KitKat':['4.4', '4.4.4']} and device version 4.4.2 how can I detect if it's part of KitKat
maybe store the min and max as two variables, then do if os(version)> (min value):
then check if os(version) < (max value)
This is how I would approach the problem with the help provided! There are better ways I know that much so if anyone has another method please share.
def DroidName(ReleaseVersion):
# ReleaseVersion = '4.4.2'
VersionValue = {'Ice Cream Sandwich':['4.0', '4.0.4'], 'Jelly Bean':['4.1', '4.3.1'], 'KitKat':['4.4', '4.4.4'], 'Lollipop':['5.0', '5.1.1'], 'Marshmallow':['6.0', '6.0.1'], 'Nougat':['7.0', '7.1.1']}
for i in VersionValue.items():
AndroidName = i[0]
MinimalValue = i[1][0]
MaximunValue = i[1][1]
if ReleaseVersion >= MinimalValue and ReleaseVersion <= MaximunValue:
print AndroidName, ReleaseVersion
break
I am working on a method which extracts the correct version number from a String (for later comparisation if there is a new version).
The String which is being provided unfortunatly has no fixed pattern and can have multiple combinations of digits.
Below code parses the version number but if the string includes for example build 50124 this number is pasted after the extracted version combination which I do not want.
It could also be that combos in the string are possible like for example v1.12 [build452] or v1.32.856 (build 8754) but I already took care of that by substringing the parts as of [ or (.
The method in question:
private String extractVersion(String str){
str = str.substring(str.lastIndexOf('v'),
str.indexOf('[') != -1 ? str.indexOf('[') : str.length()).trim();
str = str.substring(str.lastIndexOf('v'),
str.indexOf('(') != -1 ? str.indexOf('(') : str.length()).trim();
return str.replaceAll("[^0-9?!\\.]", "");
}
I tested it on some examples but unfortunatly the result is not what I want, sometimes digits are pasted behind the actual version number, I refer to the logcat output.
Is there a 'better' regex or another way I can use to improve the method, so it extracts the correct version number?
Thank you for your help.
..
NewVersion = tempWatchList.get(i);
Log.w("Versionnr", extractVersion(NewVersion));
Log.e("Versionname", NewVersion);
..
Logcat outout:
/Versionnr: 5.131 //should be 5.13
/Versionname: somename v5.13b1
/Versionnr: 2.0..4 //should be 2.0
/Versionname: another name 2 v2.0.exp.4
/Versionnr: 18.01 //should be 18.0
/Versionname: somename v18.0-ALPHA1
/Versionnr: 7.2.42221..3634639 //should be 7.2.4222
/Versionname: another name v7.2.4222-1.L.3634639
/Versionnr: 5.0.220170112 //should be 5.0.2
/Versionname: somename v5.0.2 build 20170112
/Versionnr: 4.4.0.201701124401 //should be 4.4.0
/Versionname: another name v4.4.0.20170112b4401
You can use this to extract versions:
Pattern p = Pattern.compile("[0-9]+([.][0-9]+){1,2}");
Matcher m = p.matcher(NewVersion);
m.find();
Log.w("Versionnr", m.group());
This works with all the examples from your logcat messages:
Pattern pattern = Pattern.compile("\\d+\\.\\d+(\\.[\\d]+)?");
Matcher matcher = pattern.matcher(NewVersion);
if (matcher.find()) {
String version = matcher.group();
}
https://regex101.com/r/P7lICp/1
Personally, I would rethink what you are doing.
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?
I am programming an authentication service in Android and this one includes a server part written in java.
I do the same operations in both parts executing these two pieces of codes in Android and Server:
ANDROID:
String genChallengeResponse(String challenge, String message) {
String Hmac_ALG = "HmacSHA256";
SecretKey key = new SecretKeySpec(challenge.getBytes(), Hmac_ALG);
Mac m = Mac.getInstance(Hmac_ALG);
m.init(key);
m.update(password.getBytes());
byte[] mac = m.doFinal();
return new String(Base64.encode(mac, Base64.DEFAULT));
}
SERVER:
String genChallengeResponse(String challenge, String message) {
String Hmac_ALG = "HmacSHA256";
SecretKey key = new SecretKeySpec(challenge.getBytes(), Hmac_ALG);
Mac m = Mac.getInstance(Hmac_ALG);
m.init(key);
m.update(password.getBytes());
byte[] mac = m.doFinal();
return new String(Base64.encodeBase64(mac));
}
Starting from the same challenge and message these are the results:
Android: n2EaLpQr0uKgkZKhCQzwuIFeeLjzZKerZcETVNcfla4=
Server: n2EaLpQr0uKgkZKhCQzwuD9eeLjzZKerZcETVNcfla4=
^^
These are different just for TWO CHARACTERS.
The problem is that this strange behaviour does not appear in every pair of String passed to the functions...
I tried to use the UTF-8 in each system, but nothing changes...
Do someone knows what is the problem? If this is a known problem...
(is important to say that the problem is the same using Android 2.2 or also 4.0, then the problem is not the operating system, I think).
Can't comment yet therefore as answer:
I found out a few weeks ago that Android's Base64 uses different settings for the Linefeeds (check here: http://developer.android.com/reference/android/util/Base64.html )
I think in my case it was NO_WRAP missing.Perhaps one of the other options (NO_PADDING or URL-Safe, does the tested password contain + or - ?) could change your results...
In Android 2.1 this
JSONObject o = new JSONObject();
o.put("MyDate", "/Date(1289334937639)/");
Log.d(TAG, o.toString());
produces
{"MyDate":"/Date(1289334937639)/"}
but in 2.2 it produces
{"MyDate":"\/Date(1289334937639)\/"}
I am talking to a .Net web service so the 2.2 version works correctly for me. How do I make 2.1 produce the same thing without breaking 2.2?
Thanks for your help.
Get the latest version of of JSON from http://www.json.org/java/ and integrate it to your code. You just need to change your imports I guess.
I ended up with the following:
if (Build.VERSION.SDK_INT == 7) {
params = params.replaceAll("/", "\\\\/");
}
where params is the json already converted to a string. Ugly, but it works.