com.microsoft.mimickeralarm.ringing.ShareFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.mimickeralarm.ringing.ShareFragment.java

Source

/*
 *
 * Copyright (c) Microsoft. All rights reserved.
 * Licensed under the MIT license.
 *
 * Project Oxford: http://ProjectOxford.ai
 *
 * Project Oxford Mimicker Alarm Github:
 * https://github.com/Microsoft/ProjectOxford-Apps-MimickerAlarm
 *
 * Copyright (c) Microsoft Corporation
 * All rights reserved.
 *
 * MIT License:
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

package com.microsoft.mimickeralarm.ringing;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.microsoft.mimickeralarm.R;
import com.microsoft.mimickeralarm.utilities.Loggable;
import com.microsoft.mimickeralarm.utilities.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * This class handles the Sharing user experience once a user has successfully completed a Mimic
 * game.  The class utilizes the system sharing action to allow the user to share with the
 * application of their choice.
 */
public class ShareFragment extends Fragment {
    public static final String SHARE_FRAGMENT_TAG = "share_fragment";
    public static final String SHAREABLE_URI = "shareable-uri";
    private final static int SHARE_REQUEST_CODE = 2;
    private final static String MIMICKER_FILE_PREFIX = "Mimicker_";
    // The time to auto-dismiss share screen if there is no user interaction
    private static final int SHARING_FRAGMENT_STAY_DURATION = 60 * 1000; // 1 minute
    // The time to auto-dismiss share screen after pressing save button
    private static final int SHARING_FRAGMENT_SAVE_STAY_DURATION = 60 * 1000; // 1 minute
    // The time to auto-dismiss share screen after pressing share button
    private static final int SHARING_FRAGMENT_SHARE_STAY_DURATION = 300 * 1000; // 5 minutes
    // Delay to dismiss the toast message
    private static final long TOAST_IN_FRAGMENT_DELAY = 1500; // 1.5 seconds

    private ShareResultListener mCallback;
    private String mShareableUri;
    private ImageView mShareableImage;

    private Handler mHandler;
    private Runnable mSharingFragmentDismissTask;
    private Runnable mToastAutoDismiss;
    private int mSharingFragmentDismissTaskDelay = SHARING_FRAGMENT_STAY_DURATION;

    public static ShareFragment newInstance(String shareableUri) {
        ShareFragment fragment = new ShareFragment();
        Bundle bundle = new Bundle(1);
        bundle.putString(SHAREABLE_URI, shareableUri);
        fragment.setArguments(bundle);
        return fragment;
    }

    public static Uri saveShareableBitmap(Context context, Bitmap bitmap, String question) {
        drawStamp(context, bitmap, question);

        File tempFile;
        try {
            tempFile = File.createTempFile("mimicker", ".jpg", context.getCacheDir());
            tempFile.setReadable(true, false);
            tempFile.deleteOnExit();
        } catch (IOException ex) {
            Logger.trackException(ex);
            return null;
        }

        if (tempFile.canWrite()) {
            try {
                FileOutputStream stream = new FileOutputStream(tempFile);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
                stream.close();
            } catch (IOException ex) {
                Logger.trackException(ex);
                return null;
            }
        }
        return Uri.fromFile(tempFile);
    }

