com.klinker.android.twitter.activities.compose.Compose.java Source code

Java tutorial

Introduction

Here is the source code for com.klinker.android.twitter.activities.compose.Compose.java

Source

/*
 * Copyright 2014 Luke Klinker
 *
 * 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.klinker.android.twitter.activities.compose;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.location.Location;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.support.v4.app.NotificationCompat;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.Patterns;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListPopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.klinker.android.twitter.R;
import com.klinker.android.twitter.data.sq_lite.HashtagDataSource;
import com.klinker.android.twitter.data.sq_lite.QueuedDataSource;
import com.klinker.android.twitter.views.HoloTextView;
import com.klinker.android.twitter.views.NetworkedCacheableImageView;
import com.klinker.android.twitter.settings.AppSettings;
import com.klinker.android.twitter.views.EmojiKeyboard;
import com.klinker.android.twitter.activities.MainActivity;
import com.klinker.android.twitter.utils.IOUtils;
import com.klinker.android.twitter.utils.ImageUtils;
import com.klinker.android.twitter.utils.TweetLinkUtils;
import com.klinker.android.twitter.utils.api_helper.TwitLongerHelper;
import com.klinker.android.twitter.utils.Utils;
import com.klinker.android.twitter.utils.api_helper.TwitPicHelper;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.klinker.android.twitter.utils.text.TextUtils;
import com.yalantis.ucrop.UCrop;

import twitter4j.*;
import uk.co.senab.photoview.PhotoViewAttacher;

public abstract class Compose extends Activity
        implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private static final boolean DEBUG = false;

    public GoogleApiClient mGoogleApiClient;
    public AppSettings settings;
    public Context context;
    public SharedPreferences sharedPrefs;

    public EditText contactEntry;
    public EditText reply;
    public ImageView[] attachImage = new ImageView[4];
    public ImageButton gifButton;
    public ImageButton attachButton;
    public ImageButton emojiButton;
    public EmojiKeyboard emojiKeyboard;
    public ImageButton overflow;
    public TextView charRemaining;
    public ListPopupWindow hashtagAutoComplete;
    public HoloTextView numberAttached;

    protected boolean useAccOne = true;
    protected boolean useAccTwo = false;

    // attach up to four images
    public String[] attachedUri = new String[] { "", "", "", "" };
    public int imagesAttached = 0;

    public PhotoViewAttacher mAttacher;

    public boolean isDM = false;

    public long notiId = 0;
    public String replyText = "";

    public int currentAccount;

    final Pattern p = Patterns.WEB_URL;

    public Handler countHandler;
    public Runnable getCount = new Runnable() {
        @Override
        public void run() {
            String text = reply.getText().toString();

            if (replyText != null && !replyText.contains("/status/")) {
                String replaceable = replyText.replaceAll("#[a-zA-Z]+ ", "");
                text = text.replaceAll(replaceable, "");
            }

            if (!Patterns.WEB_URL.matcher(text).find()) { // no links, normal tweet
                try {
                    charRemaining.setText(140 - text.length() + "");
                } catch (Exception e) {
                    charRemaining.setText("0");
                }
            } else {
                int count = text.length();
                Matcher m = p.matcher(text);
                while (m.find()) {
                    String url = m.group();
                    count -= url.length(); // take out the length of the url
                    count += 23; // add 23 for the shortened url
                }

                charRemaining.setText(140 - count + "");
            }
        }
    };

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).addApi(LocationServices.API).build();

        mGoogleApiClient.connect();
    }

    @Override
    public void finish() {
        super.finish();
        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        overridePendingTransition(R.anim.fade_in, R.anim.fade_out);

        countHandler = new Handler();

        settings = AppSettings.getInstance(this);
        context = this;
        sharedPrefs = context.getSharedPreferences("com.klinker.android.twitter_world_preferences", 0);

        try {
            ViewConfiguration config = ViewConfiguration.get(this);
            Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
            if (menuKeyField != null) {
                menuKeyField.setAccessible(true);
                menuKeyField.setBoolean(config, false);
            }
        } catch (Exception ex) {
            // Ignore
        }

        int currentOrientation = getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
        }

        currentAccount = sharedPrefs.getInt("current_account", 1);

        buildGoogleApiClient();

        Utils.setUpPopupTheme(context, settings);
        setUpWindow();
        setUpLayout();
        setUpActionBar();
        setUpReplyText();

        if (reply.getText().toString().contains(" RT @") || reply.getText().toString().contains("/status/")) {
            reply.setSelection(0);
        }

        if (getIntent().getBooleanExtra("start_attach", false)) {
            attachButton.performClick();
            //overflow.performClick();
        }

        if (notiId != 0) {
            HoloTextView replyTo = (HoloTextView) findViewById(R.id.reply_to);
            replyTo.setText(replyText);
            TextUtils.linkifyText(context, replyTo, null, true, "", true);
            replyTo.setVisibility(View.VISIBLE);
        }

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                String text = reply.getText().toString();

                try {
                    if (!android.text.TextUtils.isEmpty(text)
                            && !(text.startsWith(" RT @") || text.contains("/status/"))) {
                        //text = text.replaceAll("  ", " ");

                        reply.setText(text);
                        reply.setSelection(text.length());

                        if (!text.endsWith(" ")) {
                            reply.append(" ");
                        }
                    }
                } catch (Exception e) {

                }
            }
        }, 250);
    }

    public void setUpWindow() {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
                WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        // Params for the window.
        // You can easily set the alpha and the dim behind the window from here
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.alpha = 1.0f; // lower than one makes it more transparent
        params.dimAmount = .6f; // set it higher if you want to dim behind the window
        getWindow().setAttributes(params);
        getWindow().setBackgroundDrawable(new ColorDrawable(getResources().getColor(android.R.color.transparent)));

        // Gets the display size so that you can set the window to a percent of that
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int width = size.x;
        int height = size.y;

        // You could also easily used an integer value from the shared preferences to set the percent
        if (height > width) {
            getWindow().setLayout((int) (width * .9), (int) (height * .9));
        } else {
            getWindow().setLayout((int) (width * .7), (int) (height * .8));
        }
    }

    public void setUpActionBar() {
        findViewById(R.id.send_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Compose.this instanceof ComposeDMActivity) {
                    boolean close = doneClick();
                    if (close) {
                        onBackPressed();
                    }

                    return;
                }
                if (Integer.parseInt(charRemaining.getText().toString()) < 0 && settings.twitlonger) {
                    new AlertDialog.Builder(context)
                            .setTitle(context.getResources().getString(R.string.tweet_to_long))
                            .setMessage(context.getResources().getString(R.string.select_shortening_service))
                            .setPositiveButton(R.string.twitlonger, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    doneClick();
                                }
                            }).setNeutralButton(R.string.pwiccer, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    try {
                                        Intent pwiccer = new Intent("com.t3hh4xx0r.pwiccer.requestImagePost");
                                        pwiccer.putExtra("POST_CONTENT", reply.getText().toString());
                                        startActivityForResult(pwiccer, 420);
                                    } catch (Throwable e) {
                                        // open the play store here
                                        // they don't have pwiccer installed
                                        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(
                                                "https://play.google.com/store/apps/details?id=com.t3hh4xx0r.pwiccer&hl=en")));
                                    }
                                }
                            }).setNegativeButton(R.string.edit, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                }
                            }).create().show();
                } else {
                    boolean close = doneClick();
                    if (close) {
                        onBackPressed();
                    }
                }
            }
        });
        findViewById(R.id.discard_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                discardClicked = true;
                sharedPrefs.edit().putString("draft", "").commit();
                if (emojiKeyboard.isShowing()) {
                    onBackPressed();
                }
                onBackPressed();
            }
        });

    }

    public void setUpSimilar() {
        attachImage[0] = (ImageView) findViewById(R.id.picture1);
        attachImage[1] = (ImageView) findViewById(R.id.picture2);
        attachImage[2] = (ImageView) findViewById(R.id.picture3);
        attachImage[3] = (ImageView) findViewById(R.id.picture4);
        attachButton = (ImageButton) findViewById(R.id.attach);
        gifButton = (ImageButton) findViewById(R.id.gif);
        emojiButton = (ImageButton) findViewById(R.id.emoji);
        emojiKeyboard = (EmojiKeyboard) findViewById(R.id.emojiKeyboard);
        reply = (EditText) findViewById(R.id.tweet_content);
        charRemaining = (TextView) findViewById(R.id.char_remaining);

        findViewById(R.id.prompt_pos).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.v("talon_input", "clicked the view");
                ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(reply,
                        InputMethodManager.SHOW_FORCED);
            }
        });

        NetworkedCacheableImageView pic = (NetworkedCacheableImageView) findViewById(R.id.profile_pic);
        HoloTextView currentName = (HoloTextView) findViewById(R.id.current_name);

        if (settings.roundContactImages) {
            pic.loadImage(settings.myProfilePicUrl, false, null, NetworkedCacheableImageView.CIRCLE);
        } else {
            pic.loadImage(settings.myProfilePicUrl, false, null);
        }
        currentName.setText("@" + settings.myScreenName);

        //numberAttached.setText("0 " + getString(R.string.attached_images));

        charRemaining.setText(140 - reply.getText().length() + "");

        reply.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                countHandler.removeCallbacks(getCount);
                countHandler.postDelayed(getCount, 300);
            }
        });
    }

    void handleSendText(Intent intent) {
        String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
        String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
        if (sharedText != null) {
            if (!isDM) {
                if (subject != null && !subject.equals(sharedText)) {
                    reply.setText(subject + " - " + sharedText);
                } else {
                    reply.setText(sharedText);
                }
                reply.setSelection(reply.getText().toString().length());
            } else {
                contactEntry.setText(sharedText);
                reply.requestFocus();
            }
        }
    }

    private Bitmap getThumbnail(Uri uri) throws FileNotFoundException, IOException {
        InputStream input = getContentResolver().openInputStream(uri);
        int reqWidth = 150;
        int reqHeight = 150;

        byte[] byteArr = new byte[0];
        byte[] buffer = new byte[1024];
        int len;
        int count = 0;

        try {
            while ((len = input.read(buffer)) > -1) {
                if (len != 0) {
                    if (count + len > byteArr.length) {
                        byte[] newbuf = new byte[(count + len) * 2];
                        System.arraycopy(byteArr, 0, newbuf, 0, count);
                        byteArr = newbuf;
                    }

                    System.arraycopy(buffer, 0, byteArr, count, len);
                    count += len;
                }
            }

            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(byteArr, 0, count, options);

            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inJustDecodeBounds = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

            Bitmap b = BitmapFactory.decodeByteArray(byteArr, 0, count, options);

            ExifInterface exif = new ExifInterface(IOUtils.getPath(uri, context));
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);

            b = ImageUtils.cropSquare(b);

            return rotateBitmap(b, orientation);

        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
    }

    public Bitmap getBitmapToSend(Uri uri) throws IOException {
        InputStream input = getContentResolver().openInputStream(uri);
        int reqWidth = 750;
        int reqHeight = 750;

        byte[] byteArr = new byte[0];
        byte[] buffer = new byte[1024];
        int len;
        int count = 0;

        try {
            while ((len = input.read(buffer)) > -1) {
                if (len != 0) {
                    if (count + len > byteArr.length) {
                        byte[] newbuf = new byte[(count + len) * 2];
                        System.arraycopy(byteArr, 0, newbuf, 0, count);
                        byteArr = newbuf;
                    }

                    System.arraycopy(buffer, 0, byteArr, count, len);
                    count += len;
                }
            }

            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(byteArr, 0, count, options);

            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inJustDecodeBounds = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

            Bitmap b = BitmapFactory.decodeByteArray(byteArr, 0, count, options);

            ExifInterface exif = new ExifInterface(IOUtils.getPath(uri, context));
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);

            input.close();

            return rotateBitmap(b, orientation);

        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
    }

    public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {

        Log.v("talon_composing_image", "rotation: " + orientation);

        try {
            Matrix matrix = new Matrix();
            switch (orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                return bitmap;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                matrix.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                matrix.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                matrix.setRotate(180);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                matrix.setRotate(90);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                matrix.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                matrix.setRotate(-90);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                matrix.setRotate(-90);
                break;
            default:
                return bitmap;
            }
            try {
                Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,
                        true);
                bitmap.recycle();
                return bmRotated;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    void handleSendImage(Intent intent) {
        Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
        if (imageUri != null) {
            //String filePath = IOUtils.getPath(imageUri, context);
            try {
                attachImage[imagesAttached].setImageBitmap(getThumbnail(imageUri));
                attachImage[imagesAttached].setVisibility(View.VISIBLE);
                attachedUri[imagesAttached] = imageUri.toString();
                imagesAttached++;
                //numberAttached.setText(imagesAttached + " " + getResources().getString(R.string.attached_images));
                //numberAttached.setVisibility(View.VISIBLE);
            } catch (FileNotFoundException e) {
                Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT);
                //numberAttached.setText("");
                //numberAttached.setVisibility(View.GONE);
            } catch (IOException e) {
                Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT);
                //numberAttached.setText("");
                //numberAttached.setVisibility(View.GONE);
            }
        }
    }

    public boolean addLocation = false;

    public void displayErrorNotification(final Exception e) {

        if (!DEBUG) {
            return;
        }

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_icon)
                .setContentTitle(getResources().getString(R.string.tweet_failed)).setContentText(e.getMessage());

        NotificationManager mNotificationManager = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(221, mBuilder.build());
    }

    public void makeFailedNotification(String text) {
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_icon)
                .setContentTitle(getResources().getString(R.string.tweet_failed))
                .setContentText(getResources().getString(R.string.tap_to_retry));

        Intent resultIntent = new Intent(this, RetryCompose.class);
        QueuedDataSource.getInstance(this).createDraft(text, settings.currentAccount);
        resultIntent.setAction(Intent.ACTION_SEND);
        resultIntent.setType("text/plain");
        resultIntent.putExtra("failed_notification", true);

        PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, 0);

        mBuilder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(5, mBuilder.build());
        mNotificationManager.cancel(6);
    }

    public void makeTweetingNotification() {
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_icon).setOngoing(true).setProgress(100, 0, true);

        if (Compose.this instanceof ComposeDMActivity) {
            mBuilder.setContentTitle(getResources().getString(R.string.sending_direct_message));
        } else {
            mBuilder.setContentTitle(getResources().getString(R.string.sending_tweet));
        }

        Intent resultIntent = new Intent(this, MainActivity.class);

        PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, 0);

        mBuilder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(6, mBuilder.build());
    }

    public void finishedTweetingNotification() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
                            .setSmallIcon(R.drawable.ic_stat_icon)
                            .setContentTitle(getResources().getString(R.string.tweet_success)).setOngoing(false)
                            .setTicker(getResources().getString(R.string.tweet_success));

                    if (settings.vibrate) {
                        Log.v("talon_vibrate", "vibrate on compose");
                        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                        long[] pattern = { 0, 50, 500 };
                        v.vibrate(pattern, -1);
                    }

                    NotificationManager mNotificationManager = (NotificationManager) getSystemService(
                            Context.NOTIFICATION_SERVICE);
                    mNotificationManager.notify(6, mBuilder.build());
                    // cancel it immediately, the ticker will just go off
                    mNotificationManager.cancel(6);
                } catch (Exception e) {
                    // not attached?
                }
            }
        }, 500);

    }

    Location mLastLocation;

    @Override
    public void onConnected(Bundle bundle) {
        Log.v("location", "connected");
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        //Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT).show();
        Log.v("location", "failed");
    }

    @Override
    public void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    private void startUcrop(Uri sourceUri) {
        try {
            UCrop.Options options = new UCrop.Options();
            options.setCompressionFormat(Bitmap.CompressFormat.JPEG);
            options.setCompressionQuality(90);

            File destination = File.createTempFile("ucrop", "jpg", getCacheDir());
            UCrop.of(sourceUri, Uri.fromFile(destination)).withOptions(options).start(Compose.this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static final int SELECT_PHOTO = 100;
    public static final int CAPTURE_IMAGE = 101;
    public static final int SELECT_GIF = 102;
    public static final int SELECT_VIDEO = 103;
    public static final int FIND_GIF = 104;
    public static final int PWICCER = 420;

    public boolean pwiccer = false;

    public String attachmentType = "";

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        Log.v("talon_image_attach", "got the result, code: " + requestCode);
        switch (requestCode) {
        case UCrop.REQUEST_CROP:
            if (resultCode == RESULT_OK) {
                try {
                    Uri selectedImage = UCrop.getOutput(imageReturnedIntent);

                    String filePath = IOUtils.getPath(selectedImage, context);
                    Log.v("talon_compose_pic", "path to gif on sd card: " + filePath);

                    try {
                        attachImage[imagesAttached].setImageBitmap(getThumbnail(selectedImage));
                        attachImage[imagesAttached].setVisibility(View.VISIBLE);
                        attachedUri[imagesAttached] = selectedImage.toString();
                        imagesAttached++;
                    } catch (Throwable e) {
                        Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT).show();
                }
            } else if (resultCode == UCrop.RESULT_ERROR) {
                final Throwable cropError = UCrop.getError(imageReturnedIntent);
                cropError.printStackTrace();
            }
            countHandler.post(getCount);
            break;
        case SELECT_PHOTO:
            if (resultCode == RESULT_OK) {
                startUcrop(imageReturnedIntent.getData());
            }

            break;
        case CAPTURE_IMAGE:
            if (resultCode == RESULT_OK) {
                Uri selectedImage = Uri.fromFile(
                        new File(Environment.getExternalStorageDirectory() + "/Talon/", "photoToTweet.jpg"));
                startUcrop(selectedImage);
            }

            break;
        case PWICCER:
            if (resultCode == Activity.RESULT_OK) {
                String path = imageReturnedIntent.getStringExtra("RESULT");
                attachedUri[imagesAttached] = Uri.fromFile(new File(path)).toString();

                try {
                    attachImage[imagesAttached]
                            .setImageBitmap(getThumbnail(Uri.parse(attachedUri[imagesAttached])));
                    attachImage[imagesAttached].setVisibility(View.VISIBLE);
                    imagesAttached++;
                    //numberAttached.setText(imagesAttached + " " + getResources().getString(R.string.attached_images));
                    //numberAttached.setVisibility(View.VISIBLE);
                } catch (FileNotFoundException e) {
                    Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT);
                    //numberAttached.setText("");
                    //numberAttached.setVisibility(View.GONE);
                } catch (IOException e) {
                    Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT);
                    //numberAttached.setText("");
                    //numberAttached.setVisibility(View.GONE);
                }

                String currText = imageReturnedIntent.getStringExtra("RESULT_TEXT");
                Log.v("pwiccer_text", currText);
                Log.v("pwiccer_text", "length: " + currText.length());
                if (currText != null) {
                    reply.setText(currText);
                } else {
                    reply.setText(reply.getText().toString().substring(0, 114) + "...");
                }

                pwiccer = true;

                doneClick();
                onBackPressed();
            } else {
                Toast.makeText(context, "Pwiccer failed to generate image! Is it installed?", Toast.LENGTH_SHORT)
                        .show();
            }
            countHandler.post(getCount);
            break;
        case FIND_GIF:
        case SELECT_GIF:
            if (resultCode == RESULT_OK) {
                try {
                    Uri selectedImage = imageReturnedIntent.getData();

                    String filePath = IOUtils.getPath(selectedImage, context);

                    Log.v("talon_compose_pic", "path to gif on sd card: " + filePath);

                    attachImage[0].setImageURI(selectedImage);
                    attachImage[0].setVisibility(View.VISIBLE);
                    attachedUri[0] = selectedImage.toString();
                    imagesAttached = 1;

                    attachmentType = "animated_gif";

                    attachButton.setEnabled(false);
                } catch (Throwable e) {
                    e.printStackTrace();
                    Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT).show();
                }
            }
            countHandler.post(getCount);
            break;
        case SELECT_VIDEO:
            if (resultCode == RESULT_OK) {
                try {
                    Uri selectedImage = imageReturnedIntent.getData();

                    String filePath = IOUtils.getPath(selectedImage, context);

                    Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(filePath,
                            MediaStore.Images.Thumbnails.MINI_KIND);

                    Log.v("talon_compose_pic", "path to video on sd card: " + filePath);

                    attachImage[0].setImageBitmap(thumbnail);
                    attachImage[0].setVisibility(View.VISIBLE);
                    attachedUri[0] = selectedImage.toString();
                    imagesAttached = 1;

                    attachmentType = "video";

                    attachButton.setEnabled(false);
                } catch (Throwable e) {
                    e.printStackTrace();
                    Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT).show();
                }
            }
            countHandler.post(getCount);
            break;
        }

        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    }

    @Override
    public void onBackPressed() {
        if (emojiKeyboard.isShowing()) {
            emojiKeyboard.setVisibility(false);

            TypedArray a = getTheme().obtainStyledAttributes(new int[] { R.attr.emoji_button_changing });
            int resource = a.getResourceId(0, 0);
            a.recycle();
            emojiButton.setImageResource(resource);
            return;
        }

        super.onBackPressed();
    }

    public boolean doneClicked = false;
    public boolean discardClicked = false;

    class SendDirectMessage extends AsyncTask<String, String, Boolean> {

        @Override
        protected void onPreExecute() {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    makeTweetingNotification();
                }
            }, 200);
            super.onPreExecute();

        }

        protected Boolean doInBackground(String... args) {
            String status = args[0];

            try {
                Twitter twitter = Utils.getTwitter(getApplicationContext(), settings);

                if (!attachedUri.equals("")) {
                    try {
                        for (int i = 0; i < imagesAttached; i++) {
                            File outputDir = context.getCacheDir();
                            File f = File.createTempFile("compose", "picture_" + i, outputDir);

                            Bitmap bitmap = getBitmapToSend(Uri.parse(attachedUri[i]));
                            ByteArrayOutputStream bos = new ByteArrayOutputStream();
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                            byte[] bitmapdata = bos.toByteArray();

                            FileOutputStream fos = new FileOutputStream(f);
                            fos.write(bitmapdata);
                            fos.flush();
                            fos.close();

                            // we wont attach any text to this image at least, since it is a direct message
                            TwitPicHelper helper = new TwitPicHelper(twitter, " ", f, context);
                            String url = helper.uploadForUrl();

                            status += " " + url;
                        }
                    } catch (Exception e) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(context, getString(R.string.error_attaching_image),
                                        Toast.LENGTH_SHORT).show();
                            }
                        });
                    }

                }

                String sendTo = contactEntry.getText().toString().replace("@", "").replace(" ", "");

                twitter.sendDirectMessage(sendTo, status);

                return true;

            } catch (TwitterException e) {
                e.printStackTrace();
            }

            return false;
        }

        protected void onPostExecute(Boolean sent) {
            // dismiss the dialog after getting all products

            if (sent) {
                finishedTweetingNotification();
            } else {
                Toast.makeText(getBaseContext(), getResources().getString(R.string.error), Toast.LENGTH_SHORT)
                        .show();
            }

            context.sendBroadcast(new Intent("com.klinker.android.twitter.UPDATE_DM"));
        }

    }

    class updateTwitterStatus extends AsyncTask<String, String, Boolean> {

        String text;
        String status;
        private boolean secondTry;
        private int remaining;
        private InputStream stream;

        public updateTwitterStatus(String text, int length) {
            this.text = text;
            this.remaining = length;
            this.secondTry = false;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    makeTweetingNotification();
                }
            }, 200);
        }

        public updateTwitterStatus(String text, int length, boolean secondTry) {
            this.text = text;
            this.remaining = length;
            this.secondTry = secondTry;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    makeTweetingNotification();
                }
            }, 200);
        }

        protected Boolean doInBackground(String... args) {
            status = args[0];
            try {
                Twitter twitter = Utils.getTwitter(getApplicationContext(), settings);
                Twitter twitter2 = Utils.getSecondTwitter(getApplicationContext());

                if (remaining < 0 && !pwiccer) {
                    // twitlonger goes here

                    boolean isDone = false;

                    if (useAccOne) {
                        TwitLongerHelper helper = new TwitLongerHelper(text, twitter);

                        if (notiId != 0) {
                            helper.setInReplyToStatusId(notiId);
                        }

                        if (addLocation) {
                            if (waitForLocation()) {
                                Location location = mLastLocation;
                                GeoLocation geolocation = new GeoLocation(location.getLatitude(),
                                        location.getLongitude());
                                helper.setLocation(geolocation);
                            }
                        }

                        if (helper.createPost() != 0) {
                            isDone = true;
                        }
                    }

                    if (useAccTwo) {
                        TwitLongerHelper helper = new TwitLongerHelper(text, twitter2);

                        if (notiId != 0) {
                            helper.setInReplyToStatusId(notiId);
                        }

                        if (addLocation) {
                            waitForLocation();

                            if (waitForLocation()) {
                                Location location = mLastLocation;
                                GeoLocation geolocation = new GeoLocation(location.getLatitude(),
                                        location.getLongitude());
                                helper.setLocation(geolocation);
                            }
                        }

                        if (helper.createPost() != 0) {
                            isDone = true;
                        }
                    }

                    return isDone;
                } else {
                    boolean autoPopulateMetadata = false;
                    if (replyText != null && !replyText.contains("/status/")) {
                        String replaceable = replyText.replaceAll("#[a-zA-Z]+ ", "");
                        status = status.replaceAll(replaceable, "");
                        autoPopulateMetadata = true;
                    }

                    StatusUpdate media = new StatusUpdate(status);
                    media.setAutoPopulateReplyMetadata(autoPopulateMetadata);

                    if (notiId != 0) {
                        media.setInReplyToStatusId(notiId);
                    }

                    if (imagesAttached == 0) {
                        // Update status
                        if (addLocation) {
                            if (waitForLocation()) {
                                Location location = mLastLocation;
                                GeoLocation geolocation = new GeoLocation(location.getLatitude(),
                                        location.getLongitude());
                                media.setLocation(geolocation);
                            }
                        }

                        if (useAccOne) {
                            twitter.updateStatus(media);
                        }
                        if (useAccTwo) {
                            twitter2.updateStatus(media);
                        }

                        return true;

                    } else {
                        // status with picture(s)
                        File[] files = new File[imagesAttached];
                        File outputDir = context.getCacheDir();

                        if (attachButton.isEnabled()) {
                            for (int i = 0; i < imagesAttached; i++) {
                                files[i] = File.createTempFile("compose", "picture_" + i, outputDir);

                                Bitmap bitmap = getBitmapToSend(Uri.parse(attachedUri[i]));
                                ByteArrayOutputStream bos = new ByteArrayOutputStream();

                                if (secondTry) {
                                    bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth() / 2,
                                            bitmap.getHeight() / 2, true);
                                }

                                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                                byte[] bitmapdata = bos.toByteArray();

                                FileOutputStream fos = new FileOutputStream(files[i]);
                                fos.write(bitmapdata);
                                fos.flush();
                                fos.close();
                            }
                        }

                        if (settings.twitpic && attachButton.isEnabled()) {
                            boolean isDone = false;

                            if (useAccOne) {
                                // attach pics 1 - 3
                                for (int i = 1; i < imagesAttached; i++) {
                                    TwitPicHelper helper = new TwitPicHelper(twitter, "", files[i], context);
                                    text += " " + helper.uploadForUrl();
                                }

                                // post the status with the 0th picture attached
                                TwitPicHelper helper = new TwitPicHelper(twitter, text, files[0], context);
                                if (addLocation) {
                                    if (waitForLocation()) {
                                        Location location = mLastLocation;
                                        GeoLocation geolocation = new GeoLocation(location.getLatitude(),
                                                location.getLongitude());
                                        media.setLocation(geolocation);
                                    }
                                }
                                if (helper.createPost() != 0) {
                                    isDone = true;
                                }
                            }
                            if (useAccTwo) {
                                for (int i = 1; i < imagesAttached; i++) {
                                    TwitPicHelper helper = new TwitPicHelper(twitter2, "", files[i], context);
                                    text += " " + helper.uploadForUrl();
                                }

                                TwitPicHelper helper = new TwitPicHelper(twitter2, text, files[0], context);
                                if (addLocation) {
                                    if (waitForLocation()) {
                                        Location location = mLastLocation;
                                        GeoLocation geolocation = new GeoLocation(location.getLatitude(),
                                                location.getLongitude());
                                        media.setLocation(geolocation);
                                    }
                                }
                                if (helper.createPost() != 0) {
                                    isDone = true;
                                }
                            }
                            return isDone;
                        } else {
                            // use twitter4j's because it is easier
                            if (attachButton.isEnabled()) {
                                if (imagesAttached == 1) {
                                    media.setMedia(files[0]);
                                } else {
                                    // has multiple images and should be done through twitters service

                                    long[] mediaIds = new long[files.length];
                                    for (int i = 0; i < files.length; i++) {
                                        UploadedMedia upload = twitter.uploadMedia(files[i]);
                                        mediaIds[i] = upload.getMediaId();
                                    }

                                    media.setMediaIds(mediaIds);

                                }
                            } else {
                                // animated gif
                                Log.v("talon_compose", "attaching: " + attachmentType);
                                media.setMedia(attachmentType,
                                        getContentResolver().openInputStream(Uri.parse(attachedUri[0])));
                            }

                            if (addLocation) {
                                if (waitForLocation()) {
                                    Location location = mLastLocation;
                                    GeoLocation geolocation = new GeoLocation(location.getLatitude(),
                                            location.getLongitude());
                                    media.setLocation(geolocation);
                                }
                            }

                            twitter4j.Status s = null;
                            if (useAccOne) {
                                s = twitter.updateStatus(media);
                            }
                            if (useAccTwo) {
                                s = twitter2.updateStatus(media);
                            }

                            if (s != null) {
                                final String[] hashtags = TweetLinkUtils.getLinksInStatus(s)[3].split("  ");

                                if (hashtags != null) {
                                    // we will add them to the auto complete
                                    new Thread(new Runnable() {
                                        @Override
                                        public void run() {
                                            ArrayList<String> tags = new ArrayList<String>();
                                            if (hashtags != null) {
                                                for (String s : hashtags) {
                                                    if (!s.equals("")) {
                                                        tags.add("#" + s);
                                                    }
                                                }
                                            }

                                            HashtagDataSource source = HashtagDataSource.getInstance(context);

                                            for (String s : tags) {
                                                if (s.contains("#")) {
                                                    // we want to add it to the auto complete

                                                    source.deleteTag(s);
                                                    source.createTag(s);
                                                }
                                            }
                                        }
                                    }).start();
                                }
                            }

                            return true;
                        }

                    }
                }

            } catch (final Exception e) {
                e.printStackTrace();

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        displayErrorNotification(e);
                    }
                });

                if (e.getMessage() != null && e.getMessage().contains("the uploaded media is too large.")) {
                    tryingAgain = true;
                    return false;
                }
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                outofmem = true;
            }
            return false;
        }

        private boolean waitForLocation() {
            if (mLastLocation == null) {
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1500);
                    } catch (Exception e) {

                    }
                    if (mLastLocation != null) {
                        break;
                    }
                }
            }

            return mLastLocation != null;
        }

        boolean outofmem = false;
        boolean tryingAgain = false;

        protected void onPostExecute(Boolean success) {
            // dismiss the dialog after getting all products
            try {
                stream.close();
            } catch (Throwable e) {
                e.printStackTrace();
            }

            if (!tryingAgain) {
                if (success) {
                    finishedTweetingNotification();
                } else if (outofmem) {
                    Toast.makeText(context, getString(R.string.error_attaching_image), Toast.LENGTH_SHORT).show();
                } else {
                    makeFailedNotification(text);
                }
            } else {
                new updateTwitterStatus(text, remaining, true).execute(status);
            }
        }
    }

    public Bitmap decodeSampledBitmapFromResourceMemOpt(InputStream inputStream, int reqWidth, int reqHeight) {

        byte[] byteArr = new byte[0];
        byte[] buffer = new byte[1024];
        int len;
        int count = 0;

        try {
            while ((len = inputStream.read(buffer)) > -1) {
                if (len != 0) {
                    if (count + len > byteArr.length) {
                        byte[] newbuf = new byte[(count + len) * 2];
                        System.arraycopy(byteArr, 0, newbuf, 0, count);
                        byteArr = newbuf;
                    }

                    System.arraycopy(buffer, 0, byteArr, count, len);
                    count += len;
                }
            }

            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(byteArr, 0, count, options);

            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inJustDecodeBounds = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

            return BitmapFactory.decodeByteArray(byteArr, 0, count, options);

        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
    }

    public int calculateInSampleSize(BitmapFactory.Options opt, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = opt.outHeight;
        final int width = opt.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public abstract boolean doneClick();

    public abstract void setUpLayout();

    public abstract void setUpReplyText();

    public int toDP(int px) {
        try {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, px,
                    getResources().getDisplayMetrics());
        } catch (Exception e) {
            return px;
        }
    }
}