diff --git a/app/src/main/java/com/klinker/android/twitter/activities/DirectMessageConversation.java b/app/src/main/java/com/klinker/android/twitter/activities/DirectMessageConversation.java index 4485791..4a5ce84 100644 --- a/app/src/main/java/com/klinker/android/twitter/activities/DirectMessageConversation.java +++ b/app/src/main/java/com/klinker/android/twitter/activities/DirectMessageConversation.java @@ -32,12 +32,15 @@ import android.graphics.BitmapFactory; import android.graphics.Point; import android.graphics.drawable.ColorDrawable; +import android.media.ExifInterface; import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.provider.MediaStore; +import android.support.v4.content.FileProvider; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; @@ -56,18 +59,22 @@ import android.widget.LinearLayout; import android.widget.Toast; +import com.klinker.android.twitter.BuildConfig; import com.klinker.android.twitter.R; +import com.klinker.android.twitter.activities.compose.Compose; import com.klinker.android.twitter.adapters.CursorListLoader; import com.klinker.android.twitter.adapters.TimeLineCursorAdapter; import com.klinker.android.twitter.data.App; import com.klinker.android.twitter.data.sq_lite.DMDataSource; import com.klinker.android.twitter.settings.AppSettings; +import com.klinker.android.twitter.utils.ImageUtils; import com.klinker.android.twitter.views.HoloEditText; import com.klinker.android.twitter.views.HoloTextView; import com.klinker.android.twitter.activities.setup.LoginActivity; import com.klinker.android.twitter.utils.IOUtils; import com.klinker.android.twitter.utils.Utils; import com.klinker.android.twitter.utils.api_helper.TwitPicHelper; +import com.yalantis.ucrop.UCrop; import org.lucasr.smoothie.AsyncListView; import org.lucasr.smoothie.ItemManager; @@ -79,11 +86,16 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; +import java.net.URI; import java.util.regex.Matcher; import java.util.regex.Pattern; +import twitter4j.DirectMessageEvent; +import twitter4j.MessageData; import twitter4j.Twitter; import twitter4j.TwitterException; +import twitter4j.UploadedMedia; +import twitter4j.User; import uk.co.senab.bitmapcache.BitmapLruCache; @@ -356,38 +368,39 @@ protected Boolean doInBackground(String... args) { try { Twitter twitter = Utils.getTwitter(getApplicationContext(), settings); + String sendTo = listName; + User user = twitter.showUser(sendTo); + MessageData data = new MessageData(user.getId(), status); + if (!attachedUri.equals("")) { try { - File outputDir = context.getCacheDir(); - File f = File.createTempFile("compose", "picture", outputDir); - - Bitmap bitmap = getBitmapToSend(Uri.parse(attachedUri)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); - byte[] bitmapdata = bos.toByteArray(); + File f; - 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(); + if (attachmentType == null) { + // image file + f = ImageUtils.scaleToSend(context, Uri.parse(attachedUri)); + } else { + f = new File(URI.create(attachedUri)); + } - status += " " + url; + UploadedMedia media = twitter.uploadMedia(f); + data.setMediaId(media.getMediaId()); } catch (Exception e) { - Toast.makeText(context, getString(R.string.error_attaching_image), Toast.LENGTH_SHORT).show(); + e.printStackTrace(); + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(context, getString(R.string.error_attaching_image), Toast.LENGTH_SHORT).show(); + } + }); } } - String sendTo = listName; - - twitter4j.DirectMessage message = twitter.sendDirectMessage(sendTo, status); + DirectMessageEvent message = twitter.createMessage(data); if (!settings.pushNotifications) { - DMDataSource.getInstance(context).createDirectMessage(message, settings.currentAccount); + DMDataSource.getInstance(context).createSentDirectMessage(message, user, settings, settings.currentAccount); } sharedPrefs.edit().putLong("last_direct_message_id_" + sharedPrefs.getInt("current_account", 1), message.getId()).commit(); @@ -466,38 +479,7 @@ public boolean onOptionsItemSelected(MenuItem item) { onBackPressed(); return true; case R.id.menu_attach_picture: - // if they haven't seen the disclaimer, show it to them - if (!sharedPrefs.getBoolean("knows_twitpic_dm_warning", false)) { - new AlertDialog.Builder(context) - .setTitle(context.getResources().getString(R.string.twitpic_disclaimer)) - .setMessage(getResources().getString(R.string.twitpic_disclaimer_summary)) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - attachImage(); - dialogInterface.dismiss(); - } - }) - .setNeutralButton(R.string.dont_show_again, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - sharedPrefs.edit().putBoolean("knows_twitpic_dm_warning", true).commit(); - attachImage(); - dialogInterface.dismiss(); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - dialogInterface.dismiss(); - } - }) - .create() - .show(); - } else { - // they know and don't want to see the disclaimer again - attachImage(); - } + attachImage(); return true; default: return super.onOptionsItemSelected(item); @@ -506,71 +488,99 @@ public void onClick(DialogInterface dialogInterface, int i) { public ImageView attachImage; public String attachedUri = ""; + public String attachmentType = ""; public static final int SELECT_PHOTO = 100; public static final int CAPTURE_IMAGE = 101; - public static final int PWICCER = 420; - - public boolean pwiccer = false; + public static final int SELECT_GIF = 102; + public static final int FIND_GIF = 104; protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { - super.onActivityResult(requestCode, resultCode, imageReturnedIntent); - - switch(requestCode) { - case SELECT_PHOTO: - if(resultCode == RESULT_OK){ + Log.v("talon_image_attach", "got the result, code: " + requestCode); + switch (requestCode) { + case UCrop.REQUEST_CROP: + if (resultCode == RESULT_OK) { try { - Uri selectedImage = imageReturnedIntent.getData(); + Uri selectedImage = UCrop.getOutput(imageReturnedIntent); String filePath = IOUtils.getPath(selectedImage, context); - - Log.v("talon_compose_pic", "path to image on sd card: " + filePath); + Log.v("talon_compose_pic", "path to gif on sd card: " + filePath); try { - attachImage.setImageBitmap(getBitmapToSend(selectedImage)); + attachImage.setImageBitmap(getThumbnail(selectedImage)); attachImage.setVisibility(View.VISIBLE); attachedUri = selectedImage.toString(); - new Handler().post(getCount); - } catch (FileNotFoundException e) { - Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT); - } catch (IOException e) { + } 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 == Activity.RESULT_OK) { + if (resultCode == RESULT_OK) { + Uri selectedImage = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/Talon/", "photoToTweet.jpg")); + startUcrop(selectedImage); + } + + break; + case FIND_GIF: + case SELECT_GIF: + if (resultCode == RESULT_OK) { try { - Uri selectedImage = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/Talon/", "photoToTweet.jpg")); + Uri selectedImage = imageReturnedIntent.getData(); - try { - attachImage.setImageBitmap(getBitmapToSend(selectedImage)); - attachImage.setVisibility(View.VISIBLE); - attachedUri = selectedImage.toString(); - new Handler().post(getCount); - } catch (FileNotFoundException e) { - Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT); - } catch (IOException e) { - Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT); - } + String filePath = IOUtils.getPath(selectedImage, context); + + Log.v("talon_compose_pic", "path to gif on sd card: " + filePath); + attachImage.setImageBitmap(getThumbnail(selectedImage)); + attachImage.setVisibility(View.VISIBLE); + attachedUri = selectedImage.toString(); + attachmentType = "animated_gif"; } catch (Throwable e) { e.printStackTrace(); - Toast.makeText(this, getResources().getString(R.string.error), Toast.LENGTH_SHORT).show(); + Toast.makeText(context, getResources().getString(R.string.error), Toast.LENGTH_SHORT).show(); } } + countHandler.post(getCount); break; } + + super.onActivityResult(requestCode, resultCode, imageReturnedIntent); + } + + 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(DirectMessageConversation.this); + } catch (Exception e) { + e.printStackTrace(); + } } public void attachImage() { AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setItems(R.array.attach_options, new DialogInterface.OnClickListener() { + builder.setItems(R.array.attach_dm_options, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { if(item == 0) { // take picture Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); @@ -585,21 +595,50 @@ public void onClick(DialogInterface dialog, int item) { } } - captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); - startActivityForResult(captureIntent, CAPTURE_IMAGE); - } else { // attach picture - if (attachedUri == null || attachedUri.equals("")) { - Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); - photoPickerIntent.setType("image/*"); - startActivityForResult(photoPickerIntent, SELECT_PHOTO); - } else { - attachedUri = ""; - attachImage.setImageDrawable(null); - attachImage.setVisibility(View.GONE); + captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + + try { + Uri photoURI = FileProvider.getUriForFile(context, + BuildConfig.APPLICATION_ID + ".provider", f); + + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); + startActivityForResult(captureIntent, CAPTURE_IMAGE); + } catch (Exception e) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Toast.makeText(DirectMessageConversation.this, "Have you given Talon the storage permission?", Toast.LENGTH_LONG).show(); + } + } + + } else if (item == 1) { // attach picture + try { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PHOTO); + } catch (Exception e) { Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); - startActivityForResult(photoPickerIntent, SELECT_PHOTO); + startActivityForResult(Intent.createChooser(photoPickerIntent, + "Select Picture"), SELECT_PHOTO); + } + } else if (item == 2) { + Toast.makeText(DirectMessageConversation.this, "GIFs must be less than 5 MB", Toast.LENGTH_SHORT).show(); + + try { + Intent gifIntent = new Intent(); + gifIntent.setType("image/gif"); + gifIntent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(gifIntent, SELECT_GIF); + } catch (Exception e) { + Intent gifIntent = new Intent(); + gifIntent.setType("image/gif"); + gifIntent.setAction(Intent.ACTION_PICK); + startActivityForResult(gifIntent, SELECT_GIF); } + } else if (item == 3) { + Intent gif = new Intent(context, GiphySearch.class); + startActivityForResult(gif, FIND_GIF); } } }); @@ -607,36 +646,62 @@ public void onClick(DialogInterface dialog, int item) { builder.create().show(); } - private Bitmap getBitmapToSend(Uri uri) throws IOException { + + private Bitmap getThumbnail(Uri uri) throws IOException { InputStream input = getContentResolver().openInputStream(uri); + int reqWidth = 150; + int reqHeight = 150; - BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options(); - onlyBoundsOptions.inJustDecodeBounds = true; - onlyBoundsOptions.inDither=true;//optional - onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional - BitmapFactory.decodeStream(input, null, onlyBoundsOptions); - input.close(); - if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) - return null; + 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; + } - int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth; + System.arraycopy(buffer, 0, byteArr, count, len); + count += len; + } + } - double ratio = (originalSize > 1000) ? (originalSize / 1000) : 1.0; + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(byteArr, 0, count, options); - BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); - bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio); - bitmapOptions.inDither=true;//optional - bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional - input = this.getContentResolver().openInputStream(uri); - Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions); - input.close(); - return bitmap; - } + options.inSampleSize = Compose.calculateInSampleSize(options, reqWidth, + reqHeight); + options.inPurgeable = true; + options.inInputShareable = true; + options.inJustDecodeBounds = false; + options.inPreferredConfig = Bitmap.Config.ARGB_8888; - private static int getPowerOfTwoForSampleRatio(double ratio){ - int k = Integer.highestOneBit((int)Math.floor(ratio)); - if(k==0) return 1; - else return k; - } + Bitmap b = BitmapFactory.decodeByteArray(byteArr, 0, count, options); + + if (!Compose.isAndroidN()) { + ExifInterface exif = new ExifInterface(IOUtils.getPath(uri, context)); + int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); + input.close(); + + b = ImageUtils.cropSquare(b); + return Compose.rotateBitmap(b, orientation); + } else { + input.close(); + b = ImageUtils.cropSquare(b); + return b; + } + + } catch (Exception e) { + e.printStackTrace(); + + return null; + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/klinker/android/twitter/activities/compose/Compose.java b/app/src/main/java/com/klinker/android/twitter/activities/compose/Compose.java index 1ccc806..1e18bac 100644 --- a/app/src/main/java/com/klinker/android/twitter/activities/compose/Compose.java +++ b/app/src/main/java/com/klinker/android/twitter/activities/compose/Compose.java @@ -37,6 +37,7 @@ import android.media.ThumbnailUtils; import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -89,6 +90,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; +import java.net.URI; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -769,6 +771,10 @@ private void startUcrop(Uri sourceUri) { } } + public static boolean isAndroidN() { + return Build.VERSION.SDK_INT > Build.VERSION_CODES.M || Build.VERSION.CODENAME.equals("N"); + } + public static final int SELECT_PHOTO = 100; public static final int CAPTURE_IMAGE = 101; public static final int SELECT_GIF = 102; @@ -960,29 +966,25 @@ protected Boolean doInBackground(String... args) { try { Twitter twitter = Utils.getTwitter(getApplicationContext(), settings); + String sendTo = contactEntry.getText().toString().replace("@", "").replace(" ", ""); + User user = twitter.showUser(sendTo); + MessageData data = new MessageData(user.getId(), status); + 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(); + File f; - status += " " + url; + if (attachmentType == null) { + // image file + f = ImageUtils.scaleToSend(context, Uri.parse(attachedUri[0])); + } else { + f = new File(URI.create(attachedUri[0])); } + + UploadedMedia media = twitter.uploadMedia(f); + data.setMediaId(media.getMediaId()); } catch (Exception e) { + e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { @@ -993,11 +995,8 @@ public void run() { } - String sendTo = contactEntry.getText().toString().replace("@", "").replace(" ", ""); - - twitter.sendDirectMessage(sendTo, status); - - return true; + DirectMessageEvent event = twitter.createMessage(data); + return event != null; } catch (TwitterException e) { e.printStackTrace(); @@ -1468,7 +1467,7 @@ public Bitmap decodeSampledBitmapFromResourceMemOpt( } } - public int calculateInSampleSize(BitmapFactory.Options opt, int reqWidth, int reqHeight) { + public static 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; diff --git a/app/src/main/java/com/klinker/android/twitter/activities/compose/ComposeDMActivity.java b/app/src/main/java/com/klinker/android/twitter/activities/compose/ComposeDMActivity.java index 08b4380..ff85034 100644 --- a/app/src/main/java/com/klinker/android/twitter/activities/compose/ComposeDMActivity.java +++ b/app/src/main/java/com/klinker/android/twitter/activities/compose/ComposeDMActivity.java @@ -22,9 +22,11 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.net.Uri; +import android.os.Build; import android.os.Environment; import android.os.Handler; import android.provider.MediaStore; +import android.support.v4.content.FileProvider; import android.text.Editable; import android.text.TextWatcher; import android.view.View; @@ -35,7 +37,9 @@ import android.widget.ListPopupWindow; import android.widget.Toast; +import com.klinker.android.twitter.BuildConfig; import com.klinker.android.twitter.R; +import com.klinker.android.twitter.activities.GiphySearch; import com.klinker.android.twitter.adapters.AutoCompletePeopleAdapter; import com.klinker.android.twitter.data.sq_lite.FollowersDataSource; import com.klinker.android.twitter.utils.UserAutoCompleteHelper; @@ -79,37 +83,7 @@ public void setUpLayout() { attachButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (imagesAttached > 0 && !sharedPrefs.getBoolean("know_twitpic_for_mult_attach", false)) { - new AlertDialog.Builder(context) - .setTitle(context.getResources().getString(R.string.twitpic_disclaimer)) - .setMessage(getResources().getString(R.string.twitpic_disclaimer_multi_summary)) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - attachImage(); - dialogInterface.dismiss(); - } - }) - .setNeutralButton(R.string.dont_show_again, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - sharedPrefs.edit().putBoolean("know_twitpic_for_mult_attach", true).commit(); - attachImage(); - dialogInterface.dismiss(); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - dialogInterface.dismiss(); - } - }) - .create() - .show(); - } else { - attachImage(); - } - + attachImage(); } }); @@ -231,7 +205,7 @@ private void sendStatus(String status) { public void attachImage() { AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setItems(R.array.attach_options, new DialogInterface.OnClickListener() { + builder.setItems(R.array.attach_dm_options, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { if(item == 0) { // take picture Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); @@ -246,35 +220,50 @@ public void onClick(DialogInterface dialog, int item) { } } - captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); - startActivityForResult(captureIntent, CAPTURE_IMAGE); - } else { // attach picture - if (attachedUri == null || attachedUri.equals("")) { - Intent photoPickerIntent = new Intent(); - photoPickerIntent.setType("image/*"); - photoPickerIntent.setAction(Intent.ACTION_GET_CONTENT); - try { - startActivityForResult(Intent.createChooser(photoPickerIntent, - "Select Picture"), SELECT_PHOTO); - } catch (Throwable t) { - // no app to preform this..? hmm, tell them that I guess - Toast.makeText(context, "No app available to select pictures!", Toast.LENGTH_SHORT).show(); + captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + + try { + Uri photoURI = FileProvider.getUriForFile(context, + BuildConfig.APPLICATION_ID + ".provider", f); + + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); + startActivityForResult(captureIntent, CAPTURE_IMAGE); + } catch (Exception e) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Toast.makeText(ComposeDMActivity.this, "Have you given Talon the storage permission?", Toast.LENGTH_LONG).show(); } - } else { - attachedUri = ""; - attachImage.setImageDrawable(null); - attachImage.setVisibility(View.GONE); - Intent photoPickerIntent = new Intent(); + } + + } else if (item == 1) { // attach picture + try { + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PHOTO); + } catch (Exception e) { + Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); - photoPickerIntent.setAction(Intent.ACTION_GET_CONTENT); - try { - startActivityForResult(Intent.createChooser(photoPickerIntent, - "Select Picture"), SELECT_PHOTO); - } catch (Throwable t) { - // no app to preform this..? hmm, tell them that I guess - Toast.makeText(context, "No app available to select pictures!", Toast.LENGTH_SHORT).show(); - } + startActivityForResult(Intent.createChooser(photoPickerIntent, + "Select Picture"), SELECT_PHOTO); + } + } else if (item == 2) { + Toast.makeText(ComposeDMActivity.this, "GIFs must be less than 5 MB", Toast.LENGTH_SHORT).show(); + + try { + Intent gifIntent = new Intent(); + gifIntent.setType("image/gif"); + gifIntent.setAction(Intent.ACTION_GET_CONTENT); + startActivityForResult(gifIntent, SELECT_GIF); + } catch (Exception e) { + Intent gifIntent = new Intent(); + gifIntent.setType("image/gif"); + gifIntent.setAction(Intent.ACTION_PICK); + startActivityForResult(gifIntent, SELECT_GIF); } + } else if (item == 3) { + Intent gif = new Intent(context, GiphySearch.class); + startActivityForResult(gif, FIND_GIF); } } }); diff --git a/app/src/main/java/com/klinker/android/twitter/adapters/DMCursorAdapter.java b/app/src/main/java/com/klinker/android/twitter/adapters/DMCursorAdapter.java index 7a64685..1e7df38 100644 --- a/app/src/main/java/com/klinker/android/twitter/adapters/DMCursorAdapter.java +++ b/app/src/main/java/com/klinker/android/twitter/adapters/DMCursorAdapter.java @@ -22,9 +22,6 @@ import com.klinker.android.twitter.data.sq_lite.HomeSQLiteHelper; -/** - * Created by luke on 1/20/14. - */ public class DMCursorAdapter extends TimeLineCursorAdapter { public DMCursorAdapter(Context context, Cursor cursor, boolean isDM) { super(context, cursor, isDM); diff --git a/app/src/main/java/com/klinker/android/twitter/data/sq_lite/DMDataSource.java b/app/src/main/java/com/klinker/android/twitter/data/sq_lite/DMDataSource.java index 9505a55..53b4492 100644 --- a/app/src/main/java/com/klinker/android/twitter/data/sq_lite/DMDataSource.java +++ b/app/src/main/java/com/klinker/android/twitter/data/sq_lite/DMDataSource.java @@ -23,11 +23,14 @@ import android.database.sqlite.SQLiteDatabase; import android.util.Log; +import com.klinker.android.twitter.settings.AppSettings; import com.klinker.android.twitter.utils.TweetLinkUtils; import twitter4j.DirectMessage; +import twitter4j.DirectMessageEvent; import twitter4j.MediaEntity; import twitter4j.URLEntity; +import twitter4j.User; public class DMDataSource { @@ -129,6 +132,51 @@ public synchronized void createDirectMessage(DirectMessage status, int account) } + public synchronized void createSentDirectMessage(DirectMessageEvent status, User recipient, AppSettings settings, int account) { + ContentValues values = new ContentValues(); + long time = status.getCreatedTimestamp().getTime(); + + String[] html = TweetLinkUtils.getLinksInStatus(status); + String text = html[0]; + String media = html[1]; + String url = html[2]; + String hashtags = html[3]; + String users = html[4]; + + values.put(DMSQLiteHelper.COLUMN_ACCOUNT, account); + values.put(DMSQLiteHelper.COLUMN_TEXT, text); + values.put(DMSQLiteHelper.COLUMN_TWEET_ID, status.getId()); + values.put(DMSQLiteHelper.COLUMN_NAME, settings.myName); + values.put(DMSQLiteHelper.COLUMN_PRO_PIC, settings.myProfilePicUrl); + values.put(DMSQLiteHelper.COLUMN_SCREEN_NAME, settings.myScreenName); + values.put(DMSQLiteHelper.COLUMN_TIME, time); + values.put(DMSQLiteHelper.COLUMN_RETWEETER, recipient.getScreenName()); + values.put(DMSQLiteHelper.COLUMN_EXTRA_ONE, recipient.getOriginalProfileImageURL()); + values.put(DMSQLiteHelper.COLUMN_EXTRA_TWO, recipient.getName()); + values.put(HomeSQLiteHelper.COLUMN_PIC_URL, media); + values.put(DMSQLiteHelper.COLUMN_EXTRA_THREE, TweetLinkUtils.getGIFUrl(status.getMediaEntities(), url)); + + MediaEntity[] entities = status.getMediaEntities(); + + if (entities.length > 0) { + values.put(DMSQLiteHelper.COLUMN_PIC_URL, entities[0].getMediaURL()); + } + + URLEntity[] urls = status.getUrlEntities(); + for (URLEntity u : urls) { + Log.v("inserting_dm", "url here: " + u.getExpandedURL()); + values.put(DMSQLiteHelper.COLUMN_URL, u.getExpandedURL()); + } + + try { + database.insert(DMSQLiteHelper.TABLE_DM, null, values); + } catch (Exception e) { + open(); + database.insert(DMSQLiteHelper.TABLE_DM, null, values); + } + + } + public synchronized void deleteTweet(long tweetId) { long id = tweetId; diff --git a/app/src/main/java/com/klinker/android/twitter/utils/ImageUtils.java b/app/src/main/java/com/klinker/android/twitter/utils/ImageUtils.java index 37398a8..ad5f05c 100644 --- a/app/src/main/java/com/klinker/android/twitter/utils/ImageUtils.java +++ b/app/src/main/java/com/klinker/android/twitter/utils/ImageUtils.java @@ -29,6 +29,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.util.Log; @@ -42,6 +43,8 @@ import com.klinker.android.twitter.R; import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; @@ -56,6 +59,8 @@ public class ImageUtils { + private static final long MAX_PICTURE_UPLOAD_SIZE = 1024 * 1024 * 3; + public static Bitmap getCircle(Bitmap currentImage, Context context) { int scale = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 96, context.getResources().getDisplayMetrics()); @@ -1063,4 +1068,122 @@ public static Bitmap combineBitmaps(Context context, Bitmap[] bitmaps) { return bitmaps[0]; } + + /** + * Scales a bitmap file to a lower resolution so that it can be sent over MMS. Most carriers + * have a 1 MB limit, so we'll scale to under that. This method will create a new file in the + * application memory. + */ + public static File scaleToSend(Context context, Uri uri) throws IOException { + InputStream input = context.getContentResolver().openInputStream(uri); + + byte[] byteArr = new byte[0]; + byte[] buffer = new byte[1024]; + int arraySize = 0; + int len; + + try { + // convert the Uri to a byte array that we can manipulate + while ((len = input.read(buffer)) > -1) { + if (len != 0) { + if (arraySize + len > byteArr.length) { + byte[] newbuf = new byte[(arraySize + len) * 2]; + System.arraycopy(byteArr, 0, newbuf, 0, arraySize); + byteArr = newbuf; + } + + System.arraycopy(buffer, 0, byteArr, arraySize, len); + arraySize += len; + } + } + + try { + input.close(); + } catch(Exception e) { } + + // with inJustDecodeBounds, we are telling the system just to get the resolution + // of the image and not to decode anything else. This resolution + // is used to calculate the in sample size + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(byteArr, 0, arraySize, options); + int srcWidth = options.outWidth; + int srcHeight = options.outHeight; + + String fileName = ((int) (Math.random() * Integer.MAX_VALUE)) + ".jpg"; + + // start generating bitmaps and checking the size against the max size + Bitmap scaled = generateBitmap(byteArr, arraySize, srcWidth, srcHeight, 2000); + File file = createFileFromBitmap(context, fileName, scaled); + + int maxResolution = 1500; + while (maxResolution > 0 && file.length() > MAX_PICTURE_UPLOAD_SIZE) { + scaled.recycle(); + + scaled = generateBitmap(byteArr, arraySize, srcWidth, srcHeight, maxResolution); + file = createFileFromBitmap(context, fileName, scaled); + maxResolution -= 250; + } + + return file; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private static Bitmap generateBitmap(byte[] byteArr, int arraySize, int srcWidth, int srcHeight, int maxSize) { + final BitmapFactory.Options options = new BitmapFactory.Options(); + + // in sample size reduces the size of the image by this factor of 2 + options.inSampleSize = calculateInSampleSize(srcHeight, srcWidth, maxSize); + + // these options set up the image coloring + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + options.inDither = true; + + // these options set it up with the actual dimensions that you are looking for + options.inDensity = srcWidth; + options.inTargetDensity = maxSize * options.inSampleSize; + + // now we actually decode the image to these dimensions + return BitmapFactory.decodeByteArray(byteArr, 0, arraySize, options); + } + + private static int calculateInSampleSize(int currentHeight, int currentWidth, int maxSize) { + int scale = 1; + + if (currentHeight > maxSize || currentWidth > maxSize) { + scale = (int) Math.pow(2, (int) Math.ceil(Math.log(maxSize / + (double) Math.max(currentHeight, currentWidth)) / Math.log(0.5))); + } + + return scale; + } + + private static File createFileFromBitmap(Context context, String name, Bitmap bitmap) { + FileOutputStream out = null; + File file = new File(context.getFilesDir(), name); + + try { + if (!file.exists()) { + file.createNewFile(); + } + + out = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); + } catch (IOException e) { + Log.e("Scale to Send", "failed to write output stream", e); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException e) { + Log.e("Scale to Send", "failed to close output stream", e); + } + } + + return file; + } } \ No newline at end of file diff --git a/app/src/main/java/com/klinker/android/twitter/utils/TweetLinkUtils.java b/app/src/main/java/com/klinker/android/twitter/utils/TweetLinkUtils.java index 2668d26..6359e72 100644 --- a/app/src/main/java/com/klinker/android/twitter/utils/TweetLinkUtils.java +++ b/app/src/main/java/com/klinker/android/twitter/utils/TweetLinkUtils.java @@ -16,18 +16,37 @@ package com.klinker.android.twitter.utils; -import android.util.Log; - import com.klinker.android.twitter.settings.AppSettings; import java.util.ArrayList; -import twitter4j.*; +import twitter4j.DirectMessage; +import twitter4j.DirectMessageEvent; +import twitter4j.HashtagEntity; +import twitter4j.MediaEntity; +import twitter4j.Status; +import twitter4j.URLEntity; +import twitter4j.UserMentionEntity; public class TweetLinkUtils { public static String[] getLinksInStatus(Status status) { - UserMentionEntity[] users = status.getUserMentionEntities(); + return getLinksInStatus(status.getText(), status.getUserMentionEntities(), + status.getHashtagEntities(), status.getURLEntities(), status.getMediaEntities()); + } + + public static String[] getLinksInStatus(DirectMessage status) { + return getLinksInStatus(status.getText(), status.getUserMentionEntities(), + status.getHashtagEntities(), status.getURLEntities(), status.getMediaEntities()); + } + + public static String[] getLinksInStatus(DirectMessageEvent event) { + return getLinksInStatus(event.getText(), event.getUserMentionEntities(), event.getHashtagEntities(), + event.getUrlEntities(), event.getMediaEntities()); + } + + private static String[] getLinksInStatus(String tweetTexts, UserMentionEntity[] users, HashtagEntity[] hashtags, + URLEntity[] urls, MediaEntity[] medias) { String mUsers = ""; for(UserMentionEntity name : users) { @@ -37,7 +56,6 @@ public static String[] getLinksInStatus(Status status) { } } - HashtagEntity[] hashtags = status.getHashtagEntities(); String mHashtags = ""; for (HashtagEntity hashtagEntity : hashtags) { @@ -47,7 +65,6 @@ public static String[] getLinksInStatus(Status status) { } } - URLEntity[] urls = status.getURLEntities(); String expandedUrls = ""; String compressedUrls = ""; @@ -59,7 +76,6 @@ public static String[] getLinksInStatus(Status status) { } } - MediaEntity[] medias = status.getMediaEntities(); String mediaExp = ""; String mediaComp = ""; String mediaDisplay = ""; @@ -109,8 +125,6 @@ public static String[] getLinksInStatus(Status status) { sMediaDisplay = new String[0]; } - String tweetTexts = status.getText(); - String imageUrl = ""; String otherUrl = ""; @@ -139,8 +153,8 @@ public static String[] getLinksInStatus(Status status) { if (str.contains("instag") && !str.contains("blog.insta")) { imageUrl = exp + "media/?size=l"; otherUrl += exp + " "; - } else if (exp.toLowerCase().contains("youtub") && !(str.contains("channel") || str.contains("user"))) { - // first get the youtube video code + } else if (exp.toLowerCase().contains("youtub") && !(str.contains("channel") || str.contains("user") || str.contains("playlist"))) { + // first get the youtube surfaceView code int start = exp.indexOf("v=") + 2; int end = exp.length(); if (exp.substring(start).contains("&")) { @@ -155,7 +169,7 @@ public static String[] getLinksInStatus(Status status) { } otherUrl += exp + " "; } else if (str.contains("youtu.be")) { - // first get the youtube video code + // first get the youtube surfaceView code int start = exp.indexOf(".be/") + 4; int end = exp.length(); if (exp.substring(start).contains("&")) { @@ -173,12 +187,12 @@ public static String[] getLinksInStatus(Status status) { int start = exp.indexOf(".com/") + 5; imageUrl = "http://twitpic.com/show/full/" + exp.substring(start).replace("/", ""); otherUrl += exp + " "; - } else if (str.contains("i.imgur") && !str.contains("/a/")) { + } else if (str.contains("i.imgur") && !str.contains("/a/") && !str.contains(".gifv")) { int start = exp.indexOf(".com/") + 5; imageUrl = "http://i.imgur.com/" + exp.replace("http://i.imgur.com/", "").replace(".jpg", "") + "l.jpg"; imageUrl = imageUrl.replace("gallery/", ""); otherUrl += exp + " "; - } else if (str.contains("imgur") && !str.contains("/a/")) { + } else if (str.contains("imgur") && !str.contains("/a/") && !str.contains(".gifv")) { int start = exp.indexOf(".com/") + 6; imageUrl = "http://i.imgur.com/" + exp.replace("http://imgur.com/", "").replace(".jpg", "") + "l.jpg"; imageUrl = imageUrl.replace("gallery/", "").replace("a/", ""); @@ -222,11 +236,13 @@ public static String[] getLinksInStatus(Status status) { tweetTexts = tweetTexts.replace(comp, replacement); } catch (Exception e) { + e.printStackTrace(); tweetTexts = tweetTexts.replace(comp, sMediaDisplay[i].replace("http://", "").replace("https://", "").replace("www.", "")); } - imageUrl = status.getMediaEntities()[0].getMediaURL(); - for (MediaEntity m : status.getMediaEntities()) { + imageUrl = medias[0].getMediaURL(); + + for (MediaEntity m : medias) { if (m.getType().equals("photo")) { if (!imageUrl.contains(m.getMediaURL())) { imageUrl += " " + m.getMediaURL(); @@ -241,170 +257,6 @@ public static String[] getLinksInStatus(Status status) { return new String[] { tweetTexts, imageUrl, otherUrl, mHashtags, mUsers }; } - public static String[] getLinksInStatus(DirectMessage status) { - UserMentionEntity[] users = status.getUserMentionEntities(); - String mUsers = ""; - - for(UserMentionEntity name : users) { - String n = name.getScreenName(); - if (n.length() > 1) { - mUsers += n + " "; - } - } - - HashtagEntity[] hashtags = status.getHashtagEntities(); - String mHashtags = ""; - - for (HashtagEntity hashtagEntity : hashtags) { - String text = hashtagEntity.getText(); - if (text.length() > 1) { - mHashtags += text + " "; - } - } - - URLEntity[] urls = status.getURLEntities(); - String expandedUrls = ""; - String compressedUrls = ""; - - for (URLEntity entity : urls) { - String url = entity.getExpandedURL(); - if (url.length() > 1) { - expandedUrls += url + " "; - compressedUrls += entity.getURL() + " "; - } - } - - MediaEntity[] medias = status.getMediaEntities(); - String mediaExp = ""; - String mediaComp = ""; - String mediaDisplay = ""; - - for (MediaEntity e : medias) { - String url = e.getURL(); - if (url.length() > 1) { - mediaComp += url + " "; - mediaExp += e.getExpandedURL() + " "; - mediaDisplay += e.getDisplayURL() + " "; - } - } - - String[] sExpandedUrls; - String[] sCompressedUrls; - String[] sMediaExp; - String[] sMediaComp; - String[] sMediaDisply; - - try { - sCompressedUrls = compressedUrls.split(" "); - } catch (Exception e) { - sCompressedUrls = new String[0]; - } - - try { - sExpandedUrls = expandedUrls.split(" "); - } catch (Exception e) { - sExpandedUrls = new String[0]; - } - - try { - sMediaComp = mediaComp.split(" "); - } catch (Exception e) { - sMediaComp = new String[0]; - } - - try { - sMediaExp = mediaExp.split(" "); - } catch (Exception e) { - sMediaExp = new String[0]; - } - - try { - sMediaDisply = mediaDisplay.split(" "); - } catch (Exception e) { - sMediaDisply = new String[0]; - } - - String tweetTexts = status.getText(); - - String imageUrl = ""; - String otherUrl = ""; - - for (int i = 0; i < sCompressedUrls.length; i++) { - String comp = sCompressedUrls[i]; - String exp = sExpandedUrls[i]; - - if (comp.length() > 1 && exp.length() > 1) { - String str = exp.toLowerCase(); - - tweetTexts = tweetTexts.replace(comp, exp.replace("http://", "").replace("https://", "").replace("www.", "")); - - if(str.contains("instag") && !str.contains("blog.instag")) { - imageUrl = exp + "media/?size=m"; - otherUrl += exp + " "; - } else if (str.contains("youtub") && !(str.contains("channel") || str.contains("user"))) { // normal youtube link - // first get the youtube video code - int start = exp.indexOf("v=") + 2; - int end = exp.length(); - if (exp.substring(start).contains("&")) { - end = exp.indexOf("&"); - } else if (exp.substring(start).contains("?")) { - end = exp.indexOf("?"); - } - imageUrl = "http://img.youtube.com/vi/" + exp.substring(start, end) + "/hqdefault.jpg"; - otherUrl += exp + " "; - } else if (str.contains("youtu.be")) { // shortened youtube link - // first get the youtube video code - int start = exp.indexOf(".be/") + 4; - int end = exp.length(); - if (exp.substring(start).contains("&")) { - end = exp.indexOf("&"); - } else if (exp.substring(start).contains("?")) { - end = exp.indexOf("?"); - } - imageUrl = "http://img.youtube.com/vi/" + exp.substring(start, end) + "/hqdefault.jpg"; - otherUrl += exp + " "; - } else if (str.contains("twitpic")) { - int start = exp.indexOf(".com/") + 5; - imageUrl = "http://twitpic.com/show/full/" + exp.substring(start).replace("/", ""); - otherUrl += exp + " "; - } else if (str.contains("imgur") && !str.contains("/a/")) { - int start = exp.indexOf(".com/") + 6; - imageUrl = "http://i.imgur.com/" + exp.substring(start) + "l.jpg" ; - imageUrl = imageUrl.replace("gallery/", "").replace("a/", ""); - otherUrl += exp + " "; - } else if (str.contains("pbs.twimg.com")) { - imageUrl = exp; - otherUrl += exp + " "; - } else if (str.contains("ow.ly/i/")) { - Log.v("talon_owly", exp); - imageUrl = "http://static.ow.ly/photos/original/" + exp.substring(exp.lastIndexOf("/")).replaceAll("/", "") + ".jpg"; - otherUrl += exp + " "; - } else if (str.contains(".jpg") || str.contains(".png")) { - imageUrl = exp; - otherUrl += exp + " "; - } else if (str.contains("img.ly")) { - imageUrl = exp.replace("https", "http").replace("http://img.ly/", "http://img.ly/show/large/"); - otherUrl += exp + " "; - } else { - otherUrl += exp + " "; - } - } - } - - for (int i = 0; i < sMediaComp.length; i++) { - String comp = sMediaComp[i]; - String exp = sMediaExp[i]; - - if (comp.length() > 1 && exp.length() > 1) { - tweetTexts = tweetTexts.replace(comp, sMediaDisply[i]); - imageUrl = status.getMediaEntities()[0].getMediaURL(); - otherUrl += sMediaDisply[i]; - } - } - - return new String[] { tweetTexts, imageUrl, otherUrl, mHashtags, mUsers }; - } - public static ArrayList getAllExternalPictures(Status status) { URLEntity[] urls = status.getURLEntities(); String expandedUrls = ""; @@ -470,8 +322,8 @@ public static ArrayList getAllExternalPictures(Status status) { if(str.contains("instag") && !str.contains("blog.insta")) { images.add(exp + "media/?size=m"); - } else if (exp.toLowerCase().contains("youtub") && !(str.contains("channel") || str.contains("user"))) { - // first get the youtube video code + } else if (exp.toLowerCase().contains("youtub") && !(str.contains("channel") || str.contains("user") || str.contains("playlist"))) { + // first get the youtube surfaceView code int start = exp.indexOf("v=") + 2; int end = exp.length(); if (exp.substring(start).contains("&")) { @@ -485,7 +337,7 @@ public static ArrayList getAllExternalPictures(Status status) { images.add("http://img.youtube.com/vi/" + exp.substring(start, exp.length() - 1) + "/hqdefault.jpg"); } } else if (str.contains("youtu.be")) { - // first get the youtube video code + // first get the youtube surfaceView code int start = exp.indexOf(".be/") + 4; int end = exp.length(); if (exp.substring(start).contains("&")) { @@ -541,35 +393,64 @@ public static String removeColorHtml(String text, AppSettings settings) { return text; } - public static String getGIFUrl(Status s, String otherUrls) { + public static String getGIFUrl(Status status, String otherUrls) { + return getGIFUrl(status.getMediaEntities(), otherUrls); + } + + public static String getGIFUrl(MediaEntity[] entities, String otherUrls) { + + for (MediaEntity e : entities) { + if (e.getType().contains("gif")) { + if (e.getVideoVariants().length > 0) { + String url = ""; + MediaEntity.Variant variants[] = e.getVideoVariants(); - // this will be used after twitter begins to support them - for (MediaEntity e : s.getMediaEntities()) { + if (variants.length == 0) { + return url; + } + + for (int i = variants.length - 1; i >= 0; i--) { + MediaEntity.Variant v = variants[i]; + if (v.getUrl().contains(".mp4") || v.getUrl().contains(".m3u8")) { + url = v.getUrl(); + } + } - if (e.getType().equals("animated_gif")) { - return e.getMediaURL().replace("tweet_video_thumb", "tweet_video").replace(".png", ".mp4").replace(".jpg",".mp4").replace(".jpeg", ".mp4"); - } else if (e.getType().equals("video")) { + return url; + } + return e.getMediaURL().replace("tweet_video_thumb", "tweet_video").replace(".png", ".mp4").replace(".jpg", ".mp4").replace(".jpeg", ".mp4"); + } else if (e.getType().equals("surfaceView") || e.getType().equals("video")) { if (e.getVideoVariants().length > 0) { String url = ""; - for (MediaEntity.Variant v : e.getVideoVariants()) { + MediaEntity.Variant variants[] = e.getVideoVariants(); + + if (variants.length == 0) { + return url; + } + + for (int i = variants.length - 1; i >= 0; i--) { + MediaEntity.Variant v = variants[i]; if (v.getUrl().contains(".mp4")) { url = v.getUrl(); } } - Log.v("talon_video_link", url); + if (url.isEmpty()) { + for (int i = variants.length - 1; i >= 0; i--) { + MediaEntity.Variant v = variants[i]; + if (v.getUrl().contains(".m3u8")) { + url = v.getUrl(); + } + } + } + return url; } } } - // this is how the urls are currently stored - String gifUrl = "twitter.com/" + s.getUser().getScreenName() + "/status/" + s.getId() + "/photo/1"; - if (otherUrls.contains(gifUrl)) { - return gifUrl; - } - // otherwise, lets just go with a blank string return ""; } + } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index a3435f3..95df32c 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -143,7 +143,13 @@ @string/take_picture @string/from_file @string/attach_gif - + + + + @string/take_picture + @string/from_file + @string/attach_gif + Giphy