Java tutorial
/* * Copyright 2015 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. */ package com.examples.abelanav2.ui; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import com.examples.abelanav2.R; import com.examples.abelanav2.grpcclient.AbelanaClientException; import java.io.FileNotFoundException; import java.io.InputStream; /** * This Fragment handles the upload of a new picture. * Use the {@link UploadFragment#newInstance} factory method to * create an instance of this fragment. */ public class UploadFragment extends Fragment implements MenuItem.OnMenuItemClickListener, View.OnClickListener { /** * The code for the select photo intent. */ private static final int SELECT_PHOTO_INTENT = 100; /** * The photo to upload. */ private Bitmap mBitmap = null; /** * We are retrieving an image. */ private boolean mRetrieving = false; /** * Required empty public constructor. */ public UploadFragment() { } /** * Use this factory method to create a new instance of this fragment * using the provided parameters. * @return A new instance of fragment PicturesFragment. */ public static UploadFragment newInstance() { return new UploadFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { MenuItem uploadMenu = menu.add(R.string.upload_menu_action); uploadMenu.setIcon(R.drawable.ic_done_white_24dp); uploadMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); uploadMenu.setOnMenuItemClickListener(this); super.onCreateOptionsMenu(menu, inflater); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_upload, container, false); ImageView imageView = (ImageView) view.findViewById(R.id.imageViewUploadImage); imageView.setOnClickListener(this); if (!mRetrieving) { mRetrieving = true; selectPhoto(); } return view; } /** * Starts the select photo intent. */ private void selectPhoto() { Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); startActivityForResult(photoPickerIntent, SELECT_PHOTO_INTENT); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.imageViewUploadImage: selectPhoto(); break; default: break; } } @Override public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { super.onActivityResult(requestCode, resultCode, imageReturnedIntent); switch (requestCode) { case SELECT_PHOTO_INTENT: if (resultCode == Activity.RESULT_OK) { mRetrieving = true; Uri selectedImage = imageReturnedIntent.getData(); new RetrieveBitmap().execute(selectedImage); } break; default: break; } } @Override public boolean onMenuItemClick(MenuItem item) { uploadNewPhoto(); return false; } /** * Uploads the new photo to the backend. */ private void uploadNewPhoto() { EditText editText = (EditText) getActivity().findViewById(R.id.editTextUploadDescription); String description = editText.getText().toString(); String error = ""; if (!description.equals("") && mBitmap != null) { new UploadTask().execute(description); } else { if (description.equals("")) { editText.setError(getString(R.string.upload_photo_description_missing)); error += getString(R.string.upload_photo_description_missing); } if (mBitmap == null) { if (!error.equals("")) { error += "\n"; } error += getString(R.string.upload_photo_photo_missing); } new AlertDialog.Builder(getActivity()).setTitle(getString(R.string.upload_photo_error_dialog_title)) .setMessage(error).setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // do nothing } }).setIcon(R.drawable.ic_error_black_48dp).show(); } } /** * AsyncTask used to upload the photo. */ private class UploadTask extends AsyncTask<String, Void, String> { /** * A progress dialog shown while the picture is uploading. */ private ProgressDialog mProgress; @Override protected void onPreExecute() { mProgress = ProgressDialog.show(getActivity(), getString(R.string.upload_photo_progress_title), getString(R.string.upload_photo_progress_message), true); } @Override protected String doInBackground(final String... params) { try { boolean res = ((MainActivity) getActivity()).getAbelanaClient().uploadPhoto(params[0], mBitmap); return (res) ? null : getString(R.string.server_error); } catch (AbelanaClientException e) { return e.getMessage(); } } @Override protected void onPostExecute(final String result) { mProgress.dismiss(); if (result == null) { startMainActivity(); } else { showErrorMessage(result); } } } /** * AsyncTask used to retrieve the image selected. */ private class RetrieveBitmap extends AsyncTask<Uri, Void, String> { /** * A progress dialog shown while the picture is uploading. */ private ProgressDialog mProgress; /** * The reduced image. */ private Bitmap mSmallImage; @Override protected void onPreExecute() { mProgress = ProgressDialog.show(getActivity(), getString(R.string.upload_photo_progress_retrieve_title), getString(R.string.upload_photo_progress_retrieve_message), true); } @Override protected String doInBackground(final Uri... params) { try { InputStream imageStream = getActivity().getContentResolver().openInputStream(params[0]); mBitmap = BitmapFactory.decodeStream(imageStream); mSmallImage = downSampleBitmap(params[0]); return null; } catch (FileNotFoundException e) { return getString(R.string.upload_photo_retrieve_image_error); } } @Override protected void onPostExecute(final String result) { mProgress.dismiss(); if (result == null) { ((ImageView) getActivity().findViewById(R.id.imageViewUploadImage)).setImageBitmap(mSmallImage); } else { showErrorMessage(result); } } /** * Reduces the size of the bitmap for display. * @param selectedImage the image Uri. * @return the resized Bitmap. * @throws FileNotFoundException if the image was not found. */ private Bitmap downSampleBitmap(Uri selectedImage) throws FileNotFoundException { // Decode image size BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(selectedImage), null, options); // The new size we want to scale to ImageView imageView = (ImageView) getActivity().findViewById(R.id.imageViewUploadImage); int requiredSize = Math.min(imageView.getWidth(), imageView.getHeight()); // Find the correct scale value. It should be the power of 2. int width = options.outWidth, height = options.outHeight; int scale = 1; while (true) { if (width / 2 < requiredSize || height / 2 < requiredSize) { break; } width /= 2; height /= 2; scale *= 2; } // Decode with inSampleSize BitmapFactory.Options options2 = new BitmapFactory.Options(); options2.inSampleSize = scale; return BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(selectedImage), null, options2); } } /** * Displays a Toast with an error message. * @param message the message to display. */ private void showErrorMessage(String message) { Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show(); // If it is an auth error, let's redirect the user also if (message.equals(getString(R.string.abelana_auth_error_message))) { ((MainActivity) getActivity()).startGitkitActivity(); } } /** * Navigates to the MainActivity. */ private void startMainActivity() { Intent intent = new Intent(getActivity(), MainActivity.class); startActivity(intent); } }