com.examples.abelanav2.ui.UploadFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.examples.abelanav2.ui.UploadFragment.java

Source

/*
 * 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);
    }

}