Android Camera API ISO Setting? - android
Would anyone know where to control the ISO setting for the camera from in the Android SDK ?
It should be possible as the native camera application on the HTC Desire has ISO settings.
you should take a look at the methods flatten(), unflatten(), get(String key), set(String key, String value) in android.hardware.Camera.Parameters.
Also consider the source code of that class. It might make things clearer.
First you need to obtain the Camera.Parameters. Unflatten it to a String and investigate it. I am developing on a HTC Desire as well an get the following String:
sharpness-max=30;zoom=0;taking-picture-zoom=0;zoom-supported=true;sharpness-min=0;sharpness=10;contrast=5;whitebalance=auto;jpeg-quality=100;preview-format-values=yuv420sp;jpeg-thumbnail-quality=75;preview-format=yuv420sp;preview-size=640x480;focal-length=3.53;iso=auto;meter-mode=meter-center;front-camera-mode=mirror;flash-mode-values=off,auto,on,torch;preview-frame-rate-values=15;preview-frame-rate=15;focus-mode-values=auto,infinity;jpeg-thumbnail-width=640;jpeg-thumbnail-size-values=640x480,512x384,384x288,0x0;zoom-ratios=100,114,131,151,174,200;saturation-def=5;preview-size-values=1280x720,800x480,768x432,720x480,640x480,576x432,480x320,400x240,384x288,352x288,320x240,272x272,240x240,240x160,176x144,160x120;smart-contrast=off;picture-size-values=2592x1952,2592x1456,2592x1936,2592x1728,2592x1552,2048x1536,2048x1360,2048x1216,2048x1152,1600x1200,1584x1056,1280x960,1280x848,1280x768,1280x720,1024x768,640x480,640x416,640x384,640x368,512x384,400x400,272x272;contrast-min=0;min-exposure-compensation=-4;brightness-min=0;antibanding=auto;taking-picture-zoom-min=0;saturation-min=1;contrast-max=10;vertical-view-angle=42.5;taking-picture-zoom-max=21;contrast-def=5;brightness-max=6;horizontal-view-angle=54.8;brightness=3;jpeg-thumbnail-height=480;cam-mode=0;focus-mode=auto;sharpness-def=10;front-camera-mode-values=mirror,reverse;picture-format-values=jpeg;saturation-max=10;max-exposure-compensation=4;exposure-compensation=0;exposure-compensation-step=0.5;flash-mode=off;effect-values=none,mono,negative,solarize,sepia,posterize,aqua;meter-mode-values=meter-average,meter-center,meter-spot;picture-size=2592x1952;max-zoom=5;effect=none;saturation=5;whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight;picture-format=jpeg;brightness-def=3;iso-values=auto,deblur,100,200,400,800,1250;enable-caf=off;antibanding-values=off,50hz,60hz,auto
So basically there is a key called iso-values to retrieve the supported values and a key iso which holds the current value.
You can do the following:
Camera cam = Camera.open();
Camera.Parameters camParams = cam.getParameters();
String supportedIsoValues = camParams.get("iso-values"); //supported values, comma separated String
camParams.set("iso", (String)newValue);
cam.setParameters(camParams);
And with reference to the unflattened parameters I would assume that there is a difference between the iso and exposure compensation settings.
By now (KK 4.4.2) android has no official APIs to manage ISO.
ISO management is a totally device dependant matter, and 8/18 devices i tested so far doesn't support ISO settings at all.
Investigate Camera.getParameters().flatten() String to check valid keywords, every device can use different keywords!!
Most devices use "iso-values" keyword to define a comma separated list-of-possible-values to use with "iso" keyword, like this:
param.set("iso", valid_value_from_list);
Some other devices uses "iso-mode-values" and "iso" keywords (Galaxy Nexus).
I found also a device that uses "iso-speed-values" and "iso-speed" (Micromax A101).
Another one that make me sad is "nv-picture-iso-values" -> "nv-picture-iso" (LG dual P990).
Follow szia answer on how to use these keywords.
Here's some code i use to get a list of valid values using known keywords:
String flat = param.flatten();
String[] isoValues = null;
String values_keyword=null;
String iso_keyword=null;
if(flat.contains("iso-values")) {
// most used keywords
values_keyword="iso-values";
iso_keyword="iso";
} else if(flat.contains("iso-mode-values")) {
// google galaxy nexus keywords
values_keyword="iso-mode-values";
iso_keyword="iso";
} else if(flat.contains("iso-speed-values")) {
// micromax a101 keywords
values_keyword="iso-speed-values";
iso_keyword="iso-speed";
} else if(flat.contains("nv-picture-iso-values")) {
// LG dual p990 keywords
values_keyword="nv-picture-iso-values";
iso_keyword="nv-picture-iso";
}
// add other eventual keywords here...
if(iso_keyword!=null) {
// flatten contains the iso key!!
String iso = flat.substring(flat.indexOf(values_keyword));
iso = iso.substring(iso.indexOf("=")+1);
if(iso.contains(";")) iso = iso.substring(0, iso.indexOf(";"));
isoValues = iso.split(",");
} else {
// iso not supported in a known way
}
since I had the same problem of finding if the device has an ISO parameter I looked at this answer https://stackoverflow.com/a/23567103/3976589 and saw that #j.c had solved the problem for 8/18 devices by listing some parameters that he had found on different devices. Based on that listing I found that each paramter contains the words iso and values (sometimes only those words, sometimes something additional).
So if I list all of the camera parameters and search for a strings that contain both words I will know what is the name of the ISO parameter, if it exists. Furthermore if the parameter exists I can take the supported ISO values and if I want to set one of those values i.e. change the camera parameter, I can just remove the -values at the end of the iso-values parameter and then I can change the ISO value successfully.
I will now share my code for this task. First a snippet that retrieves a list with supported ISO values.
private String ISOValuesParameter = null;
private String ISOParameter = null;
private String ISOValues = null;
private void initCamera() {
Camera mCamera = Camera.open();
// this will list supported values
String ISOvalues = getISOValues();
textViewISO = (TextView) findViewById(R.id.viewISO);
textViewISO.setText(ISOvalues);
// setting Minimum ISO value
if(ISOValuesParameter != null) {
Camera.Parameters params = mCamera.getParameters();
ISOParameter = ISOValuesParameter.replace("-values", "");
params.set(ISOParameter, getMinISO());
mCamera.setParameters(params);
// get the updated ISO value
params = mCamera.getParameters();
String ISO = params.get(ISOParameter);
Toast.makeText(this,"ISO set to: " + ISO, Toast.LENGTH_SHORT).show();
}
}
// returns a list with supported ISO values
private String getISOValues() {
ISOValuesParamter = getISOValuesParameter();
Camera.Parameters params = mCamera.getParameters();
ISOValues = params.get(ISOValuesParamter);
return ISOValues!=null ? ISOValues : "ISO not supported";
}
// this will return the name of the ISO parameter containing supported ISO values
private String getISOValuesParameter() {
Camera.Parameters params = mCamera.getParameters();
String flatten = params.flatten();
String[] paramsSeparated = flatten.split(";");
for(String cur : paramsSeparated) {
if(cur.contains("iso") && cur.contains("values")) {
return cur.substring(0,cur.indexOf('='));
}
}
return null;
}
This snippet only lists the supported ISO values. In my application I needed to pick the lowest ISO. Here is my solution:
private String getMinISO() {
if(ISOValues == null) {
return null;
}
String[] ISOarray = ISOValues.split(",");
Arrays.sort(ISOarray, myComparator);
String minISO = ISOarray[ISOarray.length-1];
return minISO;
}
Here myComparator is a class that compares two strings and sorts the array in descending order. All alphabet words are at the beginning and all numbers are at the end. Here is my implementation:
// Singelton class
public class MyComparator implements Comparator<String> {
private static MyComparator myComparator = null;
private MyComparator() {}
#Override
public int compare(String a, String b) {
return compareString(a,b);
}
public static int compareString(String a, String b) {
if (a.length() > b.length())
return -1;
if (a.length() == b.length()) {
if (a.compareTo(b) > 0)
return -1;
else if (a.compareTo(b) == 0)
return 0;
}
return 1;
}
public static synchronized MyComparator getInstance() {
if(myComparator==null) {
myComparator = new MyComparator();
}
return myComparator;
}
}
I hope my answer helps other people. :)
Cheers!
#ee3509
szias answer is correct.
Only
String supportedIsoValues = camParams.get("iso-values");
returns null on some devices.
Nevertheless you can set the iso by
Camera cam = Camera.open();
Camera.Parameters camParams = cam.getParameters();
camParams.set("iso", "400"); // values can be "auto", "100", "200", "400", "800", "1600"
cam.setParameters(camParams);
I do not know whether "800" or "1600" is supported on all devices
you can check what you did by
String newVAlue = camParams.get("iso");
Forgive my ignorance, but how is this different from "exposure compensation" set via setExposureCompensation()? Wikipedia has some of the conversion formulas you might find useful.
Related
Android Contacts Search: Using dialpad keys (alphabets combinations/permutations)
I am trying to a build an Android Dialer App (MinSDK 23). I'd like to implement a contacts search (usually available in default dialer apps and other third party dialer apps) like below: As I type digits on dial pad e.g. 245 I should be able to search contacts having phone numbers containing '245' as well as their names containing matches for alphabetical combinations of the digits 245, that as per my calculation should be 27 unique combinations. While I do know it's a permutations problem and I might be able to search by applying OR 'LIKE' filters on Contacts Name, this doesn't seem efficient enough and it will cause more performance issues as I keep typing e.g. 245658. How do we do this efficiently? Is there any built-in search mechanism for searching android contacts this way or any better custom solution exists?
I can Filter 1500+ Contact in only 0.5 second , You can create same as List< String> or you can go with Object like List< Contact> and just change condition import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; class Scratch { public static void main(String[] args) { List<String> contactList= new ArrayList<String>(); contactList.add("Jason Arnold 9875454454"); contactList.add("Joshua Ferguson 789455482121"); contactList.add("Sarah Churchill 78452165982"); contactList.add("Brandon Walsh 78452121"); contactList.add("Justin Cameron 452197821"); contactList.add("Rebecca Howard 784521983232"); contactList.add("Trevor Smith 372753221"); contactList.add("Heather Fraser 9884562145"); contactList.add("Caroline Peters 6598421"); contactList.add("Chloe Lyman"); HashMap<String, String> hm = new HashMap<String, String>(); hm.put("2", "[2abc]"); hm.put("3", "[3def]"); hm.put("4", "[4ghi]"); hm.put("5", "[5jkl]"); hm.put("6", "[6mno]"); hm.put("7", "[7pqrs]"); hm.put("8", "[8tuv]"); hm.put("9", "[9wxyz]"); hm.put("1", "[1]"); hm.put("0", "[0]"); Instant startTime = Instant.now(); String findContact = "3727"; // todo String regEx = ""; for (int i = 0; i < findContact.length(); i++) { regEx = regEx + hm.get(findContact.charAt(i) + ""); } String finalRegEx = "^"+regEx+".*$"; System.out.println("!_!_" + finalRegEx); List<String> ll = contactList.stream().filter(s -> isMatched(s, finalRegEx)) .collect(Collectors.toList()); for (int i = 0; i < ll.size(); i++) { System.out.println("-->: " + ll.get(i)); } Instant current = Instant.now(); System.out.println("\nFound List size: " + ll.size()); long milliseconds = (current.toEpochMilli() - startTime.toEpochMilli()); System.out.println("\nmilliseconds: " + milliseconds); } private static boolean isMatched(String str, String finalRegEx) { String[] arrOfStr = str.split("\\s"); for (String a : arrOfStr) { if (a.toUpperCase().matches(finalRegEx.toUpperCase())) return true; } return false; } } Result : Trevor Smith 372753221 (as Phonenumber start with 3727) Heather Fraser 9884562145 (as Last name match with 3727 dial pad keys)
That's a classic interview question in our company. First of all, don't hit the ContactsContract APIs for every digit typed, you'll need to run a single query during launch to get all names from the Contacts DB so you'll be able to quickly search over them in memory. Something like: Map<String, Long> namesMap = new HashMap<>(); String[] projection = new String[]{Contacts._ID, Contacts.DISPLAY_NAME}; Cursor c = getContentResolver().query(Contacts.CONTENT_URI, projection, null, null, null); while (c != null && c.moveToNext()) { namesMap.put(c.getString(1), c.getLong(0)); } c.close(); Next, the nicest way to filter the above NamesMap to get only names to fit the search digits is to generate a regex pattern. So a search query for 245 will generate the regex: .*[2abc][4ghi][5jkl].*, that shouldn't be too hard to build, every digit is mapped to a fixed string: 2 -> [2abc]. Once you have the regex pattern ready, you iterate through the namesMap and return only entries with keys matching the pattern. Make sure you do a case-insensitive match, or instead, lowercase all names while building namesMap.
How to get country code from mobile number using libphonenumber api in Android [duplicate]
This question already has answers here: Extract code country from phone number [libphonenumber] (7 answers) Closed 5 years ago. I am using libphonenumber api https://code.google.com/p/libphonenumber/ in android project, I am getting country code using following code PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); try { PhoneNumber numberProto = phoneUtil.parse(number, "IN"); int countryCode = numberProto.getCountryCode(); } catch (NumberParseException e) { System.err.println("NumberParseException was thrown: " + e.toString()); } My question is:- -- I have number like +447870000000 but don't know about country code but want to get country code from this number like +44 how can I get it through this api ? please help me Thanks in advance
#Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_activity); /*********** read indicative sim *************/ TelephonyManager telMgr = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); String simContryiso = telMgr.getSimCountryIso(); String indicative = Iso2Phone.getPhone(simContryiso); } //create a class which contains the indicative of all the country and the ISO code public class Iso2Phone { // Get the indicative public static String getPhone(String code) { return country_to_indicative.get(code.toUpperCase()); } private static Map<String, String> country_to_indicative = new HashMap<String, String>(); static { country_to_indicative.put("AF", "+93"); country_to_indicative.put("AL", "+355"); country_to_indicative.put("DZ", "+213"); country_to_indicative.put("AS", "+1684"); country_to_indicative.put("AD", "+376"); country_to_indicative.put("AO", "+244"); country_to_indicative.put("AI", "+1264"); country_to_indicative.put("AG", "+1268"); country_to_indicative.put("AR", "+54"); country_to_indicative.put("AM", "+374"); country_to_indicative.put("AU", "+61"); country_to_indicative.put("AW", "+297"); country_to_indicative.put("AT", "+43"); country_to_indicative.put("AZ", "+994"); country_to_indicative.put("BS", "+1242"); country_to_indicative.put("BH", "+973"); country_to_indicative.put("BD", "+880"); country_to_indicative.put("BB", "+1246"); country_to_indicative.put("BY", "+375"); country_to_indicative.put("BE", "+32"); country_to_indicative.put("BZ", "+501"); country_to_indicative.put("BJ", "+229"); country_to_indicative.put("BM", "+1441"); country_to_indicative.put("BT", "+975"); country_to_indicative.put("BO", "+591"); country_to_indicative.put("BA", "+387"); country_to_indicative.put("BW", "+267"); country_to_indicative.put("BR", "+55"); country_to_indicative.put("BN", "+673"); country_to_indicative.put("BG", "+359"); country_to_indicative.put("BF", "+226"); country_to_indicative.put("BI", "+257"); country_to_indicative.put("KH", "+855"); country_to_indicative.put("CM", "+237"); country_to_indicative.put("CA", "+1"); country_to_indicative.put("CV", "+238"); country_to_indicative.put("CF", "+236"); country_to_indicative.put("TD", "+235"); country_to_indicative.put("CL", "+56"); country_to_indicative.put("CN", "+86"); country_to_indicative.put("CO", "+57"); country_to_indicative.put("KM", "+269"); country_to_indicative.put("CD", "+243"); country_to_indicative.put("CG", "+242"); country_to_indicative.put("CR", "+506"); country_to_indicative.put("CI", "+225"); country_to_indicative.put("HR", "+385"); country_to_indicative.put("CU", "+53"); country_to_indicative.put("CY", "+357"); country_to_indicative.put("CZ", "+420"); country_to_indicative.put("DK", "+45"); country_to_indicative.put("DJ", "+253"); country_to_indicative.put("DM", "+1767"); country_to_indicative.put("DO", "+1829"); country_to_indicative.put("EC", "+593"); country_to_indicative.put("EG", "+20"); country_to_indicative.put("SV", "+503"); country_to_indicative.put("GQ", "+240"); country_to_indicative.put("ER", "+291"); country_to_indicative.put("EE", "+372"); country_to_indicative.put("ET", "+251"); country_to_indicative.put("FJ", "+679"); country_to_indicative.put("FI", "+358"); country_to_indicative.put("FR", "+33"); country_to_indicative.put("GA", "+241"); country_to_indicative.put("GM", "+220"); country_to_indicative.put("GE", "+995"); country_to_indicative.put("DE", "+49"); country_to_indicative.put("GH", "+233"); country_to_indicative.put("GR", "+30"); country_to_indicative.put("GD", "+1473"); country_to_indicative.put("GT", "+502"); country_to_indicative.put("GN", "+224"); country_to_indicative.put("GW", "+245"); country_to_indicative.put("GY", "+592"); country_to_indicative.put("HT", "+509"); country_to_indicative.put("HN", "+504"); country_to_indicative.put("HU", "+36"); country_to_indicative.put("IS", "+354"); country_to_indicative.put("IN", "+91"); country_to_indicative.put("ID", "+62"); country_to_indicative.put("IR", "+98"); country_to_indicative.put("IQ", "+964"); country_to_indicative.put("IE", "+353"); country_to_indicative.put("IL", "+972"); country_to_indicative.put("IT", "+39"); country_to_indicative.put("JM", "+1876"); country_to_indicative.put("JP", "+81"); country_to_indicative.put("JO", "+962"); country_to_indicative.put("KZ", "+7"); country_to_indicative.put("KE", "+254"); country_to_indicative.put("KI", "+686"); country_to_indicative.put("KP", "+850"); country_to_indicative.put("KR", "+82"); country_to_indicative.put("KW", "+965"); country_to_indicative.put("KG", "+996"); country_to_indicative.put("LA", "+856"); country_to_indicative.put("LV", "+371"); country_to_indicative.put("LB", "+961"); country_to_indicative.put("LS", "+266"); country_to_indicative.put("LR", "+231"); country_to_indicative.put("LY", "+218"); country_to_indicative.put("LI", "+423"); country_to_indicative.put("LT", "+370"); country_to_indicative.put("LU", "+352"); country_to_indicative.put("MK", "+389"); country_to_indicative.put("MG", "+261"); country_to_indicative.put("MW", "+265"); country_to_indicative.put("MY", "+60"); country_to_indicative.put("MV", "+960"); country_to_indicative.put("ML", "+223"); country_to_indicative.put("MT", "+356"); country_to_indicative.put("MH", "+692"); country_to_indicative.put("MR", "+222"); country_to_indicative.put("MU", "+230"); country_to_indicative.put("MX", "+52"); country_to_indicative.put("FM", "+691"); country_to_indicative.put("MD", "+373"); country_to_indicative.put("MC", "+377"); country_to_indicative.put("MN", "+976"); country_to_indicative.put("ME", "+382"); country_to_indicative.put("MA", "+212"); country_to_indicative.put("MZ", "+258"); country_to_indicative.put("MM", "+95"); country_to_indicative.put("NA", "+264"); country_to_indicative.put("NR", "+674"); country_to_indicative.put("NP", "+977"); country_to_indicative.put("NL", "+31"); country_to_indicative.put("NZ", "+64"); country_to_indicative.put("NI", "+505"); country_to_indicative.put("NE", "+227"); country_to_indicative.put("NG", "+234"); country_to_indicative.put("NO", "+47"); country_to_indicative.put("OM", "+968"); country_to_indicative.put("PK", "+92"); country_to_indicative.put("PW", "+680"); country_to_indicative.put("PA", "+507"); country_to_indicative.put("PG", "+675"); country_to_indicative.put("PY", "+595"); country_to_indicative.put("PE", "+51"); country_to_indicative.put("PH", "+63"); country_to_indicative.put("PL", "+48"); country_to_indicative.put("PT", "+351"); country_to_indicative.put("QA", "+974"); country_to_indicative.put("RO", "+40"); country_to_indicative.put("RU", "+7"); country_to_indicative.put("RW", "+250"); country_to_indicative.put("KN", "+1869"); country_to_indicative.put("LC", "+1758"); country_to_indicative.put("VC", "+1784"); country_to_indicative.put("WS", "+685"); country_to_indicative.put("SM", "+378"); country_to_indicative.put("ST", "+239"); country_to_indicative.put("SA", "+966"); country_to_indicative.put("SN", "+221"); country_to_indicative.put("RS", "+381"); country_to_indicative.put("SC", "+248"); country_to_indicative.put("SL", "+232"); country_to_indicative.put("SG", "+65"); country_to_indicative.put("SK", "+421"); country_to_indicative.put("SI", "+386"); country_to_indicative.put("SB", "+677"); country_to_indicative.put("SO", "+252"); country_to_indicative.put("ZA", "+27"); country_to_indicative.put("ES", "+34"); country_to_indicative.put("LK", "+94"); country_to_indicative.put("SD", "+249"); country_to_indicative.put("SR", "+597"); country_to_indicative.put("SZ", "+268"); country_to_indicative.put("SE", "+46"); country_to_indicative.put("CH", "+41"); country_to_indicative.put("SY", "+963"); country_to_indicative.put("TJ", "+992"); country_to_indicative.put("TZ", "+255"); country_to_indicative.put("TH", "+66"); country_to_indicative.put("TL", "+670"); country_to_indicative.put("TG", "+228"); country_to_indicative.put("TO", "+676"); country_to_indicative.put("TT", "+1868"); country_to_indicative.put("TN", "+216"); country_to_indicative.put("TR", "+90"); country_to_indicative.put("TM", "+993"); country_to_indicative.put("TV", "+688"); country_to_indicative.put("UG", "+256"); country_to_indicative.put("UA", "+380"); country_to_indicative.put("AE", "+971"); country_to_indicative.put("GB", "+44"); country_to_indicative.put("US", "+1"); country_to_indicative.put("UY", "+598"); country_to_indicative.put("UZ", "+998"); country_to_indicative.put("VU", "+678"); country_to_indicative.put("VA", "+39"); country_to_indicative.put("VE", "+58"); country_to_indicative.put("VN", "+84"); country_to_indicative.put("YE", "+967"); country_to_indicative.put("ZM", "+260"); country_to_indicative.put("ZW", "+263"); country_to_indicative.put("GE", "+995"); country_to_indicative.put("TW", "+886"); country_to_indicative.put("AZ", "+994"); country_to_indicative.put("MD", "+373"); country_to_indicative.put("SO", "+252"); country_to_indicative.put("GE", "+995"); country_to_indicative.put("AU", "+61"); country_to_indicative.put("CX", "+61"); country_to_indicative.put("CC", "+61"); country_to_indicative.put("NF", "+672"); country_to_indicative.put("NC", "+687"); country_to_indicative.put("PF", "+689"); country_to_indicative.put("YT", "+262"); country_to_indicative.put("GP", "+590"); country_to_indicative.put("GP", "+590"); country_to_indicative.put("PM", "+508"); country_to_indicative.put("WF", "+681"); country_to_indicative.put("PF", "+689"); country_to_indicative.put("CK", "+682"); country_to_indicative.put("NU", "+683"); country_to_indicative.put("TK", "+690"); country_to_indicative.put("GG", "+44"); country_to_indicative.put("IM", "+44"); country_to_indicative.put("JE", "+44"); country_to_indicative.put("AI", "+1264"); country_to_indicative.put("BM", "+1441"); country_to_indicative.put("IO", "+246"); country_to_indicative.put("VG", "+1284"); country_to_indicative.put("KY", "+1345"); country_to_indicative.put("FK", "+500"); country_to_indicative.put("GI", "+350"); country_to_indicative.put("MS", "+1664"); country_to_indicative.put("PN", "+870"); country_to_indicative.put("SH", "+290"); country_to_indicative.put("TC", "+1649"); country_to_indicative.put("MP", "+1670"); country_to_indicative.put("PR", "+1"); country_to_indicative.put("AS", "+1684"); country_to_indicative.put("GU", "+1671"); country_to_indicative.put("VI", "+1340"); country_to_indicative.put("HK", "+852"); country_to_indicative.put("MO", "+853"); country_to_indicative.put("FO", "+298"); country_to_indicative.put("GL", "+299"); country_to_indicative.put("GF", "+594"); country_to_indicative.put("GP", "+590"); country_to_indicative.put("MQ", "+596"); country_to_indicative.put("RE", "+262"); country_to_indicative.put("AX", "+35818"); country_to_indicative.put("AW", "+297"); country_to_indicative.put("AN", "+599"); country_to_indicative.put("SJ", "+47"); country_to_indicative.put("AC", "+247"); country_to_indicative.put("TA", "+290"); country_to_indicative.put("AQ", "+6721"); country_to_indicative.put("CS", "+381"); country_to_indicative.put("PS", "+970"); country_to_indicative.put("EH", "+212"); } }
A nice Library has been provided https://github.com/hbb20/CountryCodePickerProject In dependency add dependencies { implementation 'com.hbb20:ccp:2.2.0' } then use this xml code <com.hbb20.CountryCodePicker android:id="#+id/ccp" android:layout_width="wrap_content" android:layout_height="wrap_content" fbutton:ccp_contentColor="#color/appcolor" fbutton:ccp_textSize="#dimen/_10sdp" /> It will automatically populate the list of country code and also u can search in it.
If you have a number in a E164 format (in your case +447870000000) and you specify country code ISO in the parser, it will actually ignore the given iso code and do the formatting based on the number. Country code ISO is needed when the number you give to the method is in national format. As far as your code snippet goes, it should work.
UID of Type V tag seems to be "backwards"
I am building an app that uses RFID tags to identify users, using NFC. I can correctly read the tags, there is no problem. However, when I use the "NFC TagInfo" app, I received this ID from a Type V tag: e00401007539c2d3 when I read the tag myself, the UID is completely backwards: d3c23975000104e0 The RF technology for the Type V tag is Type V (ISO/IEC 15693 / Vicinity). There seems to be nothing wrong with my code, as other tags (Type A (ISO/IEC 14443 Type A) work fine. This is how I convert the byte[] to String: public static String tagFromByte(byte[] __tagId) { String tagId = ""; for (byte b: __tagId) { tagId += String.format("%02x", b); } return tagId; } According to the documentation: The size and format of an ID is specific to the RF technology used by the tag. I tried to search for more info on how to read the UID for a specific technology, but couldn't find any. Update here I found, it is according to documentation. But, that leads to the question, how to get the tag's RF technology used to trigger the right UID byte[]-to-string implementation?
You are logging you tag from 0 to 7, while it should be the other way around. The tagId[0] byte is the least significant byte, and therefore goes at the end. Log it like so: for (int i = _tagId.length(); i > 0; --i) { tagId += String.format("%02x", _tagId[i]); }
Turns out, the UID is not always the same per technology. Here is the solution to that. Check which technology is in use and call the correct function to get the id as a String: protected String getId(Tag tag) { String id = null; if (NfcA.get(tag) != null) { id = byteToString(tag.getId()); } else if (NfcV.get(tag) != null) { id = byteToStringReversed(tag.getId()); } return id; }
What does this regular expression mean in Android augmented reality?
I found a program in Android that claims to return marker positions in AR ("AR_speaker") and uses native code (jni). My problem is in the markerInfo class. I can't understand the meaning of this regular expression: ^id=(\\d+):name=(.+):pos\\[0\\]=([\\d.]+):pos\\[1\\]=([\\d.]+)$ public class MarkerInfo implements Serializable { private static final long serialVersionUID = 1L; private static final Pattern REGEX = Pattern.compile("^id=(\\d+):name=(.+):pos\\[0\\]=([\\d.]+):pos\\[1\\]=([\\d.]+)$"); private Integer id; private String fileName; private Float[] pos = new Float[3]; public MarkerInfo(String markerStr) { Matcher m = REGEX.matcher(markerStr); if (!m.find()) throw new RuntimeException("not markerInfo string : " + markerStr); id = Integer.parseInt(m.group(1)); fileName = m.group(2); pos[0] = Float.parseFloat(m.group(3)); pos[1] = Float.parseFloat(m.group(4)); //pos[2]=Float.parseFloat(m.group(5)); } public Integer getId() { return id; } public String getFileName() { return fileName; } public Float[] getPos() { return pos; } } My other question is where are these data stored? Do any patterns used in AR have these data? In which file? (For example, in marker.patt?)
In Regular Expressions ^ means "start of expression or deny character but in this case is start of expression", then this is what the expression is looking for in the markerStr, is looking for the characters "id=" followed by one or more decimal characters followed by ":name=" followed by a group one or more characters of any kind (thats what .+ mean) followed by ":pos[0]=" followed by one or more decimal characters or dot (thats what [\d.]+ mean) followed by "pos[1]=" followed by one or more decimal characters or dot (thats what [\d.]+ mean) and $ means the end of the regular expression... Hope this help, and anyway i recommed you to read about Regex, they are extremely good tool to find patterns in a string, that's what they are using it for in this case... Regards!
How is the Date/Time formatted in Android notifications?
What does the Android OS use to format Dates and Times in notifications? I assumed it used DateUtils.formatSameDayTime, but it does not exactly do that. The logic appears the same, but the format is not exactly the same. For instance, a notification will show me "2013-08-06" (based on my System Settings) when formatSameDayTime returns "8/6/13". Edit: Here's my current solution. But is it the best? public static final CharSequence formatSameDayTimeCustom(Context context, long then) { if (DateUtils.isToday(then)) { return DateFormat.getTimeFormat(context).format(new Date(then)); } else { final String format = Settings.System.getString(context.getContentResolver(), Settings.System.DATE_FORMAT); return new SimpleDateFormat(format).format(new Date(then)); } }