Android Question Send a picture to google vision

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I would like to recognize a picture with google vision. I know that there is this library: https://www.b4x.com/android/forum/t...-with-google-mobile-vision-api.66431/#content

but it is for faces, I would like to recognize places, for example Eiffel tower....

I now am able to access to google services like in this exaample:
https://www.b4x.com/android/forum/threads/google-maps.63930/#post-404386

So I have the APIKey, the keystore file etc.

How could I send the picture and parse the result ?
Thank you
 

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I used this approach:
B4X:
  Dim outString As String="{"&QUOTE&"requests"&QUOTE&":[{"&QUOTE&"image"&QUOTE&":{"&QUOTE&"content"&QUOTE&":"&QUOTE&string64&QUOTE&"},"&QUOTE&"features"&QUOTE&":[{"&QUOTE&"type"&QUOTE&": "&QUOTE&"LABEL_DETECTION"&QUOTE&","&QUOTE&"maxResults"&QUOTE&": 2},{"&QUOTE&"type"&QUOTE&": "&QUOTE&"LANDMARK_DETECTION"&QUOTE&","&QUOTE&"maxResults"&QUOTE&": 2},{"&QUOTE&"type"&QUOTE&": "&QUOTE&"IMAGE_PROPERTIES"&QUOTE&","&QUOTE&"maxResults"&QUOTE&": 2}]}]}"

job.PostString("https://vision.googleapis.com/v1/images:annotate?key="&ApiKey&"",outString)

But the result is job.success = False, job.ErrorMessage= Forbidden

The ApiKey is correct because I can see accesses from google dashboard

May be that someone knows why ?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I think that the key should be in the URL because making a try here (in the interactive composer at the end of the page):
https://cloud.google.com/vision/docs/quickstart

Doing this query:


It return to me something like this:



I used a string instead the JSONGenerator just to do a quick test, it should work anyway I think.

I also found this example code in php:
B4X:
include_once("creds.php"); // Get $api_key
$cvurl = "https://vision.googleapis.com/v1/images:annotate?key=" . $api_key;
$type = "LANDMARK_DETECTION";

//Did they upload a file...
if($_FILES['photo']['name'])
{
   //if no errors...
   if(!$_FILES['photo']['error'])
   {
     $valid_file = true;
     //can't be larger than ~4 MB
     if($_FILES['photo']['size'] > (4024000))
     {
       $valid_file = false;
       die('Your file\'s size is too large.');
     }

     //if the file has passed the test
     if($valid_file)
     {
       //convert it to base64
       $fname = $_FILES['photo']['tmp_name'];
       $data = file_get_contents($fname);
       $base64 = base64_encode($data);
       //Create this JSON
       $r_json ='{
           "requests": [
           {
            "image": {
            "content":"' . $base64. '"
            },
            "features": [
            {
               "type": "' .$type. '",
               "maxResults": 200
            }
            ]
           }
         ]
       }';

       $curl = curl_init();
       curl_setopt($curl, CURLOPT_URL, $cvurl);
       curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
       curl_setopt($curl, CURLOPT_HTTPHEADER,
         array("Content-type: application/json"));
       curl_setopt($curl, CURLOPT_POST, true);
       curl_setopt($curl, CURLOPT_POSTFIELDS, $r_json);
       $json_response = curl_exec($curl);
       $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
       curl_close($curl);

       if ( $status != 200 ) {
        die("Error: $cvurl failed status $status" );
       }

       echo "<pre>";
       echo $json_response;
       echo "</pre>";
     }
   }
   //if there is an error...
   else
   {
     //set that to be the returned message
     echo "Error";
      die('Drror:  '.$_FILES['photo']['error']);
   }
}
?>

I don't understand where my code does something different from this. May be that this part :
B4X:
curl_setopt($curl, CURLOPT_URL, $cvurl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER,
array("Content-type: application/json"));
curl_setopt($curl, CURLOPT_POST, true);
matters ? But how could I do this in B4A?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
Why Job.GetRequest.SetContentType("application/json") must be after and not before PostString ? If I put it before the app crashes, but when I run PostString the request is already gone, is it ?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
Problem discovered.
If I use and APIKey for browser everything works. If I use the APIKey for android apps it fails. I think it is an authenticating issue. How does google check if the sign of app is paired with the Key ?

In other words, how could I send to google the sign of the app ?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I think that if someone disassemble the app or intercept data traffic can stole the key and referer and charge my account.

If I understand correctly, the app signing protect me from this
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
Ok, but in this example : https://www.b4x.com/android/forum/threads/google-maps-android-v2-tutorial.24415/ it is used app sign.

I don't know and rellay I couldn't find any detailed info about the sign is used. I think that the OS calculate some hash from the executable file of the and send it to Google. Google check if it is paired with the SHA1 associated with the ApiKEY and unlock it.

I am not sure if it so, but I think that it should be something similar to avoid that someone could send to the appstore an app that uses stolen ApiKeys.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…