added location info, bug fix

This commit is contained in:
nuclearfog 2019-11-10 15:57:38 +01:00
parent 19e94ff9e6
commit 6b2009766f
No known key found for this signature in database
GPG Key ID: ED35E22099354A64
14 changed files with 160 additions and 21 deletions

View File

@ -33,14 +33,12 @@ android {
} }
dependencies { dependencies {
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.exifinterface:exifinterface:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0' implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'org.twitter4j:twitter4j-core:4.0.7' implementation 'org.twitter4j:twitter4j-core:4.0.7'
implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.squareup.picasso:picasso:2.71828'

View File

@ -2,7 +2,9 @@ package org.nuclearfog.twidda.backend.items;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import twitter4j.GeoLocation;
import twitter4j.MediaEntity; import twitter4j.MediaEntity;
import twitter4j.Place;
import twitter4j.Status; import twitter4j.Status;
import twitter4j.URLEntity; import twitter4j.URLEntity;
@ -32,12 +34,27 @@ public class Tweet {
private final boolean retweeted; private final boolean retweeted;
private final boolean favored; private final boolean favored;
private final String locationName;
private final String locationCoordinates;
/**
* Tweet Constructor
*
* @param status Twitter4J status
*/
public Tweet(Status status) { public Tweet(Status status) {
this(status, status.getRetweetCount(), status.isRetweeted(), status.getFavoriteCount(), status.isFavorited()); this(status, status.getRetweetCount(), status.isRetweeted(), status.getFavoriteCount(), status.isFavorited());
} }
/**
* Tweet constructor
* @param status twitter4j status
* @param retweetCount set retweet count
* @param retweeted set if tweet is retweeted by current user
* @param favoriteCount set favor count
* @param favored set if tweet is favored by current user
*/
public Tweet(Status status, int retweetCount, boolean retweeted, int favoriteCount, boolean favored) { public Tweet(Status status, int retweetCount, boolean retweeted, int favoriteCount, boolean favored) {
this.retweetCount = retweetCount; this.retweetCount = retweetCount;
this.retweeted = retweeted; this.retweeted = retweeted;
@ -57,6 +74,16 @@ public class Tweet {
api = api.substring(0, api.indexOf('<')); api = api.substring(0, api.indexOf('<'));
source = api; source = api;
Place place = status.getPlace();
GeoLocation geo = status.getGeoLocation();
if (place != null)
locationName = place.getFullName();
else
locationName = "";
if (geo != null)
locationCoordinates = geo.getLatitude() + "," + geo.getLongitude();
else
locationCoordinates = "";
if (status.getInReplyToScreenName() == null) if (status.getInReplyToScreenName() == null)
replyName = ""; replyName = "";
else else
@ -67,10 +94,29 @@ public class Tweet {
embedded = null; embedded = null;
} }
/**
* Tweet constructor for database tweets
* @param tweetID unique id of tweet
* @param retweetCount number of retweets
* @param favoriteCount number of favors
* @param user tweet author
* @param tweet tweet text
* @param time time long format
* @param replyName author's name of replied tweet
* @param replyUserId quthor's ID of replied tweet
* @param medias Media links attached to tweet
* @param source used API of the tweet
* @param replyID ID of replied tweet
* @param embedded quoted tweet
* @param myRetweetId ID of the current users retweeted tweet
* @param retweeted tweet is retweeted by current user
* @param favored tweet is favored by current user
* @param coordinates location gps coordinates
* @param place location full place name
*/
public Tweet(long tweetID, int retweetCount, int favoriteCount, TwitterUser user, String tweet, long time, public Tweet(long tweetID, int retweetCount, int favoriteCount, TwitterUser user, String tweet, long time,
String replyName, long replyUserId, String[] medias, String source, long replyID, String replyName, long replyUserId, String[] medias, String source, long replyID,
Tweet embedded, long myRetweetId, boolean retweeted, boolean favored) { Tweet embedded, long myRetweetId, boolean retweeted, boolean favored, String place, String coordinates) {
this.tweetID = tweetID; this.tweetID = tweetID;
this.user = user; this.user = user;
this.retweetCount = retweetCount; this.retweetCount = retweetCount;
@ -86,6 +132,8 @@ public class Tweet {
this.favored = favored; this.favored = favored;
this.myRetweetId = myRetweetId; this.myRetweetId = myRetweetId;
this.replyUserId = replyUserId; this.replyUserId = replyUserId;
this.locationName = place;
this.locationCoordinates = coordinates;
} }
/** /**
@ -233,6 +281,24 @@ public class Tweet {
return favored; return favored;
} }
/**
* get location of tweet if any
*
* @return full location name
*/
public String getLocationName() {
return locationName;
}
/**
* get location coordinate
*
* @return latitude and longitude
*/
public String getLocationCoordinates() {
return locationCoordinates;
}
/** /**
* @param status Twitter4J status * @param status Twitter4J status
* @return Array of Medialinks * @return Array of Medialinks

View File

@ -545,6 +545,10 @@ public class AppDatabase {
String source = cursor.getString(index); String source = cursor.getString(index);
index = cursor.getColumnIndex("media"); index = cursor.getColumnIndex("media");
String medialinks = cursor.getString(index); String medialinks = cursor.getString(index);
index = cursor.getColumnIndex("place");
String place = cursor.getString(index);
index = cursor.getColumnIndex("geo");
String geo = cursor.getString(index);
index = cursor.getColumnIndex("replyUserID"); index = cursor.getColumnIndex("replyUserID");
long replyUserId = cursor.getLong(index); long replyUserId = cursor.getLong(index);
index = cursor.getColumnIndex("statusregister"); index = cursor.getColumnIndex("statusregister");
@ -559,7 +563,7 @@ public class AppDatabase {
if (retweetId > 1) if (retweetId > 1)
embeddedTweet = getStatus(retweetId); embeddedTweet = getStatus(retweetId);
return new Tweet(tweetId, retweet, favorit, user, tweettext, time, replyname, replyUserId, medias, return new Tweet(tweetId, retweet, favorit, user, tweettext, time, replyname, replyUserId, medias,
source, replyStatusId, embeddedTweet, retweeterId, retweeted, favorited); source, replyStatusId, embeddedTweet, retweeterId, retweeted, favorited, place, geo);
} }
@ -691,6 +695,9 @@ public class AppDatabase {
status.put("favorite", tweet.getFavorCount()); status.put("favorite", tweet.getFavorCount());
status.put("retweeterID", tweet.getMyRetweetId()); status.put("retweeterID", tweet.getMyRetweetId());
status.put("replyUserID", tweet.getReplyUserId()); status.put("replyUserID", tweet.getReplyUserId());
status.put("place", tweet.getLocationName());
status.put("geo", tweet.getLocationCoordinates());
status.put("replyUserID", tweet.getReplyUserId());
if (tweet.getReplyUserId() > 0) if (tweet.getReplyUserId() > 0)
status.put("replyname", tweet.getReplyName()); status.put("replyname", tweet.getReplyName());
storeUser(user, db, CONFLICT_IGNORE); storeUser(user, db, CONFLICT_IGNORE);

View File

@ -14,17 +14,18 @@ import static android.content.Context.MODE_PRIVATE;
*/ */
public class DatabaseAdapter { public class DatabaseAdapter {
private static final int DB_VERSION = 2;
private static final String DB_NAME = "database.db"; private static final String DB_NAME = "database.db";
private static final String TABLE_USER = "CREATE TABLE IF NOT EXISTS user (" + private static final String TABLE_USER = "CREATE TABLE IF NOT EXISTS user (" +
"userID INTEGER PRIMARY KEY,username VARCHAR(50),scrname VARCHAR(15)," + "userID INTEGER PRIMARY KEY,username TEXT,scrname TEXT," +
"pbLink TEXT,banner TEXT,bio TEXT,location TEXT,link TEXT,userregister INTEGER," + "pbLink TEXT,banner TEXT,bio TEXT,location TEXT,link TEXT,userregister INTEGER," +
"createdAt INTEGER,following INTEGER,follower INTEGER,tweetCount INTEGER,favorCount INTEGER);"; "createdAt INTEGER,following INTEGER,follower INTEGER,tweetCount INTEGER,favorCount INTEGER);";
private static final String TABLE_TWEET = "CREATE TABLE IF NOT EXISTS tweet (" + private static final String TABLE_TWEET = "CREATE TABLE IF NOT EXISTS tweet (" +
"tweetID INTEGER PRIMARY KEY,userID INTEGER,retweetID INTEGER,replyID INTEGER,retweeterID INTEGER," + "tweetID INTEGER PRIMARY KEY,userID INTEGER,retweetID INTEGER,replyID INTEGER,retweeterID INTEGER," +
"replyname TEXT,replyUserID INTEGER,time INTEGER,tweet TEXT,media TEXT,retweet INTEGER,favorite INTEGER," + "replyname TEXT,replyUserID INTEGER,time INTEGER,tweet TEXT,media TEXT,retweet INTEGER,favorite INTEGER," +
"statusregister INTEGER,source VARCHAR(32),FOREIGN KEY (userID) REFERENCES user(userID));"; "statusregister INTEGER,source TEXT,place TEXT,geo TEXT,FOREIGN KEY (userID) REFERENCES user(userID));";
private static final String TABLE_FAVORS = "CREATE TABLE IF NOT EXISTS favorit (" + private static final String TABLE_FAVORS = "CREATE TABLE IF NOT EXISTS favorit (" +
"ownerID INTEGER,tweetID INTEGER," + "ownerID INTEGER,tweetID INTEGER," +
@ -42,6 +43,9 @@ public class DatabaseAdapter {
private static final String INDX_FAVOR = "CREATE INDEX IF NOT EXISTS idx_favor ON favorit(ownerID,tweetID);"; private static final String INDX_FAVOR = "CREATE INDEX IF NOT EXISTS idx_favor ON favorit(ownerID,tweetID);";
private static final String INDX_TREND = "CREATE INDEX IF NOT EXISTS idx_trend ON trend(woeID);"; private static final String INDX_TREND = "CREATE INDEX IF NOT EXISTS idx_trend ON trend(woeID);";
private static final String TABLE_TWEET_ADD_PLACE = "ALTER TABLE tweet ADD COLUMN place TEXT";
private static final String TABLE_TWEET_ADD_GEO = "ALTER TABLE tweet ADD COLUMN geo TEXT";
private static DatabaseAdapter instance; private static DatabaseAdapter instance;
private final File databasePath; private final File databasePath;
@ -53,6 +57,7 @@ public class DatabaseAdapter {
databasePath = context.getDatabasePath(DB_NAME); databasePath = context.getDatabasePath(DB_NAME);
db = context.openOrCreateDatabase(databasePath.toString(), MODE_PRIVATE, null); db = context.openOrCreateDatabase(databasePath.toString(), MODE_PRIVATE, null);
initTables(); initTables();
updateTable();
} }
@ -78,6 +83,15 @@ public class DatabaseAdapter {
} }
private void updateTable() {
if (db.getVersion() < DB_VERSION) {
db.execSQL(TABLE_TWEET_ADD_PLACE);
db.execSQL(TABLE_TWEET_ADD_GEO);
db.setVersion(DB_VERSION);
}
}
private void initTables() { private void initTables() {
db.execSQL(TABLE_USER); db.execSQL(TABLE_USER);
db.execSQL(TABLE_TWEET); db.execSQL(TABLE_TWEET);

View File

@ -25,10 +25,11 @@ public class MessageLoader extends AsyncTask<Long, Void, List<Message>> {
DEL DEL
} }
@Nullable
private TwitterException twException;
private Mode mode; private Mode mode;
private WeakReference<MessageListFragment> ui; private WeakReference<MessageListFragment> ui;
private TwitterEngine mTwitter; private TwitterEngine mTwitter;
private TwitterException twException;
private AppDatabase db; private AppDatabase db;
private MessageAdapter adapter; private MessageAdapter adapter;

View File

@ -20,8 +20,9 @@ import twitter4j.TwitterException;
public class TrendLoader extends AsyncTask<Void, Void, List<String>> { public class TrendLoader extends AsyncTask<Void, Void, List<String>> {
private WeakReference<TrendListFragment> ui; @Nullable
private TwitterException twException; private TwitterException twException;
private WeakReference<TrendListFragment> ui;
private TwitterEngine mTwitter; private TwitterEngine mTwitter;
private AppDatabase db; private AppDatabase db;
private TrendAdapter adapter; private TrendAdapter adapter;

View File

@ -17,6 +17,9 @@ import java.util.List;
import twitter4j.TwitterException; import twitter4j.TwitterException;
/**
* Timeline loader Task
*/
public class TweetLoader extends AsyncTask<Object, Void, List<Tweet>> { public class TweetLoader extends AsyncTask<Object, Void, List<Tweet>> {
public enum Mode { public enum Mode {
@ -29,11 +32,12 @@ public class TweetLoader extends AsyncTask<Object, Void, List<Tweet>> {
TWEET_SEARCH TWEET_SEARCH
} }
@Nullable
private TwitterException twException;
private Mode mode; private Mode mode;
private WeakReference<TweetListFragment> ui; private WeakReference<TweetListFragment> ui;
private TweetAdapter adapter; private TweetAdapter adapter;
private TwitterEngine mTwitter; private TwitterEngine mTwitter;
private TwitterException twException;
private AppDatabase db; private AppDatabase db;

View File

@ -18,6 +18,9 @@ import java.util.List;
import twitter4j.TwitterException; import twitter4j.TwitterException;
/**
* User list loader task
*/
public class UserLoader extends AsyncTask<Object, Void, List<TwitterUser>> { public class UserLoader extends AsyncTask<Object, Void, List<TwitterUser>> {
public enum Mode { public enum Mode {
@ -28,10 +31,11 @@ public class UserLoader extends AsyncTask<Object, Void, List<TwitterUser>> {
SEARCH SEARCH
} }
@Nullable
private TwitterException twException;
private Mode mode; private Mode mode;
private WeakReference<UserListFragment> ui; private WeakReference<UserListFragment> ui;
private TwitterEngine mTwitter; private TwitterEngine mTwitter;
private TwitterException twException;
private UserAdapter adapter; private UserAdapter adapter;

View File

@ -9,7 +9,10 @@ import android.net.ConnectivityManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -51,6 +54,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static android.os.AsyncTask.Status.RUNNING; import static android.os.AsyncTask.Status.RUNNING;
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_UP;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
@ -76,7 +80,7 @@ public class TweetDetail extends AppCompatActivity implements OnClickListener, O
private static final Pattern linkPattern = Pattern.compile("/@?[\\w_]+/status/\\d{1,20}/?.*"); private static final Pattern linkPattern = Pattern.compile("/@?[\\w_]+/status/\\d{1,20}/?.*");
private View header, footer, videoButton, imageButton; private View header, footer, videoButton, imageButton;
private TextView tweet_api, tweetDate, tweetText, scrName, usrName; private TextView tweet_api, tweetDate, tweetText, scrName, usrName, tweetLoc;
private Button rtwButton, favButton, replyName; private Button rtwButton, favButton, replyName;
private ImageView profile_img; private ImageView profile_img;
@ -123,6 +127,7 @@ public class TweetDetail extends AppCompatActivity implements OnClickListener, O
tweetText = findViewById(R.id.tweet_detailed); tweetText = findViewById(R.id.tweet_detailed);
tweetDate = findViewById(R.id.timedetail); tweetDate = findViewById(R.id.timedetail);
tweet_api = findViewById(R.id.used_api); tweet_api = findViewById(R.id.used_api);
tweetLoc = findViewById(R.id.tweet_location);
imageButton = findViewById(R.id.image_attach); imageButton = findViewById(R.id.image_attach);
videoButton = findViewById(R.id.video_attach); videoButton = findViewById(R.id.video_attach);
@ -403,6 +408,30 @@ public class TweetDetail extends AppCompatActivity implements OnClickListener, O
} }
if (settings.getImageLoad()) if (settings.getImageLoad())
Picasso.get().load(tweet.getUser().getImageLink() + "_bigger").into(profile_img); Picasso.get().load(tweet.getUser().getImageLink() + "_bigger").into(profile_img);
SpannableStringBuilder locationText = new SpannableStringBuilder("");
if (!tweet.getLocationName().isEmpty())
locationText.append(tweet.getLocationName());
if (!tweet.getLocationCoordinates().isEmpty()) {
final int start = locationText.length();
locationText.append(tweet.getLocationCoordinates());
final int end = locationText.length() - 1;
locationText.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
Intent locationIntent = new Intent(Intent.ACTION_VIEW);
locationIntent.setData(Uri.parse("geo:" + tweet.getLocationCoordinates()));
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
ds.setColor(settings.getHighlightColor());
ds.setUnderlineText(false);
}
}, start, end, SPAN_EXCLUSIVE_EXCLUSIVE);
tweetLoc.setText(locationText);
tweetLoc.setVisibility(VISIBLE);
}
} }

View File

@ -275,6 +275,8 @@ public class TweetPopup extends AppCompatActivity implements OnClickListener, Lo
@Override @Override
public void onProviderDisabled(String provider) { public void onProviderDisabled(String provider) {
if (gpsLocation == null)
Toast.makeText(this, R.string.error_gps, LENGTH_SHORT).show();
} }

View File

@ -95,7 +95,7 @@
android:paddingRight="@dimen/button_padding" android:paddingRight="@dimen/button_padding"
android:background="@drawable/button" android:background="@drawable/button"
android:singleLine="true" android:singleLine="true"
android:textSize="@dimen/textsize_refer" android:textSize="@dimen/tweet_textsize_api"
android:visibility="gone" android:visibility="gone"
style="@style/Widget.AppCompat.Button.Borderless" /> style="@style/Widget.AppCompat.Button.Borderless" />
@ -103,13 +103,23 @@
android:id="@+id/tweet_detailed" android:id="@+id/tweet_detailed"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
android:autoLink="web" android:autoLink="web"
android:fadeScrollbars="false" android:fadeScrollbars="false"
android:linksClickable="true" android:linksClickable="true"
android:maxLines="@integer/text_tweet_lines" android:maxLines="@integer/text_tweet_lines"
android:scrollbars="vertical" android:scrollbars="vertical"
android:textSize="@dimen/textsize_tweet" /> android:textSize="@dimen/textsize_tweet"
android:visibility="gone" />
<TextView
android:id="@+id/tweet_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:visibility="gone"
android:textSize="@dimen/textsize_tweet_locale"
app:drawableLeftCompat="@drawable/userlocation"
app:drawableStartCompat="@drawable/userlocation" />
<ImageButton <ImageButton
android:id="@+id/image_attach" android:id="@+id/image_attach"
@ -139,7 +149,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:linksClickable="false" android:linksClickable="false"
android:singleLine="true" android:singleLine="true"
android:textSize="@dimen/textsize_refer" /> android:textSize="@dimen/tweet_textsize_api" />
</LinearLayout> </LinearLayout>

View File

@ -124,4 +124,5 @@
<string name="error_cant_copy_clipboard">Link konnte nicht kopiert werden!</string> <string name="error_cant_copy_clipboard">Link konnte nicht kopiert werden!</string>
<string name="info_gps_attached">GPS Position hinzugefügt</string> <string name="info_gps_attached">GPS Position hinzugefügt</string>
<string name="info_get_location">starte GPS lokalisierung...</string> <string name="info_get_location">starte GPS lokalisierung...</string>
<string name="error_gps">GPS lokalisierung fehlgeschlagen!</string>
</resources> </resources>

View File

@ -28,12 +28,13 @@
<dimen name="textsize_profileedit">18sp</dimen> <dimen name="textsize_profileedit">18sp</dimen>
<dimen name="textsize_count">18sp</dimen> <dimen name="textsize_count">18sp</dimen>
<dimen name="textsize_tweet">18sp</dimen> <dimen name="textsize_tweet">18sp</dimen>
<dimen name="textsize_tweet_locale">12sp</dimen>
<dimen name="textsize_settings">18sp</dimen> <dimen name="textsize_settings">18sp</dimen>
<dimen name="textsize_profile">12sp</dimen> <dimen name="textsize_profile">12sp</dimen>
<dimen name="textsize_button">12sp</dimen> <dimen name="textsize_button">12sp</dimen>
<dimen name="textsize_date">12sp</dimen> <dimen name="textsize_date">12sp</dimen>
<dimen name="textsize_name">12sp</dimen> <dimen name="textsize_name">12sp</dimen>
<dimen name="textsize_refer">12sp</dimen> <dimen name="tweet_textsize_api">12sp</dimen>
<dimen name="textsize_checkbox">10sp</dimen> <dimen name="textsize_checkbox">10sp</dimen>
<integer name="text_tweet_lines">9</integer> <integer name="text_tweet_lines">9</integer>
<integer name="text_bio_lines">5</integer> <integer name="text_bio_lines">5</integer>

View File

@ -125,4 +125,5 @@
<string name="error_cant_copy_clipboard">can\'t copy link to clipboard!</string> <string name="error_cant_copy_clipboard">can\'t copy link to clipboard!</string>
<string name="info_gps_attached">GPS position added</string> <string name="info_gps_attached">GPS position added</string>
<string name="info_get_location">starting location...</string> <string name="info_get_location">starting location...</string>
<string name="error_gps">could not fetch GPS data!</string>
</resources> </resources>