How to get Camera RAW metadata info programmatically Android - java

I have an app, which sets the hardware parameters of the Camera programmatically.
However, as I've been told, and have come to observe, not all chipsets support all parameters.
For example, the Nexus 4 (Qualcomm) has sharpness, and sharpness-max parameters, the Galaxy Note II 3g doesn't have any.
Hence, when I set sharpness parameter, the Nexus responds well, but the Galaxy force closes:
java.lang.RuntimeException: setParameters failed
at android.hardware.Camera.native_setParameters(Native Method)
at android.hardware.Camera.setParameters(Camera.java:1452)
My question is, how can I get the RAW info programmatically? I need to get the parameters, their values, and whether they exist or not.
I wish to get the RAW-Metadata parameters, as like this: database

Alright, thought this would be a fun bit of practice. So, Android does not give a public API into this information. Why? I have no idea. Looks like you can do a Camera.Parameters#get(String) to check for any particular parameter that you're interested in, but lets say you're greedy and want the whole list to yourself. In that case, we can dive in using Reflection, but be aware that there is a strong possibility that this will not work on all versions of Android or may break in future versions. With that said, here's how you do it:
private static Map<String, String> getFullCameraParameters (Camera cam) {
Map<String, String> result = new HashMap<String, String>(64);
final String TAG = "CameraParametersRetrieval";
try {
Class camClass = cam.getClass();
//Internally, Android goes into native code to retrieve this String of values
Method getNativeParams = camClass.getDeclaredMethod("native_getParameters");
getNativeParams.setAccessible(true);
//Boom. Here's the raw String from the hardware
String rawParamsStr = (String) getNativeParams.invoke(cam);
//But let's do better. Here's what Android uses to parse the
//String into a usable Map -- a simple ';' StringSplitter, followed
//by splitting on '='
//
//Taken from Camera.Parameters unflatten() method
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(';');
splitter.setString(rawParamsStr);
for (String kv : splitter) {
int pos = kv.indexOf('=');
if (pos == -1) {
continue;
}
String k = kv.substring(0, pos);
String v = kv.substring(pos + 1);
result.put(k, v);
}
//And voila, you have a map of ALL supported parameters
return result;
} catch (NoSuchMethodException ex) {
Log.e(TAG, ex.toString());
} catch (IllegalAccessException ex) {
Log.e(TAG, ex.toString());
} catch (InvocationTargetException ex) {
Log.e(TAG, ex.toString());
}
//If there was any error, just return an empty Map
Log.e(TAG, "Unable to retrieve parameters from Camera.");
return result;
}

Related

Speech Assessment in Java never returning insertions and omissions nor detecting speech end