    private static void drawStamp(Context context, Bitmap bitmap, String question) {
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(bitmap, 0, 0, null);

        float opacity = 0.7f;
        int horizontalPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10,
                context.getResources().getDisplayMetrics());
        int verticalPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10,
                context.getResources().getDisplayMetrics());
        int textSize = 16; // defined in SP
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16,
                context.getResources().getDisplayMetrics());

        LinearLayout layout = new LinearLayout(context);
        layout.setOrientation(LinearLayout.HORIZONTAL);
        layout.setBackgroundResource(R.drawable.rounded_corners);
        layout.getBackground().setAlpha((int) (opacity * 255));
        layout.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);

        ImageView logo = new ImageView(context);
        logo.setImageDrawable(ContextCompat.getDrawable(context, R.mipmap.ic_launcher_no_bg));
        layout.addView(logo);

        TextView textView = new TextView(context);
        textView.setVisibility(View.VISIBLE);
        if (question != null) {
            textView.setText(question);
        } else {
            textView.setText("Mimicker");
        }
        textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize);
        textView.setPadding(horizontalPadding, 0, 0, 0);

        LinearLayout.LayoutParams centerInParent = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        centerInParent.gravity = Gravity.CENTER_VERTICAL;
        layout.addView(textView, centerInParent);

        layout.measure(canvas.getWidth(), height);
        layout.layout(0, 0, layout.getMeasuredWidth(), layout.getMeasuredHeight());

        canvas.translate(horizontalPadding, (float) (canvas.getHeight() * 0.8 - height));
        float scale = Math.min(1.0f, canvas.getWidth() / 1080f);
        canvas.scale(scale, scale);
        layout.draw(canvas);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_shareable, container, false);
        mShareableImage = (ImageView) view.findViewById(R.id.shareable_image);

        view.findViewById(R.id.finish_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finishShare();
            }
        });

        view.findViewById(R.id.share_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Reset the timer to wait sharing to complete
                updateDismissTaskWithDelayDuration(SHARING_FRAGMENT_SHARE_STAY_DURATION);
                share();
            }
        });

        view.findViewById(R.id.download_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Reset the timer to wait downloading to complete
                updateDismissTaskWithDelayDuration(SHARING_FRAGMENT_SAVE_STAY_DURATION);
                download();
            }
        });

        Bundle args = getArguments();
        mShareableUri = args.getString(SHAREABLE_URI);

        // Set up timer to dismiss the sharing fragment if there is no user interaction with the buttons
        mSharingFragmentDismissTask = new Runnable() {
            @Override
            public void run() {
                finishShare();
            }
        };

        mHandler = new Handler();

        Logger.init(getActivity());
        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mCallback = (ShareResultListener) context;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallback = null;
    }

    @Override
    public void onPause() {
        super.onPause();
        mHandler.removeCallbacks(mSharingFragmentDismissTask);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mShareableUri != null && mShareableUri.length() > 0) {
            Uri shareableUri = Uri.parse(mShareableUri);
            mShareableImage.setImageURI(shareableUri);
        }
        mHandler.postDelayed(mSharingFragmentDismissTask, mSharingFragmentDismissTaskDelay);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mShareableUri != null && mShareableUri.length() > 0) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    File deleteFile = new File(mShareableUri);
                    boolean deleted = deleteFile.delete();
                    if (!deleted) {
                        Loggable.AppError appError = new Loggable.AppError(Loggable.Key.APP_ERROR,
                                "Failed to delete shareable");
                        Logger.track(appError);
                    }
                }
            }).start();
        }
        mHandler.removeCallbacks(mToastAutoDismiss);
    }

    public void share() {
        Loggable.UserAction userAction = new Loggable.UserAction(Loggable.Key.ACTION_SHARE);
        Logger.track(userAction);

        mCallback.onRequestLaunchShareAction();

        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        // this causes issues with gmail
        //shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        File file = new File(mShareableUri);
        Uri uri = Uri.fromFile(file);
        shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
        shareIntent.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.share_text_template));
        shareIntent.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.share_subject_template));
        shareIntent.setType("image/*");
        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        startActivityForResult(
                Intent.createChooser(shareIntent, getResources().getString(R.string.share_action_description)),
                SHARE_REQUEST_CODE);
    }

    //
    // Copy the temporary mimic picture to the camera folder with a filename with timestamp
    //
    public void download() {
        File cameraDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

        File sourceFile = new File(mShareableUri);
        String dateTimeString = (new SimpleDateFormat("yyyy-MM-dd-HHmmss").format(new Date())); // Example: 2015-12-31-193205
        String targetFileName = MIMICKER_FILE_PREFIX + dateTimeString + ".jpg"; // "Mimicker_2015-12-31-193205.jpg
        File targetFile = new File(cameraDirectory.getPath(), targetFileName);

        try {
            copyFile(sourceFile, targetFile);
        } catch (IOException ex) {
            showToastInFragment(R.string.share_download_failure);
            Logger.trackException(ex);
            return;
        }

        // Inform the media store about the new file
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.MediaColumns.DATA, targetFile.getPath());
        getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        showToastInFragment(R.string.share_download_success);
    }

    public void copyFile(File sourceFile, File targetFile) throws IOException {
        InputStream inputStream = new FileInputStream(sourceFile);
        OutputStream outputStream = new FileOutputStream(targetFile);

        int len;
        byte[] buffer = new byte[4096];
        while ((len = inputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, len);
        }
        inputStream.close();
        outputStream.close();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SHARE_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                finishShare();
            }
        }
    }

    public void finishShare() {
        mHandler.removeCallbacks(mSharingFragmentDismissTask);
        if (mCallback != null) {
            mCallback.onShareCompleted();
        }
    }

    public interface ShareResultListener {
        void onShareCompleted();

        void onRequestLaunchShareAction();
    }

    // Display the home-made toast message with the specified string resource ID
    //
    // We create our own toast message, instead of using android.widget.toast, because
    // system toast won't work in lock screen.
    private void showToastInFragment(int resourceId) {
        String message = getResources().getString(resourceId);
        final TextView textView = (TextView) getView().findViewById(R.id.share_toast_message);
        textView.setText(message);
        textView.setVisibility(View.VISIBLE);

        Handler handler = new Handler();
        mToastAutoDismiss = new Runnable() {
            @Override
            public void run() {
                textView.setVisibility(View.INVISIBLE);
            }
        };
        handler.postDelayed(mToastAutoDismiss, TOAST_IN_FRAGMENT_DELAY);
    }

    private void updateDismissTaskWithDelayDuration(int delayDuration) {
        mHandler.removeCallbacks(mSharingFragmentDismissTask);
        mSharingFragmentDismissTaskDelay = delayDuration;
        mHandler.postDelayed(mSharingFragmentDismissTask, mSharingFragmentDismissTaskDelay);
    }
}