Java tutorial
/* * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Author: Lorenzo Bracco a.k.a. devtry (devtry@riseup.net) */ package com.dexin; import android.Manifest; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.PixelFormat; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.v4.content.FileProvider; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.android.volley.*; import android.text.Html; import android.R.color; import com.android.volley.toolbox.StringRequest; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.googleapis.json.GoogleJsonResponseException; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.gson.GsonFactory; import com.google.api.services.vision.v1.Vision; import com.google.api.services.vision.v1.VisionRequest; import com.google.api.services.vision.v1.VisionRequestInitializer; import com.google.api.services.vision.v1.model.AnnotateImageRequest; import com.google.api.services.vision.v1.model.BatchAnnotateImagesRequest; import com.google.api.services.vision.v1.model.BatchAnnotateImagesResponse; import com.google.api.services.vision.v1.model.EntityAnnotation; import com.google.api.services.vision.v1.model.Feature; import com.google.api.services.vision.v1.model.Image; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Locale; import static com.android.volley.toolbox.Volley.newRequestQueue; public class MainActivity extends AppCompatActivity { private static final String CLOUD_VISION_API_KEY = " AIzaSyDGS_DRiMBwXN3ijn68vCe7NoQ-8bcRuL0 "; public static final String FILE_NAME = "temp.jpg"; private static final String ANDROID_CERT_HEADER = "X-Android-Cert"; private static final String ANDROID_PACKAGE_HEADER = "X-Android-Package"; private static final String TAG = MainActivity.class.getSimpleName(); private static final int GALLERY_PERMISSIONS_REQUEST = 0; private static final int GALLERY_IMAGE_REQUEST = 1; public static final int CAMERA_PERMISSIONS_REQUEST = 2; public static final int CAMERA_IMAGE_REQUEST = 3; private TextView mImageDetails; private ImageView mMainImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().getDecorView().setBackground(getResources().getDrawable(R.drawable.map)); setContentView(R.layout.activity_main); findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE); ImageView viewImage = (ImageView) findViewById(R.id.main_image); viewImage.setVisibility(View.INVISIBLE); /*SupportMapFragment mapFragment = null; while (mapFragment == null) mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this);*/ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setImageDrawable(getResources().getDrawable(R.drawable.buttonphoto2)); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setMessage(R.string.dialog_select_prompt) .setPositiveButton(R.string.dialog_select_gallery, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startGalleryChooser(); } }).setNegativeButton(R.string.dialog_select_camera, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startCamera(); } }); builder.create().show(); } }); mImageDetails = (TextView) findViewById(R.id.image_details); mMainImage = (ImageView) findViewById(R.id.main_image); } public void startGalleryChooser() { if (PermissionUtils.requestPermission(this, GALLERY_PERMISSIONS_REQUEST, Manifest.permission.READ_EXTERNAL_STORAGE)) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select a photo"), GALLERY_IMAGE_REQUEST); } } public void startCamera() { if (PermissionUtils.requestPermission(this, CAMERA_PERMISSIONS_REQUEST, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA)) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri photoUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", getCameraFile()); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivityForResult(intent, CAMERA_IMAGE_REQUEST); } } public File getCameraFile() { File dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return new File(dir, FILE_NAME); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == GALLERY_IMAGE_REQUEST && resultCode == RESULT_OK && data != null) { uploadImage(data.getData()); } else if (requestCode == CAMERA_IMAGE_REQUEST && resultCode == RESULT_OK) { Uri photoUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", getCameraFile()); uploadImage(photoUri); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case CAMERA_PERMISSIONS_REQUEST: if (PermissionUtils.permissionGranted(requestCode, CAMERA_PERMISSIONS_REQUEST, grantResults)) { startCamera(); } break; case GALLERY_PERMISSIONS_REQUEST: if (PermissionUtils.permissionGranted(requestCode, GALLERY_PERMISSIONS_REQUEST, grantResults)) { startGalleryChooser(); } break; } } public void uploadImage(Uri uri) { if (uri != null) { try { // scale the image to save on bandwidth Bitmap bitmap = scaleBitmapDown(MediaStore.Images.Media.getBitmap(getContentResolver(), uri), 1200); callCloudVision(bitmap); mMainImage.setImageBitmap(bitmap); } catch (IOException e) { Log.d(TAG, "Image picking failed because " + e.getMessage()); Toast.makeText(this, R.string.image_picker_error, Toast.LENGTH_LONG).show(); } } else { Log.d(TAG, "Image picker gave us a null image."); Toast.makeText(this, R.string.image_picker_error, Toast.LENGTH_LONG).show(); } } private void callCloudVision(final Bitmap bitmap) throws IOException { // Switch text to loading findViewById(R.id.loadingPanel).setVisibility(View.VISIBLE); getWindow().getDecorView().setBackground(null); getWindow().getDecorView().setBackgroundColor(Color.WHITE); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setImageDrawable(getResources().getDrawable(R.drawable.check)); ImageView viewImage = (ImageView) findViewById(R.id.main_image); viewImage.setVisibility(View.VISIBLE); mImageDetails.setText(R.string.loading_message); // Do the real work in an async task, because we need to use the network anyway new AsyncTask<Object, Void, String>() { @Override protected String doInBackground(Object... params) { try { HttpTransport httpTransport = AndroidHttp.newCompatibleTransport(); JsonFactory jsonFactory = GsonFactory.getDefaultInstance(); VisionRequestInitializer requestInitializer = new VisionRequestInitializer( CLOUD_VISION_API_KEY) { /** * We override this so we can inject important identifying fields into the HTTP * headers. This enables use of a restricted cloud platform API key. */ @Override protected void initializeVisionRequest(VisionRequest<?> visionRequest) throws IOException { super.initializeVisionRequest(visionRequest); String packageName = getPackageName(); visionRequest.getRequestHeaders().set(ANDROID_PACKAGE_HEADER, packageName); String sig = PackageManagerUtils.getSignature(getPackageManager(), packageName); visionRequest.getRequestHeaders().set(ANDROID_CERT_HEADER, sig); } }; Vision.Builder builder = new Vision.Builder(httpTransport, jsonFactory, null); builder.setVisionRequestInitializer(requestInitializer); Vision vision = builder.build(); BatchAnnotateImagesRequest batchAnnotateImagesRequest = new BatchAnnotateImagesRequest(); batchAnnotateImagesRequest.setRequests(new ArrayList<AnnotateImageRequest>() { { AnnotateImageRequest annotateImageRequest = new AnnotateImageRequest(); // Add the image Image base64EncodedImage = new Image(); // Convert the bitmap to a JPEG // Just in case it's a format that Android understands but Cloud Vision ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, byteArrayOutputStream); byte[] imageBytes = byteArrayOutputStream.toByteArray(); // Base64 encode the JPEG base64EncodedImage.encodeContent(imageBytes); annotateImageRequest.setImage(base64EncodedImage); // add the features we want annotateImageRequest.setFeatures(new ArrayList<Feature>() { { Feature labelDetection = new Feature(); labelDetection.setType("LABEL_DETECTION"); labelDetection.setMaxResults(10); add(labelDetection); } }); // Add the list of one thing to the request add(annotateImageRequest); } }); Vision.Images.Annotate annotateRequest = vision.images().annotate(batchAnnotateImagesRequest); // Due to a bug: requests to Vision API containing large images fail when GZipped. annotateRequest.setDisableGZipContent(true); Log.d(TAG, "created Cloud Vision request object, sending request"); BatchAnnotateImagesResponse response = annotateRequest.execute(); return convertResponseToString(response); } catch (GoogleJsonResponseException e) { Log.d(TAG, "failed to make API request because " + e.getContent()); } catch (IOException e) { Log.d(TAG, "failed to make API request because of other IOException " + e.getMessage()); } return "Cloud Vision API request failed. Check logs for details."; } protected void onPostExecute(String result) { findViewById(R.id.loadingPanel).setVisibility(View.GONE); mImageDetails.setText(Html.fromHtml(result)); } }.execute(); } public Bitmap scaleBitmapDown(Bitmap bitmap, int maxDimension) { int originalWidth = bitmap.getWidth(); int originalHeight = bitmap.getHeight(); int resizedWidth = maxDimension; int resizedHeight = maxDimension; if (originalHeight > originalWidth) { resizedHeight = maxDimension; resizedWidth = (int) (resizedHeight * (float) originalWidth / (float) originalHeight); } else if (originalWidth > originalHeight) { resizedWidth = maxDimension; resizedHeight = (int) (resizedWidth * (float) originalHeight / (float) originalWidth); } else if (originalHeight == originalWidth) { resizedHeight = maxDimension; resizedWidth = maxDimension; } return Bitmap.createScaledBitmap(bitmap, resizedWidth, resizedHeight, false); } private String convertResponseToString(BatchAnnotateImagesResponse response) { String message = "Recognized as "; List<EntityAnnotation> labels = response.getResponses().get(0).getLabelAnnotations(); if (labels != null) { for (EntityAnnotation label : labels) { message += String.format(Locale.US, "<b>%s</b>", label.getDescription()); // Instantiate the RequestQueue. RequestQueue queue = newRequestQueue(this); String url = "https://en.wikipedia.org/wiki/" + label.getDescription(); // Request a string response from the provided URL. StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { String usedString = response.substring(response.indexOf("<p>"), response.indexOf("<h2>Contents</h2>")); String word = usedString.substring(usedString.indexOf("<b>") + 3, usedString.indexOf("</b>")); word = (word.charAt(0) + "").toUpperCase() + word.substring(1); String toWrite = "<h1>" + word + "</h1>"; int index = 0; int i; while ((i = usedString.indexOf("<sup", index)) > 0) { toWrite += usedString.substring(index, i); index = usedString.indexOf("</sup>", i) + 6; } toWrite += usedString.substring(index); mImageDetails.append( Html.fromHtml(toWrite.replaceAll("<a[^>]*>", "").replaceAll("</a>", ""))); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); // Add the request to the RequestQueue. queue.add(stringRequest); message += "<br /><br />"; //<big><b>Bottle</b></big><br /><i>/bot-l/</i><br />A portable container for holding liquids, characteristically having a neck and mouth and made of glass or plastic."; break; } } else { message += "nothing!"; } return message; } }