added image downloader/uploader, added profile updater endpoint, removed unused resources

This commit is contained in:
nuclearfog 2022-01-12 15:42:19 +01:00
parent 5d0fa41866
commit c3ec249efb
No known key found for this signature in database
GPG Key ID: AA0271FBE406DB98
10 changed files with 143 additions and 70 deletions

View File

@ -82,7 +82,7 @@ public class MessageEditor extends MediaActivity implements OnClickListener, OnC
receiver.append(prefix);
}
send.setImageResource(R.drawable.right);
media.setImageResource(R.drawable.image_add);
media.setImageResource(R.drawable.attachment);
preview.setImageResource(R.drawable.image);
preview.setVisibility(GONE);
AppStyles.setEditorTheme(root, background);

View File

@ -125,7 +125,7 @@ public class TweetEditor extends MediaActivity implements OnClickListener, OnPro
tweetText.append(prefix);
}
previewBtn.setImageResource(R.drawable.image);
mediaBtn.setImageResource(R.drawable.image_add);
mediaBtn.setImageResource(R.drawable.attachment);
locationBtn.setImageResource(R.drawable.location);
tweetButton.setImageResource(R.drawable.tweet);
closeButton.setImageResource(R.drawable.cross);

View File

@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.activities.MediaViewer;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.holder.ImageHolder;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
@ -16,6 +17,7 @@ import java.lang.ref.WeakReference;
/**
* Background task to load images from twitter and storage
* todo: cache files to prevent out of memory error
*
* @author nuclearfog
* @see MediaViewer
@ -44,9 +46,9 @@ public class ImageLoader extends AsyncTask<String, ImageHolder, Boolean> {
protected Boolean doInBackground(String[] links) {
try {
for (String link : links) {
Bitmap image = null;
if (link.startsWith("https://")) { // fixme
//image = mTwitter.getImage(link);
Bitmap image;
if (link.startsWith("https://")) {
image = twitter.downloadImage(link);
} else {
image = BitmapFactory.decodeFile(link);
}
@ -56,9 +58,9 @@ public class ImageLoader extends AsyncTask<String, ImageHolder, Boolean> {
}
}
return true;
} /*catch (EngineException err) {
} catch (TwitterException err) {
this.err = err;
}*/ catch (Exception exception) {
} catch (Exception exception) {
exception.printStackTrace();
}
return false;

View File

@ -44,14 +44,14 @@ public class UserUpdater extends AsyncTask<String, Void, User> {
String location = param[2];
String bio = param[3];
String profileImg = param[4];
String bannerImg = param[5];// fixme
//User user = mTwitter.updateProfile(name, link, location, bio, profileImg, bannerImg);
//db.storeUser(user);
//return user;
} /*catch (TwitterException twException) {
String bannerImg = param[5];
twitter.updateProfileImage(profileImg);
twitter.updateProfileBanner(bannerImg);
User user = twitter.updateProfile(name, link, location, bio);
db.storeUser(user);
return user;
} catch (TwitterException twException) {
this.twException = twException;
}*/ catch (Exception err) {
err.printStackTrace();
}
return null;
}

View File