for a project I am trying to use azure's speech assessment in java to assess how the user pronounces the words and if they announce it well. Currently I am using a approach that uses the listeners:
System.out.println("Starting recording with " + this.prompt);
PronunciationAssessmentConfig pronunciationAssessmentConfig = new PronunciationAssessmentConfig(this.getPrompt(),
PronunciationAssessmentGradingSystem.HundredMark, PronunciationAssessmentGranularity.Phoneme, true);
// PronunciationAssessmentConfig pronunciationAssessmentConfig = PronunciationAssessmentConfig.fromJson("{\"referenceText\":\"" + getPrompt() + "\",\"gradingSystem\":\"HundredMark\",\"granularity\":\"Phoneme\", \"miscue\":true}");
AudioConfig audioConfig = AudioConfig.fromDefaultMicrophoneInput();
SpeechUtil.SPEECH_CONFIG.setOutputFormat(OutputFormat.Detailed);
SpeechRecognizer speechRecognizer = new SpeechRecognizer(
SpeechUtil.SPEECH_CONFIG,
audioConfig);
pronunciationAssessmentConfig.applyTo(speechRecognizer);
speechRecognizer.startContinuousRecognitionAsync();
speechRecognizer.recognizing.addEventListener((o, speechRecognitionResultEventArgs) -> {
try {
final int words = speechRecognitionResultEventArgs.getResult().getText().split(" ").length;
System.out.println("Recognizing: " + speechRecognitionResultEventArgs.getResult().getText());
Platform.runLater(() -> this.controller.setSpoken(0, wordsReadToIndex(words)));
System.out.println(words);
System.out.println(pronunciationAssessmentConfig.getReferenceText());
System.out.println(speechRecognitionResultEventArgs.getResult().getProperties().getProperty(PropertyId.SpeechServiceResponse_JsonResult));
if (words >= pronunciationAssessmentConfig.getReferenceText().split(" ").length)
speechRecognizer.stopContinuousRecognitionAsync();
} catch (Throwable e) {
e.printStackTrace();
}
});
speechRecognizer.recognized.addEventListener((o, speechRecognitionEventArgs) -> {
System.out.println("Recognized!");
try {
PronunciationAssessmentResult pronunciationAssessmentResult =
PronunciationAssessmentResult.fromResult(speechRecognitionEventArgs.getResult());
if (pronunciationAssessmentResult == null) return;
System.out.println(pronunciationAssessmentResult.getAccuracyScore());
String jsonString = speechRecognitionEventArgs.getResult().getProperties().getProperty(PropertyId.SpeechServiceResponse_JsonResult);
System.out.println(jsonString);
Platform.runLater(() -> this.complete(new Score(pronunciationAssessmentResult.getAccuracyScore().intValue(), JsonParser.parseString(jsonString))));
speechRecognizer.stopContinuousRecognitionAsync();
} catch (Throwable e) {
e.printStackTrace();
}
});
//
speechRecognizer.speechEndDetected.addEventListener((o, speechRecognitionEventArgs) -> {
System.out.println("Speech end detected!");
});
however it does not detect any omissions or insertions even though it is turned on in the assessment settings. Neither does it ever detect a speech end.
*Result of saying 'Hello, could I buy one these books you are selling' with reference 'Hello, could I buy one of these books you are selling' *
https://pastebin.com/tvAVw4s3
I have tried the following example as well:
https://github.com/Azure-Samples/cognitive-services-speech-sdk/blob/master/samples/java/jre/console/src/com/microsoft/cognitiveservices/speech/samples/console/SpeechRecognitionSamples.java#L985 (The pronunciationAssessmentWithMicrophoneAsync() function)
but even this example adapted from the microsoft azure github repo never returns anything useful and when it does it is:
CANCELED: ErrorCode=ServiceTimeout
CANCELED: ErrorDetails=Timeout: no recognition result received SessionId: 09f1a5492851429e81e4672c90144a37
CANCELED: Did you update the subscription info?```
**EDIT:**
Ì have found out that it happens because of a noisy environment and pronunciationassessment, though it does return with the exact same code and environment without the pronunciationassessment.

Jsoup Google Search Results

I am attempting to parse the HTML of google's search results to grab the title of each result. This is done through android in a private nested class shown below:
private class WebScraper extends AsyncTask<String, Void, String> {
public WebScraper() {}
#Override
protected String doInBackground(String... urls) {
Document doc;
try {
doc = Jsoup.connect(urls[0]).get();
} catch (IOException e) {
System.out.println("Failed to open document");
return "";
}
Elements results = doc.getElementsByClass("rc");
int count = 0;
for (Element lmnt : results) {
System.out.println(count++);
System.out.println(lmnt.text());
}
System.out.println("Count is : " + count);
String key = "test";
//noinspection Since15
SearchActivity.this.songs.put(key, SearchActivity.this.songs.getOrDefault(key, 0) + 1);
// return requested
return "";
}
}
an example url I am trying to parse: http://www.google.com/#q=i+might+site:genius.com
For some reason, when i run the above code, my count is printed as 0, thus no elements are being stored in results. Any help is much appreciated! P.S. docs is definitely initialized and the HTML page is loading properly
This code will search a word like "Apple" in google and fetch all links from results and display their title and url. It can search upto 500 words in a day after that google detect it and stop giving results.
search="Apple"; //your word to be search on google
String userAgent = "ExampleBot 1.0 (+http://example.com/bot)";
Elements links=null;
try {
links = Jsoup.connect(google +
URLEncoder.encode(search,charset)).
userAgent(userAgent).get().select(".g>.r>a");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for (Element link : links) {
String title = link.text();
String url = link.absUrl("href"); // Google returns URLs in
format "http://www.google.com/url?q=<url>&sa=U&ei=<someKey>".
try {
url = URLDecoder.decode(url.substring(url.indexOf('=') +
1, url.indexOf('&')), "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!url.startsWith("http")) {
continue; // Ads/news/etc.
}
System.out.println("Title: " + title);
System.out.println("URL: " + url);
}
If you check source code of the Google's page, you will notice that it does not contain any text data which is shown normally in the browser - there is only a bunch of javascript code. That means that Google outputs all the search results dynamically.
Jsoup will fetch that javascript code and it will not find any html code with "rc" classes, that's why you get zero count in your code sample.
Consider using Google's public search API instead of direct parsing of its html pages: https://developers.google.com/custom-search/.
I completely agree with Matvey Sidorenko but for using the google public search API, you need to have the Google Api key. But the problem is that google limits 100 searches per api key, exceeding which, it stops working and it gets reset in 24 hours.
Recently i was working on a project where we needed to get the google search result links for different queries provided by the user, so as to overcome this issue of API limit, i made my own API that searches directly on google/ncr and gives you the result link.
Free Google Search API-
http://freegoogleapi.azurewebsites.net/ OR http://google.bittque.com
I used HTML-UNIT library for making this API.
You can use my API or you can use the HTML UNIT Library for achieving what you need.

ResourceTool : to recover a jpg with ResourceNode [velocity]

During my searching, I would like a piece of advice about the following situation :
the guy, on my website, choose a parcel to send, when he validates the choice, some carriers appear as results. Now some carriers have different offers with different logos located in a special directory.
Now the business logic I would like to use is :
If in the directory I find the peculiar logo corresponding to the special offer, I will take the logo to display It in the web page with the special offer.
I choose to do this work with the ResourceTool from Velocity
I have to implement 2 methods getLogo() and getLabel().
The getLogo() will look for the special logo.
I think to use this method to recover the object :
public static ResourceNode getResource(Context context, ResourceType resourceType, String...keys) {
try {
if (null != ResourcesTool.instance) {
ResourceNode resource = ResourcesTool.instance.getResourceSet(context, resourceType);
if (null != resource) {
Deque < String > keyDeque = new ArrayDeque < > ();
for (String key: keys) {
keyDeque.add(key);
}
return (ResourceNode) resource.sub(keyDeque);
}
}
} catch (Exception e) {
BoxtaleLogger.debug("[ResourcesTool.getResource] error: ", e);
}
return null;
}
Now I am searching a example to merely use this method to recover the different .jpg
question 2 : I don't understand what is the meaningful of Context context in this method ?
Then the resourceType is an enum either a String or a picture (the logo in fact)
All right I found It :
public String getLogo(ResourceNode node){
//readable variables
String ope_code = (String)((Instance)get("operateur")).get("ope_code");
String paysDest = ((Instance)db.getEntity("tab_pays").fetch((Integer) get("pz_id"))).get("pz_iso");
String path = node.get(ope_code+"_"+get("srv_code")+"_"+paysDest+".png");
if (path=null){
path = node.get(ope_code+"_"+get("srv_code")+".png");
if (path=null){
path = node.get(ope_code+".png");
}
}
return path ;
}
Now I am testing the method, I will tell you after.

How to avoid many if/else conditions in the method?

I'm in doubts am on right way for one of my methods. This one is a compositor of URI I'm using for my http requests. It just takes data from a separate static class with final Strings, merges them together and includes received from the server token where necessary. It happened all URIs are with token and the only one, authentication, without it. What I've done:
private URI urlComposer(String apiUri, String token) {
URI uri = null;
try {
if(apiUri.equals("POST_AUTH_URL")) {
uri = URIUtils.createURI(null, MyConfig.WEB_SERVER, -1, apiUri, null, null);
return uri;
}
String tmp = apiUri.toString();
String[] array = tmp.split("<token>");
tmp = array[0] + auth.getToken() + array[1];
uri = URIUtils.createURI(null, MyConfig.WEB_SERVER, -1, tmp, null, null);
if (MyConfig.DEBUG) Log.d("Dev", "Constructed url " + uri);
return uri;
} catch (URISyntaxException e) {
if (MyConfig.DEBUG) Log.d("Dev", "urlComposer was unable to construct a URL");
e.printStackTrace();
}
return null;
}
Trying to look in the future I don't like the idea to generate more if/else statements if I would have more special cases like this POST_AUTH_URL. One one hand I want the only one method to be called to construct a URI, on the other I don't want these ifs. What shall I do?
If you always set URIs, only different ones, you can use a map:
uriMap.put("POST_AUTH_URL", URIUtils.createURI(null, MyConfig.WEB_SERVER, -1, apiUri, null, null));
You can access this map later:
uri = uriMap.get(apiUri);
You could theoretically create an enum URI_TYPE with method createURI (it is difficult to derive the actual parameters from the provided code snippet). This way you'd simply invoke this method on a specific enum value, which would have its own specific implementation.
Pls refer this and this for more information. Hope it helps.

Is there a good way to persist printer settings in a Swing app?

We are using the new Java printing API which uses PrinterJob.printDialog(attributes) to display the dialog to the user.
Wanting to save the user's settings for the next time, I wanted to do this:
PrintRequestAttributeSet attributes = loadAttributesFromPreferences();
if (printJob.printDialog(attributes)) {
// print, and then...
saveAttributesToPreferences(attributes);
}
However, what I found by doing this is that sometimes (I haven't figured out how, yet) the attributes get some bad data inside, and then when you print, you get a white page of nothing. Then the code saves the poisoned settings into the preferences, and all subsequent print runs get poisoned settings too. Additionally, the entire point of the exercise, making the settings for the new run the same as the user chose for the previous run, is defeated, because the new dialog does not appear to use the old settings.
So I would like to know if there is a proper way to do this. Surely Sun didn't intend that users have to select the printer, page size, orientation and margin settings every time the application starts up.
Edit to show the implementation of the storage methods:
private PrintRequestAttributeSet loadAttributesFromPreferences()
{
PrintRequestAttributeSet attributes = null;
byte[] marshaledAttributes = preferences.getByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, null);
if (marshaledAttributes != null)
{
try
{
#SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
ObjectInput objectInput = new ObjectInputStream(new ByteArrayInputStream(marshaledAttributes));
attributes = (PrintRequestAttributeSet) objectInput.readObject();
}
catch (IOException e)
{
// Can occur due to invalid object data e.g. InvalidClassException, StreamCorruptedException
Logger.getLogger(getClass()).warn("Error trying to read print attributes from preferences", e);
}
catch (ClassNotFoundException e)
{
Logger.getLogger(getClass()).warn("Class not found trying to read print attributes from preferences", e);
}
}
if (attributes == null)
{
attributes = new HashPrintRequestAttributeSet();
}
return attributes;
}
private void saveAttributesToPreferences(PrintRequestAttributeSet attributes)
{
ByteArrayOutputStream storage = new ByteArrayOutputStream();
try
{
ObjectOutput objectOutput = new ObjectOutputStream(storage);
try
{
objectOutput.writeObject(attributes);
}
finally
{
objectOutput.close(); // side-effect of flushing the underlying stream
}
}
catch (IOException e)
{
throw new IllegalStateException("I/O error writing to a stream going to a byte array", e);
}
preferences.putByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, storage.toByteArray());
}
Edit: Okay, it seems like the reason it isn't remembering the printer is that it isn't in the PrintRequestAttributeSet at all. Indeed, the margins and page sizes are remembered, at least until the settings get poisoned at random. But the printer chosen by the user is not here:
[0] = {java.util.HashMap$Entry#9494} class javax.print.attribute.standard.Media -> na-letter
[1] = {java.util.HashMap$Entry#9501} class javax.print.attribute.standard.Copies -> 1
[2] = {java.util.HashMap$Entry#9510} class javax.print.attribute.standard.MediaPrintableArea -> (10.0,10.0)->(195.9,259.4)mm
[3] = {java.util.HashMap$Entry#9519} class javax.print.attribute.standard.OrientationRequested -> portrait
It appears that what you're looking for is the PrintServiceAttributeSet, rather than the PrintRequestAttributeSet.
Take a look at the PrintServiceAttribute interface, and see if the elements you need have been implemented as classes. If not, you can implement your own PrintServiceAttribute class(es).

Categories

Resources