moved package, image download fix

This commit is contained in:
nuclearfog 2022-01-14 11:05:49 +01:00
parent 996ce859fd
commit 803683691e
No known key found for this signature in database
GPG Key ID: AA0271FBE406DB98
19 changed files with 129 additions and 59 deletions

View File

@ -24,7 +24,7 @@ import androidx.appcompat.app.AppCompatActivity;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.ListUpdater;
import org.nuclearfog.twidda.backend.holder.ListHolder;
import org.nuclearfog.twidda.backend.api.holder.ListHolder;
import org.nuclearfog.twidda.model.UserList;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;

View File

@ -43,6 +43,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;
/**
* This activity is a superclass to all activities who need permission to take actions
@ -63,7 +64,6 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio
private static final String MIME_ALL_READ = "*/*";
private static final String MIME_IMAGE_READ = "image/*";
private static final String MIME_VIDEO_READ = "video/*";
private static final String MIME_IMAGE_WRITE = "image/jpeg";
/**
* mime types for videos and images
@ -190,21 +190,26 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio
imageTask.execute(src, dest);
} else {
// use scoped storage
String ext = selectedImage.getLastPathSegment();
ext = ext.substring(ext.indexOf('.') + 1).toLowerCase(Locale.ENGLISH);
String mime = "image/" + ext;
ContentValues values = new ContentValues();
values.put(DISPLAY_NAME, imageName);
values.put(DATE_TAKEN, System.currentTimeMillis());
values.put(RELATIVE_PATH, DIRECTORY_PICTURES);
values.put(MIME_TYPE, MIME_IMAGE_WRITE);
values.put(MIME_TYPE, mime);
Uri imageUri = getContentResolver().insert(EXTERNAL_CONTENT_URI, values);
if (imageUri != null) {
InputStream source = getContentResolver().openInputStream(selectedImage);
OutputStream dest = getContentResolver().openOutputStream(imageUri);
imageTask = new ImageSaver(this);
imageTask.execute(selectedImage, dest);
imageTask.execute(source, dest);
}
}
}
} catch (FileNotFoundException err) {
} catch (Exception err) {
err.printStackTrace();
onError();
}
}

View File

@ -54,12 +54,12 @@ public class MediaViewer extends MediaActivity implements OnImageClickListener,
OnPreparedListener, OnInfoListener, OnErrorListener, OnClickListener, OnTouchListener {
/**
* Key for online media files
* Key for a string array with http links
*/
public static final String KEY_MEDIA_LINK = "media_link";
/**
* key for local media files
* key for an Uri array with local links
*/
public static final String KEY_MEDIA_URI = "media_uri";
@ -73,28 +73,29 @@ public class MediaViewer extends MediaActivity implements OnImageClickListener,
* cache folder name
*/
public static final String CACHE_FOLDER = "imagecache";
/**
* setup media viewer for images from twitter
* value for {@link #KEY_MEDIA_TYPE} to show images
*/
public static final int MEDIAVIEWER_IMAGE = 0x997BCDCE;
/**
* setup media viewer for videos
* value for {@link #KEY_MEDIA_TYPE} to show a video
*/
public static final int MEDIAVIEWER_VIDEO = 0x500C9A42;
/**
* setup media viewer for GIF animation
* value for {@link #KEY_MEDIA_TYPE} to show an animated image
*/
public static final int MEDIAVIEWER_ANGIF = 0x6500EDB0;
/**
* refresh time for video progress update
* refresh time for video progress updatein milliseconds
*/
private static final int PROGRESS_UPDATE = 1000;
/**
* speed factor for fast forward or backward
* speed factor for fast forward or fast backward
*/
private static final int SPEED_FACTOR = 6;
@ -505,8 +506,10 @@ public class MediaViewer extends MediaActivity implements OnImageClickListener,
private void clearCache() {
File cacheFolder = new File(getExternalCacheDir(), CACHE_FOLDER);
File[] files = cacheFolder.listFiles();
for (File file : files) {
file.delete();
if (files != null && files.length > 0) {
for (File file : files) {
file.delete();
}
}
}
}