@ -1,6 +1,8 @@
package org.nuclearfog.twidda.backend.api;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
@ -24,6 +26,8 @@ import org.nuclearfog.twidda.model.UserList;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.LinkedList;
@ -104,6 +108,9 @@ public class Twitter {
private static final String DIRECTMESSAGE_CREATE = API + "1.1/direct_messages/events/new.json";
private static final String DIRECTMESSAGE_DELETE = API + "1.1/direct_messages/events/destroy.json";
private static final String MEDIA_UPLOAD = UPLOAD + "1.1/media/upload.json";
private static final String PROFILE_UPDATE = API + "1.1/account/update_profile.json";
private static final String PROFILE_UPDATE_IMAGE = API + "1.1/account/update_profile_image.json";
private static final String PROFILE_UPDATE_BANNER = API + "1.1/account/update_profile_banner.json";
public static final String REQUEST_URL = AUTHENTICATE + "?oauth_token=";
private static Twitter instance;
@ -118,6 +125,8 @@ public class Twitter {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.writeTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).connectTimeout(60, TimeUnit.SECONDS);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// set TLS 1.2 support for default connections
TLSSocketFactory.setSupportTLS();
try {
// use experimental TLS 1.2 support for pre-Lollipop devices
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
@ -229,7 +238,7 @@ public class Twitter {
public User showUser(long id) throws TwitterException {
List<String> params = new ArrayList<>(3);
params.add("user_id=" + id);
return showUser(params);
return getUser1(USER_LOOKUP, params);
}
/**
@ -241,7 +250,7 @@ public class Twitter {
public User showUser(String name) throws TwitterException {
List<String> params = new ArrayList<>(3);
params.add("screen_name=" + name);
return showUser(params);
return getUser1(USER_LOOKUP, params);
}
/**
@ -1059,7 +1068,7 @@ public class Twitter {
public Directmessages getDirectmessages(String cursor) throws TwitterException {
List<String> params = new ArrayList<>(3);
params.add("count=" + settings.getListSize());
if (!cursor.isEmpty())
if (cursor != null && !cursor.isEmpty())
params.add("cursor=" + cursor);
try {
Response response = get(DIRECTMESSAGE, params);
@ -1154,32 +1163,70 @@ public class Twitter {
}
/**
* lookup single user
* download image from twitter
*
* @param params additional parameter added to request
* @return user information
* @param link link to the image
* @return image bitmap
*/
private User showUser(List<String> params) throws TwitterException {
public Bitmap downloadImage(String link) throws TwitterException {
try {
params.add(UserV1.INCLUDE_ENTITIES);
Response response = get(USER_LOOKUP, params);
if (response.body() != null) {
JSONObject json = new JSONObject(response.body().string());
// this type of link requires authentication
if (link.startsWith("https://ton.twitter.com/")) {
Response response = get(link, new ArrayList<>(0));
if (response.code() == 200) {
return new UserV1(json, settings.getCurrentUserId());
byte[] data = response.body().bytes();
return BitmapFactory.decodeByteArray(data, 0, 0);
} else {
throw new TwitterException(json);
throw new TwitterException(response);
}
} else {
throw new TwitterException(response);
}
} catch (IOException err) {
throw new TwitterException(err);
} catch (JSONException err) {
throw new TwitterException(err);
// public link, no authentication required
else {
URL imageUrl = new URL(link);
InputStream is = imageUrl.openConnection().getInputStream();
return BitmapFactory.decodeStream(is);
}
} catch (IOException e) {
throw new TwitterException(e);
}
}
/**
* updates current user's profile
*
* @param username new username
* @param url new profile URL
* @param location new location name
* @param description new description
* @return updated user information
*/
public User updateProfile(String username, String url, String location, String description) throws TwitterException {
List<String> params = new ArrayList<>(7);
params.add("name=" + StringTools.encode(username));
params.add("url=" + StringTools.encode(url));
params.add("location=" + StringTools.encode(location));
params.add("description=" + StringTools.encode(description));
return getUser1(PROFILE_UPDATE, params);
}
/**
* update current user's profile image
*
* @param path local path to the image
*/
public void updateProfileImage(String path) throws TwitterException {
updateImage(PROFILE_UPDATE_IMAGE, path, "image");
}
/**
* update current user's profile banner image
*
* @param path local path to the image
*/
public void updateProfileBanner(String path) throws TwitterException {
updateImage(PROFILE_UPDATE_BANNER, path, "banner");
}
/**
* get tweets using an endpoint
*
@ -1262,7 +1309,7 @@ public class Twitter {
private Users getUsers1(String endpoint, List<String> params) throws TwitterException {
try {
params.add("count=" + settings.getListSize());
params.add(UserV1.SKIP_STAT);
params.add("skip_status=true");
Response response = get(endpoint, params);
if (response.body() != null) {
String jsonResult = response.body().string();
@ -1346,7 +1393,13 @@ public class Twitter {
*/
private User getUser1(String endpoint, List<String> params) throws TwitterException {
try {
Response response = post(endpoint, params);
params.add("skip_status=true");
params.add("include_entities=true");
Response response;
if (endpoint.equals(USER_LOOKUP))
response = get(endpoint, params);
else
response = post(endpoint, params);
if (response.body() != null) {
JSONObject json = new JSONObject(response.body().string());
if (response.code() == 200) {
@ -1404,7 +1457,7 @@ public class Twitter {
* @return list of userlists
*/
private UserLists getUserlists(String endpoint, List<String> params) throws TwitterException {
params.add(UserV1.INCLUDE_ENTITIES);
params.add("include_entities=true");
try {
Response response = get(endpoint, params);
if (response.body() != null) {
@ -1442,6 +1495,34 @@ public class Twitter {
}
}
/**
* update profile images
*
* @param endpoint endpoint to use
* @param imagePath path to the local image
* @param key key name used to identify the type of image
*/
private void updateImage(String endpoint, String imagePath, String key) throws TwitterException {
try {
List<String> params = new ArrayList<>(3);
params.add("skip_status=true");
params.add("include_entities=false");
Response response = post(endpoint, params, new File(imagePath), key);
if (response.body() != null) {
JSONObject json = new JSONObject(response.body().string());
if (response.code() != 200) {
throw new TwitterException(json);
}
} else {
throw new TwitterException(response);
}
} catch (IOException err) {
throw new TwitterException(err);
} catch (JSONException err) {
throw new TwitterException(err);
}
}
/**
* send post without return value
*

View File

@ -15,9 +15,6 @@ import org.nuclearfog.twidda.model.User;
*/
class UserV1 implements User {
static final String SKIP_STAT = "skip_status=true";
static final String INCLUDE_ENTITIES = "include_entities=true";
private long userID;
private long created;
private String username;
@ -45,7 +42,7 @@ class UserV1 implements User {
UserV1(JSONObject json) {
String bannerLink = json.optString("profile_banner_url");
profileBannerUrl = json.optString("profile_banner_url");
description = json.optString("description");
username = json.optString("name");
screenName = '@' + json.optString("screen_name");
@ -63,11 +60,6 @@ class UserV1 implements User {
profileUrl = json.optString("profile_image_url_https");
created = StringTools.getTime(json.optString("created_at"));
// remove link suffix from banner URL
if (bannerLink.length() > 4) {
profileBannerUrl = bannerLink.substring(0, bannerLink.length() - 4);
}
// expand URLs
JSONObject entities = json.optJSONObject("entities");
if (entities != null) {

View File

@ -1,7 +1,5 @@
package org.nuclearfog.twidda.backend.utils;
import android.os.Build;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
@ -36,25 +34,22 @@ public class TLSSocketFactory extends SSLSocketFactory {
/**
* check if TLS 1.2 is enabled and enable experimental TLS 1.2 support on Pre-Lollipop devices
*/
public static void getSupportTLSifNeeded() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// check for TLS 1.2 support and activate it
try {
boolean tlsEnabled = false;
SSLParameters param = SSLContext.getDefault().getDefaultSSLParameters();
String[] protocols = param.getProtocols();
for (String protocol : protocols) {
if (protocol.equals(TLS_1_2) || protocol.equals(TLS_1_3)) {
tlsEnabled = true;
break;
}
public static void setSupportTLS() {
try {
boolean tlsEnabled = false;
SSLParameters param = SSLContext.getDefault().getDefaultSSLParameters();
String[] protocols = param.getProtocols();
for (String protocol : protocols) {
if (protocol.equals(TLS_1_2) || protocol.equals(TLS_1_3)) {
tlsEnabled = true;
break;
}
if (!tlsEnabled) {
HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory());
}
} catch (Exception err) {
err.printStackTrace();
}
if (!tlsEnabled) {
HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory());
}
} catch (Exception err) {
err.printStackTrace();
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M5.602,19.8c-1.293,0 -2.504,-0.555 -3.378,-1.44c-1.695,-1.716 -2.167,-4.711 0.209,-7.116c1.391,-1.408 6.966,-7.053 9.748,-9.87c0.988,-1 2.245,-1.387 3.448,-1.06c1.183,0.32 2.151,1.301 2.468,2.498c0.322,1.22 -0.059,2.493 -1.046,3.493l-9.323,9.44c-0.532,0.539 -1.134,0.858 -1.738,0.922c-0.599,0.064 -1.17,-0.13 -1.57,-0.535c-0.724,-0.736 -0.828,-2.117 0.378,-3.337l6.548,-6.63c0.269,-0.272 0.705,-0.272 0.974,0s0.269,0.714 0,0.986l-6.549,6.631c-0.566,0.572 -0.618,1.119 -0.377,1.364C5.5,15.252 5.66,15.301 5.845,15.28c0.283,-0.029 0.606,-0.216 0.909,-0.521l9.323,-9.439c0.64,-0.648 0.885,-1.41 0.69,-2.145c-0.192,-0.725 -0.778,-1.318 -1.493,-1.513c-0.726,-0.197 -1.48,0.052 -2.12,0.7c-2.782,2.818 -8.356,8.462 -9.748,9.87c-1.816,1.839 -1.381,3.956 -0.209,5.143c1.173,1.187 3.262,1.629 5.079,-0.212l9.748,-9.87c0.269,-0.272 0.705,-0.272 0.974,0c0.269,0.272 0.269,0.714 0,0.987L9.25,18.15C8.101,19.312 6.814,19.8 5.602,19.8z"
android:fillColor="#FFFFFF"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -15,12 +15,6 @@
android:text="@string/app_name"
android:textSize="@dimen/infopopup_appname_font" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/badge_twitter4j"
android:src="@drawable/twitter4j_badge" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"