diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 575bb43d..0803aa68 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -106,6 +106,8 @@ + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 69e2457a..361c80dc 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -44,6 +44,8 @@ オリジナル画像の取得に失敗しました ユーザー情報を取得できませんでした + TLを自動で取得するには60秒間隔以上で設定する必要があります\nこれを回避するにはリストをTLとして使用してください + diff --git a/res/xml/preference.xml b/res/xml/preference.xml index 20161166..48738c65 100644 --- a/res/xml/preference.xml +++ b/res/xml/preference.xml @@ -31,15 +31,21 @@ android:positiveButtonText="OK" android:title="フォーマット" /> + + + + + - statuses); + } + + private Timer autoLoadTimer; + + @Override + public int onStartCommand(Intent intent, int flags, int startId){ + App app = (App)getApplicationContext(); + AutoLoadTLListener listener = app.getAutoLoadTLListener(); + int interval = app.getCurrentAccount().getAutoLoadTLInterval(); + long listAsTL = app.getCurrentAccount().getListAsTL(); + + AutoLoadTLTask task = new AutoLoadTLTask(app, listener, listAsTL); + autoLoadTimer = new Timer(true); + autoLoadTimer.schedule(task, interval * 1000, interval * 1000); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + startNotification(intent); + } + return super.onStartCommand(intent, flags, startId); + } + + @TargetApi(26) + public void startNotification(Intent intent){ + Intent appIntent = new Intent(this, MainActivity.class); + appIntent.setAction(Intent.ACTION_MAIN); + appIntent.addCategory(Intent.CATEGORY_LAUNCHER); + + PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, appIntent, PendingIntent.FLAG_UPDATE_CURRENT); + String channelId = "default"; + String title = "Running AutoLoadTL Service"; + NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + NotificationChannel channel = new NotificationChannel(channelId, title, NotificationManager.IMPORTANCE_DEFAULT); + if(notificationManager != null){ + notificationManager.createNotificationChannel(channel); + Notification notification = new Notification.Builder(getApplicationContext(), channelId) + .setContentTitle(title) + .setSmallIcon(R.drawable.notification_icon) + .setAutoCancel(true) + .setContentIntent(pendingIntent) + .setWhen(System.currentTimeMillis()) + .build(); + startForeground(1, notification); + } + } + + @Override + public IBinder onBind(Intent intent){ + return null; + } + + @Override + public void onDestroy(){ + autoLoadTimer.cancel(); + autoLoadTimer.purge(); + super.onDestroy(); + } + + class AutoLoadTLTask extends TimerTask{ + + private App app; + private AutoLoadTLListener listener; + private long listAsTL; + + public AutoLoadTLTask(App app, AutoLoadTLListener listener, long listAsTL){ + this.app = app; + this.listener = listener; + this.listAsTL = listAsTL; + } + + @Override + public void run(){ + try{ + ResponseList statuses; + if(listAsTL > 0){ + statuses = app.getTwitter().getUserListStatuses(listAsTL, new Paging(1, 50).sinceId(app.getLatestTweetId())); + }else{ + statuses = app.getTwitter().getHomeTimeline(new Paging(1, 50).sinceId(app.getLatestTweetId())); + } + Collections.reverse(statuses); + listener.onStatus(statuses); + }catch(TwitterException e){ + } + } + + } + +} diff --git a/src/sugtao4423/lod/Keys.java b/src/sugtao4423/lod/Keys.java index 079cfdcb..18121f1c 100644 --- a/src/sugtao4423/lod/Keys.java +++ b/src/sugtao4423/lod/Keys.java @@ -20,5 +20,6 @@ public class Keys{ public static final String APP_START_LOAD_LISTS = "appStartLoadLists"; public static final String EXPERIENCE = "experience"; public static final String LIST_AS_TIMELINE = "listAsTL"; + public static final String AUTO_LOAD_TL_INTERVAL = "autoLoadTLInterval"; } diff --git a/src/sugtao4423/lod/MainActivity.java b/src/sugtao4423/lod/MainActivity.java index 651fca9b..4a3d1dda 100644 --- a/src/sugtao4423/lod/MainActivity.java +++ b/src/sugtao4423/lod/MainActivity.java @@ -22,6 +22,7 @@ import android.view.View; import sugtao4423.icondialog.IconDialog; import sugtao4423.icondialog.IconItem; +import sugtao4423.lod.AutoLoadTLService.AutoLoadTLListener; import sugtao4423.lod.dataclass.TwitterList; import sugtao4423.lod.main_fragment.Fragment_home; import sugtao4423.lod.main_fragment.Fragment_mention; @@ -73,6 +74,7 @@ public void logIn(){ twitter = app.getTwitter(); getList(); connectStreaming(); + autoLoadTL(); } } @@ -147,6 +149,31 @@ public void run(){ } } + public void autoLoadTL(){ + if(app.getCurrentAccount().getAutoLoadTLInterval() == 0){ + return; + } + AutoLoadTLListener listener = new AutoLoadTLListener(){ + + @Override + public void onStatus(ResponseList statuses){ + for(Status s : statuses){ + fragmentHome.insert(s); + if(app.getMentionPattern().matcher(s.getText()).find() && !s.isRetweet()){ + fragmentMention.insert(s); + } + } + } + }; + app.setAutoLoadTLListener(listener); + Intent intent = new Intent(this, AutoLoadTLService.class); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + startForegroundService(intent); + }else{ + startService(intent); + } + } + public void setMusicReceiver(){ musicReceiver = new MusicReceiver(); IntentFilter filter = new IntentFilter(); @@ -201,6 +228,7 @@ public void onDestroy(){ super.onDestroy(); unregisterReceiver(musicReceiver); stopService(new Intent(this, UserStreamService.class)); + stopService(new Intent(this, AutoLoadTLService.class)); app.resetAccount(); if(resetFlag){ resetFlag = false; diff --git a/src/sugtao4423/lod/Settings.java b/src/sugtao4423/lod/Settings.java index d73bd905..df4a469c 100644 --- a/src/sugtao4423/lod/Settings.java +++ b/src/sugtao4423/lod/Settings.java @@ -6,6 +6,7 @@ import com.loopj.android.image.WebImageCache; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; @@ -15,17 +16,23 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.Toast; import sugtao4423.lod.utils.DBUtil; +import sugtao4423.lod.utils.Utils; import twitter4j.ResponseList; import twitter4j.TwitterException; import twitter4j.UserList; import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; +import android.text.InputType; public class Settings extends PreferenceActivity{ private App app; + private Preference autoLoadTLInterval; @Override protected void onCreate(Bundle savedInstanceState){ @@ -42,6 +49,7 @@ public void onCreate(Bundle savedInstanceState){ addPreferencesFromResource(R.xml.preference); CheckBoxPreference listAsTL = (CheckBoxPreference)findPreference("listAsTL"); + autoLoadTLInterval = findPreference("autoLoadTLInterval"); Preference listSetting = findPreference("listSetting"); Preference clearCache = findPreference("clearCache"); setCacheSize(clearCache); @@ -56,6 +64,15 @@ public boolean onPreferenceChange(Preference preference, Object newValue){ } }); + setAutoLoadTLIntervalSummary(app.getCurrentAccount().getAutoLoadTLInterval()); + autoLoadTLInterval.setOnPreferenceClickListener(new OnPreferenceClickListener(){ + @Override + public boolean onPreferenceClick(Preference preference){ + clickAutoLoadTLInterval(getActivity()); + return false; + } + }); + listSetting.setOnPreferenceClickListener(new OnPreferenceClickListener(){ @Override public boolean onPreferenceClick(Preference preference){ @@ -86,7 +103,10 @@ public boolean selectListAsTL(final Preference preference, boolean isCheck){ @Override public void onClick(DialogInterface dialog, int which){ dbutil.updateListAsTL(-1, app.getCurrentAccount().getScreenName()); + dbutil.updateAutoLoadTLInterval(0, app.getCurrentAccount().getScreenName()); preference.setSummary(null); + setAutoLoadTLIntervalSummary(0); + app.reloadAccountFromDB(); } }).setNegativeButton("Cancel", new OnClickListener(){ @Override @@ -126,6 +146,7 @@ public void onClick(DialogInterface dialog, int which){ long selectedListId = listMap.get(listNames[which]); dbutil.updateListAsTL(selectedListId, app.getCurrentAccount().getScreenName()); preference.setSummary(String.valueOf(selectedListId)); + app.reloadAccountFromDB(); } }).show(); } @@ -133,6 +154,43 @@ public void onClick(DialogInterface dialog, int which){ return true; } + public void clickAutoLoadTLInterval(final Context context){ + final EditText intervalEdit = new EditText(context); + intervalEdit.setInputType(InputType.TYPE_CLASS_NUMBER); + FrameLayout editContainer = new FrameLayout(context); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + int margin = Utils.convertDpToPx(context, 24); + params.leftMargin = margin; + params.rightMargin = margin; + intervalEdit.setLayoutParams(params); + editContainer.addView(intervalEdit); + + new AlertDialog.Builder(context) + .setMessage("自動で取得する間隔を秒で入力してください") + .setView(editContainer) + .setPositiveButton("OK", new OnClickListener(){ + @Override + public void onClick(DialogInterface dialog, int which){ + if(intervalEdit.getText().toString().isEmpty()){ + return; + } + boolean isListAsTL = app.getCurrentAccount().getListAsTL() > 0; + int interval = Integer.parseInt(intervalEdit.getText().toString()); + if(!isListAsTL && interval > 0 && interval < 60){ + new ShowToast(context, R.string.error_autoLoadTLInterval, Toast.LENGTH_LONG); + return; + } + new DBUtil(getApplicationContext()).updateAutoLoadTLInterval(interval, app.getCurrentAccount().getScreenName()); + setAutoLoadTLIntervalSummary(interval); + app.reloadAccountFromDB(); + } + }).show(); + } + + public void setAutoLoadTLIntervalSummary(int interval){ + autoLoadTLInterval.setSummary("設定値: " + interval + " (0: 無効)"); + } + public void setCacheSize(final Preference clearCache){ new AsyncTask(){ @Override @@ -165,7 +223,6 @@ public void onPause(){ public void onDestroy(){ super.onDestroy(); app.loadOption(); - app.reloadAccountFromDB(); } } diff --git a/src/sugtao4423/lod/dataclass/Account.java b/src/sugtao4423/lod/dataclass/Account.java index 797a370b..354bd836 100644 --- a/src/sugtao4423/lod/dataclass/Account.java +++ b/src/sugtao4423/lod/dataclass/Account.java @@ -8,25 +8,27 @@ public class Account{ private String accessToken; private String accessTokenSecret; private long listAsTL; + private int autoLoadTLInterval; private long[] selectListIds; private String[] selectListNames; private String[] startAppLoadLists; public Account(String screenName, String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret, - long listAsTL, long[] selectListIds, String[] selectListNames, String[] startAppLoadLists){ + long listAsTL, int autoLoadTLInterval, long[] selectListIds, String[] selectListNames, String[] startAppLoadLists){ this.screenName = screenName; this.consumerKey = consumerKey; this.consumerSecret = consumerSecret; this.accessToken = accessToken; this.accessTokenSecret = accessTokenSecret; this.listAsTL = listAsTL; + this.autoLoadTLInterval = autoLoadTLInterval; this.selectListIds = selectListIds; this.selectListNames = selectListNames; this.startAppLoadLists = startAppLoadLists; } public Account(String screenName, String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret){ - this(screenName, consumerKey, consumerSecret, accessToken, accessTokenSecret, -1L, new long[0], new String[0], new String[0]); + this(screenName, consumerKey, consumerSecret, accessToken, accessTokenSecret, -1L, 0, new long[0], new String[0], new String[0]); } public String getScreenName(){ @@ -53,6 +55,10 @@ public long getListAsTL(){ return listAsTL; } + public int getAutoLoadTLInterval(){ + return autoLoadTLInterval; + } + public long[] getSelectListIds(){ return selectListIds; } diff --git a/src/sugtao4423/lod/main_fragment/Fragment_home.java b/src/sugtao4423/lod/main_fragment/Fragment_home.java index 23fbfa4b..0057091f 100644 --- a/src/sugtao4423/lod/main_fragment/Fragment_home.java +++ b/src/sugtao4423/lod/main_fragment/Fragment_home.java @@ -100,10 +100,12 @@ protected void onPostExecute(ResponseList result){ public void addAll(ResponseList status){ adapter.addAll(status); + app.setLatestTweetId(status.get(0).getId()); } public void insert(Status status){ adapter.insertTop(status); + app.setLatestTweetId(status.getId()); handler.post(new Runnable(){ @Override diff --git a/src/sugtao4423/lod/utils/DBUtil.java b/src/sugtao4423/lod/utils/DBUtil.java index 693fda58..caac5f6e 100644 --- a/src/sugtao4423/lod/utils/DBUtil.java +++ b/src/sugtao4423/lod/utils/DBUtil.java @@ -47,9 +47,10 @@ private Account getAccount(Cursor c){ String at = c.getString(3); String ats = c.getString(4); long listAsTL = c.getLong(5); - String listIds = c.getString(6); - String listNames = c.getString(7); - String appLoadLists = c.getString(8); + int autoLoadTLInterval = c.getInt(6); + String listIds = c.getString(7); + String listNames = c.getString(8); + String appLoadLists = c.getString(9); long[] selectListIds; if(listIds.equals("")){ @@ -65,7 +66,7 @@ private Account getAccount(Cursor c){ String[] selectListNames = listNames.equals("") ? new String[0] : listNames.split(","); String[] startAppLoadLists = appLoadLists.equals("") ? new String[0] : appLoadLists.split(","); - return new Account(screen_name, ck, cs, at, ats, listAsTL, selectListIds, selectListNames, startAppLoadLists); + return new Account(screen_name, ck, cs, at, ats, listAsTL, autoLoadTLInterval, selectListIds, selectListNames, startAppLoadLists); } public boolean existsAccount(String screenName){ @@ -88,10 +89,10 @@ public void addAcount(Account account){ public void deleteAccount(Account account){ db.execSQL(String.format( "DELETE FROM accounts WHERE %s='%s' AND %s='%s' AND %s='%s' AND %s='%s' AND %s='%s' " - + "AND %s='%s' AND %s='%s' AND %s='%s' AND %s='%s'", + + "AND %s='%s' AND %s='%s' AND %s='%s' AND %s='%s' AND %s='%s'", Keys.SCREEN_NAME, account.getScreenName(), Keys.CK, account.getConsumerKey(), Keys.CS, account.getConsumerSecret(), Keys.ACCESS_TOKEN, account.getAccessToken(), Keys.ACCESS_TOKEN_SECRET, account.getAccessTokenSecret(), - Keys.LIST_AS_TIMELINE, account.getListAsTL(), + Keys.LIST_AS_TIMELINE, account.getListAsTL(), Keys.AUTO_LOAD_TL_INTERVAL, account.getAutoLoadTLInterval(), Keys.SELECT_LIST_IDS, Utils.implode(account.getSelectListIds()), Keys.SELECT_LIST_NAMES, Utils.implode(account.getSelectListNames()), Keys.APP_START_LOAD_LISTS, Utils.implode(account.getStartAppLoadLists()))); @@ -101,6 +102,10 @@ public void updateListAsTL(long listAsTL, String screenName){ db.execSQL(getUpdate1ColumnFromEq1Column(Keys.LIST_AS_TIMELINE, listAsTL, screenName)); } + public void updateAutoLoadTLInterval(int autoLoadTLInterval, String screenName){ + db.execSQL(getUpdate1ColumnFromEq1Column(Keys.AUTO_LOAD_TL_INTERVAL, autoLoadTLInterval, screenName)); + } + public void updateSelectListIds(String ids, String screenName){ db.execSQL(getUpdate1ColumnFromEq1Column(Keys.SELECT_LIST_IDS, ids, screenName)); }