View File

@ -23,7 +23,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.MessageUpdater;
import org.nuclearfog.twidda.backend.holder.DirectmessageHolder;
import org.nuclearfog.twidda.backend.api.holder.DirectmessageHolder;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.dialog.ConfirmDialog;

View File

@ -37,7 +37,7 @@ import com.squareup.picasso.Picasso;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.UserUpdater;
import org.nuclearfog.twidda.backend.holder.ProfileHolder;
import org.nuclearfog.twidda.backend.api.holder.ProfileHolder;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;

View File

@ -27,7 +27,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.TweetUpdater;
import org.nuclearfog.twidda.backend.holder.TweetHolder;
import org.nuclearfog.twidda.backend.api.holder.TweetHolder;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.utils.StringTools;

View File

@ -18,7 +18,8 @@ import java.io.InputStream;
import java.lang.ref.WeakReference;
/**
* background async to download images to a cache folder
* This AsyncTask class downloads images to a local cache folder
* and creates Uri of the images.
*
* @author nuclearfog
* @see MediaViewer
@ -40,6 +41,7 @@ public class ImageLoader extends AsyncTask<Uri, Uri, Boolean> {
super();
callback = new WeakReference<>(activity);
twitter = Twitter.get(activity);
// create cache folder if not exists
cache = new File(activity.getExternalCacheDir(), MediaViewer.CACHE_FOLDER);
cache.mkdirs();
}
@ -48,10 +50,12 @@ public class ImageLoader extends AsyncTask<Uri, Uri, Boolean> {
@Override
protected Boolean doInBackground(Uri[] links) {
try {
// create cache folder if not exists
// download imaged to a local cache folder
for (Uri link : links) {
File file = new File(cache, StringTools.getRandomString());
// create temp file for the image
String end = link.getLastPathSegment();
String ext = end.substring(end.indexOf('.'));
File file = new File(cache, StringTools.getRandomString() + ext);
file.createNewFile();
FileOutputStream os = new FileOutputStream(file);
InputStream input = twitter.downloadImage(link.toString());

View File

@ -9,7 +9,7 @@ import java.io.OutputStream;
import java.lang.ref.WeakReference;
/**
* background task to save an image to the external storage
* This AsyncTask class moves a cached image to the destiny folder
*
* @author nuclearfog
* @see MediaActivity

View File

@ -5,7 +5,7 @@ import android.os.AsyncTask;
import org.nuclearfog.twidda.activities.ListEditor;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.holder.ListHolder;
import org.nuclearfog.twidda.backend.api.holder.ListHolder;
import org.nuclearfog.twidda.model.UserList;
import java.lang.ref.WeakReference;

View File

@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
import org.nuclearfog.twidda.activities.MessageEditor;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.holder.DirectmessageHolder;
import org.nuclearfog.twidda.backend.api.holder.DirectmessageHolder;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import java.lang.ref.WeakReference;
@ -47,8 +47,7 @@ public class MessageUpdater extends AsyncTask<Void, Void, Boolean> {
// upload media if any
long mediaId = -1;
if (message.getMediaStream() != null) {
mediaId = twitter.uploadMedia(message.getMediaStream(), message.getMimeType());
message.getMediaStream().close();
mediaId = twitter.uploadMedia(message.getMediaStream());
}
// upload message and media ID if defined
if (!isCancelled()) {
@ -59,6 +58,8 @@ public class MessageUpdater extends AsyncTask<Void, Void, Boolean> {
this.twException = twException;
} catch (Exception err) {
err.printStackTrace();
} finally {
message.getMediaStream().close();
}
return false;
}

View File

@ -5,7 +5,8 @@ import android.os.AsyncTask;
import org.nuclearfog.twidda.activities.TweetEditor;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.holder.TweetHolder;
import org.nuclearfog.twidda.backend.api.holder.MediaStream;
import org.nuclearfog.twidda.backend.api.holder.TweetHolder;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import java.io.InputStream;
@ -48,12 +49,12 @@ public class TweetUpdater extends AsyncTask<Void, Void, Boolean> {
mediaIds = new long[mediaStreams.length];
for (int pos = 0; pos < mediaStreams.length; pos++) {
// upload media file and save media ID
mediaIds[pos] = twitter.uploadMedia(mediaStreams[pos], mimeTypes[pos]);
MediaStream mediaStream = new MediaStream(mediaStreams[pos], mimeTypes[pos]);
mediaIds[pos] = twitter.uploadMedia(mediaStream);
// close stream after upload
mediaStreams[pos].close();
}
}
// upload tweet
if (!isCancelled()) {
double[] coordinates = null;

View File

@ -7,7 +7,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.activities.ProfileEditor;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.holder.ProfileHolder;
import org.nuclearfog.twidda.backend.api.holder.ProfileHolder;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.database.AppDatabase;

View File

@ -7,6 +7,7 @@ import android.os.Build;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.nuclearfog.twidda.backend.api.holder.MediaStream;
import org.nuclearfog.twidda.backend.lists.Directmessages;
import org.nuclearfog.twidda.backend.lists.UserLists;
import org.nuclearfog.twidda.backend.lists.Users;
@ -1137,16 +1138,16 @@ public class Twitter {
/**
* upload medida file to twitter and generate a media ID
*
* @param uploadStream path to the local file
* @param mediaStream inputstream with MIME type of the media
* @return media ID
*/
public long uploadMedia(InputStream uploadStream, String mime) throws TwitterException {
public long uploadMedia(MediaStream mediaStream) throws TwitterException {
List<String> params = new ArrayList<>(4);
try {
// step 1 INIT
params.add("command=INIT");
params.add("media_type=" + mime);
params.add("total_bytes=" + uploadStream.available());
params.add("media_type=" + mediaStream.getMimeType());
params.add("total_bytes=" + mediaStream.available());
Response response = post(MEDIA_UPLOAD, params);
if (response.code() < 200 || response.code() >= 300 || response.body() == null)
throw new TwitterException(response);
@ -1158,7 +1159,7 @@ public class Twitter {
params.add("command=APPEND");
params.add("segment_index=0");
params.add("media_id=" + mediaId);
response = post(MEDIA_UPLOAD, params, uploadStream, "media");
response = post(MEDIA_UPLOAD, params, mediaStream.getStream(), "media");
if (response.code() < 200 || response.code() >= 300)
throw new TwitterException(response);

View File

@ -1,10 +1,11 @@
package org.nuclearfog.twidda.backend.holder;
package org.nuclearfog.twidda.backend.api.holder;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
@ -18,8 +19,7 @@ public class DirectmessageHolder {
private String name;
private String text;
private String mimeType = "";
private InputStream fileStream;
private MediaStream mediaStream;
public DirectmessageHolder(String name, String text) {
@ -36,8 +36,9 @@ public class DirectmessageHolder {
public void addMedia(Context context, @NonNull Uri uri) {
ContentResolver resolver = context.getContentResolver();
try {
fileStream = resolver.openInputStream(uri);
mimeType = resolver.getType(uri);
String mimeType = resolver.getType(uri);
InputStream fileStream = resolver.openInputStream(uri);
mediaStream = new MediaStream(fileStream, mimeType);
} catch (IOException e) {
e.printStackTrace();
}
@ -61,21 +62,14 @@ public class DirectmessageHolder {
return text;
}
/**
* get inputstream of the media file
*
* @return input stream
*/
public InputStream getMediaStream() {
return fileStream;
}
/**
* get MIME type of the media file
*
* @return mime type string
*/
public String getMimeType() {
return mimeType;
@Nullable
public MediaStream getMediaStream() {
return mediaStream;
}
}

View File

@ -1,4 +1,4 @@
package org.nuclearfog.twidda.backend.holder;
package org.nuclearfog.twidda.backend.api.holder;
/**
* This class stores information about an user list
@ -80,6 +80,6 @@ public class ListHolder {
* @return true if list exists
*/
public boolean exists() {
return listId != -1;
return listId != NEW_LIST;
}
}

View File

@ -0,0 +1,52 @@
package org.nuclearfog.twidda.backend.api.holder;
import java.io.IOException;
import java.io.InputStream;
/**
* this class collects information about a media file to upload
*
* @author nuclearfog
*/
public class MediaStream {
private InputStream inputStream;
private String mimeType;
public MediaStream(InputStream inputStream, String mimeType) {
this.inputStream = inputStream;
this.mimeType = mimeType;
}
/**
* @return input stream of the media file
*/
public InputStream getStream() {
return inputStream;
}
/**
* @return MIME type of the stream
*/
public String getMimeType() {
return mimeType;
}
/**
* @return remaining bytes of the stream
*/
public int available() throws IOException {
return inputStream.available();
}
/**
* close stream
*/
public void close() {
try {
inputStream.close();
} catch (IOException e) {
// ignore
}
}
}

View File

@ -1,8 +1,9 @@
package org.nuclearfog.twidda.backend.holder;
package org.nuclearfog.twidda.backend.api.holder;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.IOException;
@ -37,7 +38,7 @@ public class ProfileHolder {
* @param context context used to resolve Uri
* @param profileImgUri Uri of the local image file
*/
public void addImageUri(Context context, @Nullable Uri profileImgUri) {
public void addImageUri(Context context, @NonNull Uri profileImgUri) {
try {
profileImgStream = context.getContentResolver().openInputStream(profileImgUri);
} catch (IOException e) {
@ -51,7 +52,7 @@ public class ProfileHolder {
* @param context context used to resolve Uri
* @param bannerImgUri Uri of the local image file
*/
public void addBannerUri(Context context, @Nullable Uri bannerImgUri) {
public void addBannerUri(Context context, @NonNull Uri bannerImgUri) {
try {
bannerImgStream = context.getContentResolver().openInputStream(bannerImgUri);
} catch (IOException e) {
@ -90,6 +91,7 @@ public class ProfileHolder {
/**
* @return filestream of the profile image
*/
@Nullable
public InputStream getProfileImageStream() {
return profileImgStream;
}
@ -97,6 +99,7 @@ public class ProfileHolder {
/**
* @return filestream of the banner image
*/
@Nullable
public InputStream getBannerImageStream() {
return bannerImgStream;
}

View File

@ -1,4 +1,4 @@
package org.nuclearfog.twidda.backend.holder;
package org.nuclearfog.twidda.backend.api.holder;
import android.content.ContentResolver;
import android.content.Context;
@ -6,6 +6,7 @@ import android.location.Location;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.InputStream;
import java.util.ArrayList;
@ -97,6 +98,7 @@ public class TweetHolder {
*
* @return media type
*/
@Nullable
public String[] getMimeTypes() {
return mimeTypes;
}
@ -106,6 +108,7 @@ public class TweetHolder {
*
* @return array of media paths
*/
@Nullable
public InputStream[] getMediaStreams() {
return mediaStreams;
}

View File

@ -11,7 +11,7 @@ import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
@ -27,6 +27,8 @@ public final class StringTools {
private static final SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
private static final long DEFAULT_TIME = 0x61D99F64;
private static Random rand = new Random();
private StringTools() {
}
@ -171,8 +173,9 @@ public final class StringTools {
* @return random percentaged string
*/
public static String getRandomString() {
String rand = UUID.randomUUID().toString();
return new String(Base64.encode(rand.getBytes(), Base64.NO_PADDING | Base64.NO_WRAP));
byte[] randomBytes = new byte[16];
rand.nextBytes(randomBytes);
return new String(Base64.encode(randomBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP));
}
/**