diff --git a/app/build.gradle b/app/build.gradle index 14e078e7..30cd1a9d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "jp.juggler.subwaytooter" minSdkVersion 21 targetSdkVersion 25 - versionCode 98 - versionName "0.9.8" + versionCode 99 + versionName "0.9.9" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.java b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.java index 1844cc92..4ec1b65f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.java @@ -5,11 +5,11 @@ import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.media.RingtoneManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.Nullable; -import android.support.v4.os.AsyncTaskCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; @@ -67,10 +67,25 @@ public class ActAccountSetting extends AppCompatActivity } static final int REQUEST_CODE_ACCT_CUSTOMIZE = 1; + static final int REQUEST_CODE_NOTIFICATION_SOUND = 2; @Override protected void onActivityResult( int requestCode, int resultCode, Intent data ){ if( requestCode == REQUEST_CODE_ACCT_CUSTOMIZE && resultCode == RESULT_OK ){ showAcctColor(); + }else if( resultCode == RESULT_OK && requestCode == REQUEST_CODE_NOTIFICATION_SOUND ){ + // RINGTONE_PICKERからの選択されたデータを取得する + Uri uri = (Uri) data.getExtras().get( RingtoneManager.EXTRA_RINGTONE_PICKED_URI ); + if( uri != null ){ + notification_sound_uri = uri.toString(); + saveUIToData(); + // Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), uri); + // TextView ringView = (TextView) findViewById(R.id.ringtone); + // ringView.setText(ringtone.getTitle(getApplicationContext())); + // ringtone.setStreamType(AudioManager.STREAM_ALARM); + // ringtone.play(); + // SystemClock.sleep(1000); + // ringtone.stop(); + } } super.onActivityResult( requestCode, resultCode, data ); } @@ -97,6 +112,11 @@ public class ActAccountSetting extends AppCompatActivity View btnUserCustom; String full_acct; + Button btnNotificationSoundEdit; + Button btnNotificationSoundReset; + + String notification_sound_uri; + private void initUI(){ setContentView( R.layout.act_account_setting ); @@ -140,6 +160,11 @@ public class ActAccountSetting extends AppCompatActivity cbConfirmUnfollow.setOnCheckedChangeListener( this ); cbConfirmBoost.setOnCheckedChangeListener( this ); cbConfirmToot.setOnCheckedChangeListener( this ); + + btnNotificationSoundEdit = (Button) findViewById( R.id.btnNotificationSoundEdit ); + btnNotificationSoundReset = (Button) findViewById( R.id.btnNotificationSoundReset ); + btnNotificationSoundEdit.setOnClickListener( this ); + btnNotificationSoundReset.setOnClickListener( this ); } boolean loading = false; @@ -169,11 +194,17 @@ public class ActAccountSetting extends AppCompatActivity cbConfirmBoost.setChecked( a.confirm_boost ); cbConfirmToot.setChecked( a.confirm_post ); + notification_sound_uri = a.sound_uri; + loading = false; boolean enabled = ! a.isPseudo(); btnAccessToken.setEnabled( enabled ); btnVisibility.setEnabled( enabled ); + btnVisibility.setEnabled( enabled ); + btnVisibility.setEnabled( enabled ); + btnNotificationSoundEdit.setEnabled( enabled ); + btnNotificationSoundReset.setEnabled( enabled ); cbNotificationMention.setEnabled( enabled ); cbNotificationBoost.setEnabled( enabled ); @@ -206,6 +237,8 @@ public class ActAccountSetting extends AppCompatActivity account.notification_favourite = cbNotificationFavourite.isChecked(); account.notification_follow = cbNotificationFollow.isChecked(); + account.sound_uri = notification_sound_uri == null ? "" : notification_sound_uri; + account.confirm_follow = cbConfirmFollow.isChecked(); account.confirm_follow_locked = cbConfirmFollowLockedUser.isChecked(); account.confirm_unfollow = cbConfirmUnfollow.isChecked(); @@ -237,7 +270,15 @@ public class ActAccountSetting extends AppCompatActivity case R.id.btnUserCustom: ActNickname.open( this, full_acct, REQUEST_CODE_ACCT_CUSTOMIZE ); break; - + + case R.id.btnNotificationSoundEdit: + openNotificationSoundPicker(); + break; + + case R.id.btnNotificationSoundReset: + notification_sound_uri = ""; + saveUIToData(); + break; } } @@ -439,5 +480,23 @@ public class ActAccountSetting extends AppCompatActivity task.executeOnExecutor( App1.task_executor ); } + private void openNotificationSoundPicker(){ + Intent intent = new Intent( RingtoneManager.ACTION_RINGTONE_PICKER ); + intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION ); + intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TITLE, R.string.notification_sound ); + intent.putExtra( RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false ); + intent.putExtra( RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false ); + try{ + Uri uri = TextUtils.isEmpty( notification_sound_uri ) ? null : Uri.parse( notification_sound_uri ); + if( uri != null ){ + intent.putExtra( RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, uri ); + } + }catch( Throwable ignored ){ + } + + Intent chooser = Intent.createChooser( intent, getString( R.string.notification_sound ) ); + startActivityForResult( chooser, REQUEST_CODE_NOTIFICATION_SOUND ); + } + } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.java b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.java index 7c697061..d4005eca 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAppSetting.java @@ -40,9 +40,11 @@ import org.apache.commons.io.output.FileWriterWithEncoding; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Locale; import jp.juggler.subwaytooter.table.AcctColor; import jp.juggler.subwaytooter.table.SavedAccount; @@ -127,10 +129,17 @@ public class ActAppSetting extends AppCompatActivity EditText etMediaThumbHeight; EditText etClientName; - TextView tvTimelineFontUrl; String timeline_font; + EditText etTimelineFontSize; + EditText etAcctFontSize; + TextView tvTimelineFontSize; + TextView tvAcctFontSize; + + static final float default_timeline_font_size = 14f; + static final float default_acct_font_size = 12f; + private void initUI(){ setContentView( R.layout.act_app_setting ); @@ -178,7 +187,6 @@ public class ActAppSetting extends AppCompatActivity swPostButtonBarTop = (Switch) findViewById( R.id.swPostButtonBarTop ); swPostButtonBarTop.setOnCheckedChangeListener( this ); - cbNotificationSound = (CheckBox) findViewById( R.id.cbNotificationSound ); cbNotificationVibration = (CheckBox) findViewById( R.id.cbNotificationVibration ); cbNotificationLED = (CheckBox) findViewById( R.id.cbNotificationLED ); @@ -277,13 +285,22 @@ public class ActAppSetting extends AppCompatActivity etColumnWidth = (EditText) findViewById( R.id.etColumnWidth ); etColumnWidth.addTextChangedListener( this ); - + etMediaThumbHeight = (EditText) findViewById( R.id.etMediaThumbHeight ); etMediaThumbHeight.addTextChangedListener( this ); - + etClientName = (EditText) findViewById( R.id.etClientName ); etClientName.addTextChangedListener( this ); - + + tvTimelineFontSize = (TextView) findViewById( R.id.tvTimelineFontSize ); + tvAcctFontSize = (TextView) findViewById( R.id.tvAcctFontSize ); + + etTimelineFontSize = (EditText) findViewById( R.id.etTimelineFontSize ); + etTimelineFontSize.addTextChangedListener( new SizeCheckTextWatcher( tvTimelineFontSize, etTimelineFontSize, default_timeline_font_size ) ); + + etAcctFontSize = (EditText) findViewById( R.id.etAcctFontSize ); + etAcctFontSize.addTextChangedListener( new SizeCheckTextWatcher( tvAcctFontSize, etAcctFontSize, default_acct_font_size ) ); + tvTimelineFontUrl = (TextView) findViewById( R.id.tvTimelineFontUrl ); } @@ -332,12 +349,19 @@ public class ActAppSetting extends AppCompatActivity etColumnWidth.setText( pref.getString( Pref.KEY_COLUMN_WIDTH, "" ) ); etMediaThumbHeight.setText( pref.getString( Pref.KEY_MEDIA_THUMB_HEIGHT, "" ) ); etClientName.setText( pref.getString( Pref.KEY_CLIENT_NAME, "" ) ); + + etTimelineFontSize.setText( formatFontSize( pref.getFloat( Pref.KEY_TIMELINE_FONT_SIZE, Float.NaN ) ) ); + etAcctFontSize.setText( formatFontSize( pref.getFloat( Pref.KEY_ACCT_FONT_SIZE, Float.NaN ) ) ); + timeline_font = pref.getString( Pref.KEY_TIMELINE_FONT, "" ); load_busy = false; showFooterColor(); showTimelineFont(); + + showFontSize( tvTimelineFontSize, etTimelineFontSize, default_timeline_font_size ); + showFontSize( tvAcctFontSize, etAcctFontSize, default_acct_font_size ); } private void saveUIToData(){ @@ -357,7 +381,7 @@ public class ActAppSetting extends AppCompatActivity .putBoolean( Pref.KEY_DONT_CROP_MEDIA_THUMBNAIL, swDontCropMediaThumb.isChecked() ) .putBoolean( Pref.KEY_PRIOR_CHROME, swPriorChrome.isChecked() ) .putBoolean( Pref.KEY_POST_BUTTON_BAR_AT_TOP, swPostButtonBarTop.isChecked() ) - + .putBoolean( Pref.KEY_NOTIFICATION_SOUND, cbNotificationSound.isChecked() ) .putBoolean( Pref.KEY_NOTIFICATION_VIBRATION, cbNotificationVibration.isChecked() ) .putBoolean( Pref.KEY_NOTIFICATION_LED, cbNotificationLED.isChecked() ) @@ -380,7 +404,9 @@ public class ActAppSetting extends AppCompatActivity .putString( Pref.KEY_COLUMN_WIDTH, etColumnWidth.getText().toString().trim() ) .putString( Pref.KEY_MEDIA_THUMB_HEIGHT, etMediaThumbHeight.getText().toString().trim() ) .putString( Pref.KEY_CLIENT_NAME, etClientName.getText().toString().trim() ) - + .putFloat( Pref.KEY_TIMELINE_FONT_SIZE, parseFontSize( etTimelineFontSize.getText().toString().trim() ) ) + .putFloat( Pref.KEY_ACCT_FONT_SIZE, parseFontSize( etAcctFontSize.getText().toString().trim() ) ) + .apply(); } @@ -496,6 +522,7 @@ public class ActAppSetting extends AppCompatActivity AlarmService.startCheck( this ); Utils.showToast( this, false, getString( R.string.custom_stream_listener_was_reset ) ); break; + } } @@ -631,6 +658,65 @@ public class ActAppSetting extends AppCompatActivity saveUIToData(); } + private class SizeCheckTextWatcher implements TextWatcher { + TextView sample; + EditText et; + float default_size_sp; + + SizeCheckTextWatcher( TextView sample, EditText et, float default_size_sp ){ + this.sample = sample; + this.et = et; + this.default_size_sp = default_size_sp; + } + + @Override public void beforeTextChanged( CharSequence s, int start, int count, int after ){ + + } + + @Override public void onTextChanged( CharSequence s, int start, int before, int count ){ + + } + + @Override public void afterTextChanged( Editable s ){ + saveUIToData(); + showFontSize( sample, et, default_size_sp ); + } + } + + private String formatFontSize( float fv ){ + if( Float.isNaN( fv ) ){ + return ""; + }else{ + return String.format( Locale.getDefault(), "%.1f", fv ); + } + } + + private float parseFontSize( String src ){ + try{ + NumberFormat format = NumberFormat.getInstance( Locale.getDefault() ); + Number number = format.parse( src ); + float f = number.floatValue(); + if( ! Float.isNaN( f ) ){ + if( f < 0f ) f = 0f; + if( f > 999f ) f = 999f; + return f; + } + }catch( Throwable ex ){ + ex.printStackTrace(); + } + return Float.NaN; + } + + private void showFontSize( TextView sample, EditText et, float default_sp ){ + float fv = parseFontSize( et.getText().toString().trim() ); + if( Float.isNaN( fv ) ){ + sample.setTextSize( default_sp ); + }else{ + if( fv < 1f ) fv = 1f; + sample.setTextSize( fv ); + } + } + private void showTimelineFont(){ try{ if( ! TextUtils.isEmpty( timeline_font ) ){ diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.java b/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.java index 53c44112..c8317298 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActColumnCustomize.java @@ -225,7 +225,7 @@ public class ActColumnCustomize extends AppCompatActivity if( ! fromUser ) return; column.column_bg_image_alpha = progress / (float) PROGRESS_MAX; ivColumnBackground.setAlpha( column.column_bg_image_alpha ); - etAlpha.setText( String.format( Locale.JAPAN, "%.4f", column.column_bg_image_alpha ) ); + etAlpha.setText( String.format( Locale.getDefault() , "%.4f", column.column_bg_image_alpha ) ); } } ); diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActMain.java b/app/src/main/java/jp/juggler/subwaytooter/ActMain.java index fb4fc740..0d5ccfd4 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActMain.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ActMain.java @@ -105,6 +105,15 @@ public class ActMain extends AppCompatActivity String posted_acct; long posted_status_id; + float timeline_font_size_sp = Float.NaN; + float acct_font_size_sp = Float.NaN; + + float validateFloat( float fv){ + if( Float.isNaN( fv ) ) return fv; + if( fv < 1f ) fv = 1f; + return fv; + } + @Override protected void onCreate( Bundle savedInstanceState ){ log.d( "onCreate" ); super.onCreate( savedInstanceState ); @@ -118,6 +127,9 @@ public class ActMain extends AppCompatActivity this.density = app_state.density; this.acct_pad_lr = (int) ( 0.5f + 4f * density ); + timeline_font_size_sp = validateFloat( pref.getFloat( Pref.KEY_TIMELINE_FONT_SIZE, Float.NaN ) ); + acct_font_size_sp = validateFloat( pref.getFloat( Pref.KEY_ACCT_FONT_SIZE, Float.NaN ) ); + initUI(); updateColumnStrip(); @@ -3755,12 +3767,12 @@ public class ActMain extends AppCompatActivity } public void openTimelineFor( @NonNull String host ){ - final ArrayList< SavedAccount > account_list = new ArrayList<>( ); + final ArrayList< SavedAccount > account_list = new ArrayList<>(); for( SavedAccount a : SavedAccount.loadAccountList( log ) ){ if( host.equalsIgnoreCase( a.host ) ) account_list.add( a ); } if( account_list.isEmpty() ){ - + SavedAccount ai = addPseudoAccount( host ); if( ai != null ){ addColumn( getDefaultInsertPosition(), ai, Column.TYPE_LOCAL ); @@ -3768,7 +3780,7 @@ public class ActMain extends AppCompatActivity }else{ AccountPicker.pick( this, false, false - , getString( R.string.account_picker_add_timeline_of ,host ) + , getString( R.string.account_picker_add_timeline_of, host ) , account_list, new AccountPicker.AccountPickerCallback() { @Override public void onAccountPicked( @NonNull SavedAccount ai ){ addColumn( getDefaultInsertPosition(), ai, Column.TYPE_LOCAL ); diff --git a/app/src/main/java/jp/juggler/subwaytooter/AlarmService.java b/app/src/main/java/jp/juggler/subwaytooter/AlarmService.java index f1686792..8c520e3e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/AlarmService.java +++ b/app/src/main/java/jp/juggler/subwaytooter/AlarmService.java @@ -7,6 +7,8 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.media.Ringtone; +import android.media.RingtoneManager; import android.net.Uri; import android.os.PowerManager; import android.os.SystemClock; @@ -24,6 +26,7 @@ import org.hjson.JsonValue; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -106,7 +109,6 @@ public class AlarmService extends IntentService { Intent next_intent = new Intent( this, AlarmReceiver.class ); pi_next = PendingIntent.getBroadcast( this, PENDING_CODE_ALARM, next_intent, PendingIntent.FLAG_UPDATE_CURRENT ); - } @Override public void onDestroy(){ @@ -121,16 +123,16 @@ public class AlarmService extends IntentService { String mCustomStreamListenerSecret; String mCustomStreamListenerSettingString; JsonObject mCustomStreamListenerSetting; - - void loadCustomStreamListenerSetting( ){ + + void loadCustomStreamListenerSetting(){ mCustomStreamListenerSetting = null; mCustomStreamListenerSecret = null; - mCustomStreamListenerSettingString = pref.getString(Pref.KEY_STREAM_LISTENER_CONFIG_DATA ,null); - if(! TextUtils.isEmpty( mCustomStreamListenerSettingString ) ){ + mCustomStreamListenerSettingString = pref.getString( Pref.KEY_STREAM_LISTENER_CONFIG_DATA, null ); + if( ! TextUtils.isEmpty( mCustomStreamListenerSettingString ) ){ try{ mCustomStreamListenerSetting = JsonValue.readHjson( mCustomStreamListenerSettingString ).asObject(); - mCustomStreamListenerSecret = pref.getString(Pref.KEY_STREAM_LISTENER_SECRET ,null); - }catch(Throwable ex){ + mCustomStreamListenerSecret = pref.getString( Pref.KEY_STREAM_LISTENER_SECRET, null ); + }catch( Throwable ex ){ ex.printStackTrace(); } } @@ -139,7 +141,7 @@ public class AlarmService extends IntentService { // IntentService は onHandleIntent をワーカースレッドから呼び出す // 同期処理を行って良い @Override protected void onHandleIntent( @Nullable Intent intent ){ - bStreamListenerTest =false; + bStreamListenerTest = false; // クラッシュレポートによると App1.onCreate より前にここを通る場合がある // データベースへアクセスできるようにする @@ -184,16 +186,16 @@ public class AlarmService extends IntentService { // アプリサーバへの登録をやり直す }else if( ACTION_RESET_LAST_LOAD.equals( action ) ){ boolean bDone = false; - String tag = intent.getStringExtra(EXTRA_TAG); + String tag = intent.getStringExtra( EXTRA_TAG ); if( tag != null ){ - for(SavedAccount sa : SavedAccount.loadByTag(log,tag )){ + for( SavedAccount sa : SavedAccount.loadByTag( log, tag ) ){ bDone = true; - NotificationTracking.resetLastLoad( sa.db_id); + NotificationTracking.resetLastLoad( sa.db_id ); } } - if(!bDone){ + if( ! bDone ){ // タグにマッチする情報がなかった場合、全部読み直す - NotificationTracking.resetLastLoad( ); + NotificationTracking.resetLastLoad(); } }else if( ACTION_DATA_DELETED.equals( action ) ){ deleteCacheData( intent.getLongExtra( EXTRA_DB_ID, - 1L ) ); @@ -281,7 +283,7 @@ public class AlarmService extends IntentService { ArrayList< Data > data_list = new ArrayList<>(); checkAccount( client, data_list, account, muted_app, muted_word ); - showNotification( account.db_id, data_list ); + showNotification( account, data_list ); }catch( Throwable ex ){ ex.printStackTrace(); @@ -317,9 +319,8 @@ public class AlarmService extends IntentService { String getInstallId(){ SharedPreferences prefDevice = PrefDevice.prefDevice( this ); - - String sv = prefDevice.getString(PrefDevice.KEY_INSTALL_ID,null); + String sv = prefDevice.getString( PrefDevice.KEY_INSTALL_ID, null ); if( ! TextUtils.isEmpty( sv ) ) return sv; // インストールIDを生成する前に、各データの通知登録キャッシュをクリアする @@ -332,13 +333,13 @@ public class AlarmService extends IntentService { // トークンがまだ生成されていない場合、このメソッドは null を返します。 device_token = FirebaseInstanceId.getInstance().getToken(); if( TextUtils.isEmpty( device_token ) ){ - log.e("getInstallId: missing device token."); + log.e( "getInstallId: missing device token." ); return null; }else{ prefDevice.edit().putString( PrefDevice.KEY_DEVICE_TOKEN, device_token ).apply(); } - }catch(Throwable ex2){ - log.e("getInstallId: could not get device token."); + }catch( Throwable ex2 ){ + log.e( "getInstallId: could not get device token." ); ex2.printStackTrace(); return null; } @@ -353,13 +354,13 @@ public class AlarmService extends IntentService { Response response = call.execute(); if( ! response.isSuccessful() ){ - log.e("getInstallId: get /counter failed. %s",response); + log.e( "getInstallId: get /counter failed. %s", response ); return null; } //noinspection ConstantConditions sv = Utils.digestSHA256( device_token + UUID.randomUUID() + response.body().string() ); - prefDevice.edit().putString(PrefDevice.KEY_INSTALL_ID, sv).apply(); + prefDevice.edit().putString( PrefDevice.KEY_INSTALL_ID, sv ).apply(); return sv; @@ -369,24 +370,22 @@ public class AlarmService extends IntentService { } } - - private void unregisterDeviceToken( @NonNull SavedAccount account ){ try{ if( SavedAccount.REGISTER_KEY_UNREGISTERED.equals( account.register_key ) ){ - log.d("unregisterDeviceToken: already unregistered."); + log.d( "unregisterDeviceToken: already unregistered." ); return; } - + // ネットワーク的な事情でインストールIDを取得できなかったのなら、何もしない if( TextUtils.isEmpty( install_id ) ){ - log.d("unregisterDeviceToken: missing install_id"); + log.d( "unregisterDeviceToken: missing install_id" ); return; } String tag = account.notification_tag; if( TextUtils.isEmpty( tag ) ){ - log.d("unregisterDeviceToken: missing notification_tag"); + log.d( "unregisterDeviceToken: missing notification_tag" ); return; } @@ -410,7 +409,7 @@ public class AlarmService extends IntentService { account.register_time = 0L; account.saveRegisterKey(); } - + }catch( Throwable ex ){ ex.printStackTrace(); } @@ -421,7 +420,7 @@ public class AlarmService extends IntentService { try{ // ネットワーク的な事情でインストールIDを取得できなかったのなら、何もしない if( TextUtils.isEmpty( install_id ) ){ - log.d("registerDeviceToken: missing install id"); + log.d( "registerDeviceToken: missing install id" ); return false; } @@ -429,18 +428,18 @@ public class AlarmService extends IntentService { String device_token = prefDevice.getString( PrefDevice.KEY_DEVICE_TOKEN, null ); if( TextUtils.isEmpty( device_token ) ){ - log.d("registerDeviceToken: missing device_token"); + log.d( "registerDeviceToken: missing device_token" ); return false; } String access_token = Utils.optStringX( account.token_info, "access_token" ); if( TextUtils.isEmpty( access_token ) ){ - log.d("registerDeviceToken: missing access_token"); + log.d( "registerDeviceToken: missing access_token" ); return false; } String tag = account.notification_tag; - + if( SavedAccount.REGISTER_KEY_UNREGISTERED.equals( account.register_key ) ){ tag = null; } @@ -452,36 +451,36 @@ public class AlarmService extends IntentService { String reg_key = Utils.digestSHA256( tag - + access_token - + device_token - + (mCustomStreamListenerSecret==null? "" :mCustomStreamListenerSecret) - + (mCustomStreamListenerSettingString==null? "" :mCustomStreamListenerSettingString) + + access_token + + device_token + + ( mCustomStreamListenerSecret == null ? "" : mCustomStreamListenerSecret ) + + ( mCustomStreamListenerSettingString == null ? "" : mCustomStreamListenerSettingString ) ); long now = System.currentTimeMillis(); if( reg_key.equals( account.register_key ) && now - account.register_time < 3600000 * 3 ){ // タグやトークンが同一なら、前回登録に成功してから一定時間は再登録しない - log.d("registerDeviceToken: already registered."); + log.d( "registerDeviceToken: already registered." ); return false; } - + // サーバ情報APIを使う - StringBuilder post_data = new StringBuilder( ); - - post_data.append("instance_url=").append(Uri.encode( "https://" + account.host )); - - post_data.append("&app_id=").append(Uri.encode( getPackageName() )); - - post_data.append("&tag=").append(tag); - - post_data.append("&access_token=").append(Utils.optStringX( account.token_info, "access_token" )); - - post_data.append("&device_token=").append(device_token); - + StringBuilder post_data = new StringBuilder(); + + post_data.append( "instance_url=" ).append( Uri.encode( "https://" + account.host ) ); + + post_data.append( "&app_id=" ).append( Uri.encode( getPackageName() ) ); + + post_data.append( "&tag=" ).append( tag ); + + post_data.append( "&access_token=" ).append( Utils.optStringX( account.token_info, "access_token" ) ); + + post_data.append( "&device_token=" ).append( device_token ); + if( ! TextUtils.isEmpty( mCustomStreamListenerSettingString ) - && ! TextUtils.isEmpty( mCustomStreamListenerSecret ) + && ! TextUtils.isEmpty( mCustomStreamListenerSecret ) ){ - post_data.append("&user_config=").append(Uri.encode(mCustomStreamListenerSettingString)); - post_data.append("&app_secret=").append(Uri.encode(mCustomStreamListenerSecret)); + post_data.append( "&user_config=" ).append( Uri.encode( mCustomStreamListenerSettingString ) ); + post_data.append( "&app_secret=" ).append( Uri.encode( mCustomStreamListenerSecret ) ); } Request request = new Request.Builder() @@ -489,21 +488,21 @@ public class AlarmService extends IntentService { .post( RequestBody.create( TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, post_data.toString() ) ) .build(); - Call call = App1.ok_http_client.newCall( request ); + Call call = App1.ok_http_client.newCall( request ); Response response = call.execute(); - String body=null; + String body = null; try{ //noinspection ConstantConditions - body =response.body().string(); - }catch(Throwable ignored){ + body = response.body().string(); + }catch( Throwable ignored ){ } - log.e( "registerDeviceToken: %s (%s)",response,(body==null?"":body) ); - + log.e( "registerDeviceToken: %s (%s)", response, ( body == null ? "" : body ) ); + int code = response.code(); - - if( response.isSuccessful() || (code >= 400 && code < 500) ){ + + if( response.isSuccessful() || ( code >= 400 && code < 500 ) ){ // 登録できた時も4xxエラーだった時もDBに記録する account.register_key = reg_key; account.register_time = now; @@ -632,7 +631,7 @@ public class AlarmService extends IntentService { return; } - TootNotification notification = TootNotification.parse( log, account,account.host ,src ); + TootNotification notification = TootNotification.parse( log, account, account.host, src ); if( notification == null ){ return; } @@ -672,8 +671,8 @@ public class AlarmService extends IntentService { return "- " + "?"; } - private void showNotification( long account_db_id, @NonNull ArrayList< Data > data_list ){ - String notification_tag = Long.toString( account_db_id ); + private void showNotification( @NonNull SavedAccount account, @NonNull ArrayList< Data > data_list ){ + String notification_tag = Long.toString( account.db_id ); if( data_list.isEmpty() ){ notification_manager.cancel( notification_tag, NOTIFICATION_ID ); return; @@ -691,7 +690,7 @@ public class AlarmService extends IntentService { } ); Data item = data_list.get( 0 ); - NotificationTracking nt = NotificationTracking.load( account_db_id ); + NotificationTracking nt = NotificationTracking.load( account.db_id ); if( item.notification.time_created_at == nt.post_time && item.notification.id == nt.post_id ){ @@ -703,21 +702,39 @@ public class AlarmService extends IntentService { // 通知タップ Intent intent_click = new Intent( this, AlarmReceiver.class ); - intent_click.putExtra( EXTRA_DB_ID, account_db_id ); + intent_click.putExtra( EXTRA_DB_ID, account.db_id ); intent_click.setAction( ACTION_NOTIFICATION_CLICK ); Intent intent_delete = new Intent( this, AlarmReceiver.class ); - intent_click.putExtra( EXTRA_DB_ID, account_db_id ); + intent_click.putExtra( EXTRA_DB_ID, account.db_id ); intent_delete.setAction( ACTION_NOTIFICATION_DELETE ); - PendingIntent pi_click = PendingIntent.getBroadcast( this, ( 256 + (int) account_db_id ), intent_click, PendingIntent.FLAG_UPDATE_CURRENT ); + PendingIntent pi_click = PendingIntent.getBroadcast( this, ( 256 + (int) account.db_id ), intent_click, PendingIntent.FLAG_UPDATE_CURRENT ); // 通知を消去した時のPendingIntent - PendingIntent pi_delete = PendingIntent.getBroadcast( this, ( Integer.MAX_VALUE - (int) account_db_id ), intent_delete, PendingIntent.FLAG_UPDATE_CURRENT ); + PendingIntent pi_delete = PendingIntent.getBroadcast( this, ( Integer.MAX_VALUE - (int) account.db_id ), intent_delete, PendingIntent.FLAG_UPDATE_CURRENT ); + + NotificationCompat.Builder builder = new NotificationCompat.Builder( this ) + .setContentIntent( pi_click ) + .setDeleteIntent( pi_delete ) + .setAutoCancel( false ) + .setSmallIcon( R.drawable.ic_notification ) // ここは常に白テーマのアイコンを使う + .setColor( ContextCompat.getColor( this, R.color.Light_colorAccent ) ) // ここは常に白テーマの色を使う + .setWhen( item.notification.time_created_at ); int iv = 0; if( pref.getBoolean( Pref.KEY_NOTIFICATION_SOUND, true ) ){ - iv |= NotificationCompat.DEFAULT_SOUND; + Uri sound_uri = null; + try{ + String sv = account.sound_uri; + sound_uri = TextUtils.isEmpty( sv ) ? null : Uri.parse( sv ); + }catch( Throwable ignored ){ + } + if( sound_uri != null ){ + builder.setSound( sound_uri ); + }else{ + iv |= NotificationCompat.DEFAULT_SOUND; + } } if( pref.getBoolean( Pref.KEY_NOTIFICATION_VIBRATION, true ) ){ iv |= NotificationCompat.DEFAULT_VIBRATE; @@ -726,15 +743,7 @@ public class AlarmService extends IntentService { if( pref.getBoolean( Pref.KEY_NOTIFICATION_LED, true ) ){ iv |= NotificationCompat.DEFAULT_LIGHTS; } - - NotificationCompat.Builder builder = new NotificationCompat.Builder( this ) - .setContentIntent( pi_click ) - .setDeleteIntent( pi_delete ) - .setAutoCancel( false ) - .setSmallIcon( R.drawable.ic_notification ) // ここは常に白テーマのアイコンを使う - .setColor( ContextCompat.getColor( this, R.color.Light_colorAccent ) ) // ここは常に白テーマの色を使う - .setDefaults( iv ) - .setWhen( item.notification.time_created_at ); + builder.setDefaults( iv ); String a = getNotificationLine( item.notification.type, item.notification.account.display_name ); String acct = item.access_info.acct + " " + getString( R.string.app_name ); @@ -772,11 +781,10 @@ public class AlarmService extends IntentService { public static void onFirebaseMessage( @NonNull Context context, @Nullable String tag ){ Intent intent = new Intent( context, AlarmService.class ); intent.setAction( ACTION_RESET_LAST_LOAD ); - if(tag !=null) intent.putExtra( EXTRA_TAG,tag ); + if( tag != null ) intent.putExtra( EXTRA_TAG, tag ); context.startService( intent ); } - private static class InjectData { long account_db_id; TootNotification.List list = new TootNotification.List(); diff --git a/app/src/main/java/jp/juggler/subwaytooter/App1.java b/app/src/main/java/jp/juggler/subwaytooter/App1.java index f0c38d59..a75788b3 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/App1.java +++ b/app/src/main/java/jp/juggler/subwaytooter/App1.java @@ -51,7 +51,7 @@ public class App1 extends Application { static final LogCategory log = new LogCategory( "App1" ); static final String DB_NAME = "app_db"; - static final int DB_VERSION = 15; + static final int DB_VERSION = 16; public static final String FILE_PROVIDER_AUTHORITY = "jp.juggler.subwaytooter.FileProvider"; // 2017/4/25 v10 1=>2 SavedAccount に通知設定を追加 // 2017/4/25 v10 1=>2 NotificationTracking テーブルを追加 @@ -66,6 +66,7 @@ public class App1 extends Application { // 2017/5/23 v68 12=>13 SavedAccountに項目追加 // 2017/5/25 v69 13=>14 SavedAccountに項目追加 // 2017/5/27 v73 14=>15 TagSetテーブルの追加 + // 2017/7/22 v99 15=>16 SavedAccountに項目追加 private static DBOpenHelper db_open_helper; diff --git a/app/src/main/java/jp/juggler/subwaytooter/AppDataExporter.java b/app/src/main/java/jp/juggler/subwaytooter/AppDataExporter.java index 957ed6a9..4acf716f 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/AppDataExporter.java +++ b/app/src/main/java/jp/juggler/subwaytooter/AppDataExporter.java @@ -334,6 +334,13 @@ public class AppDataExporter { e.putString( k, sv ); break; + // double + case Pref.KEY_TIMELINE_FONT_SIZE: + case Pref.KEY_ACCT_FONT_SIZE: + double dv = reader.nextDouble(); + e.putFloat( k, (float)dv ); + break; + // force reset default: case Pref.KEY_TIMELINE_FONT: diff --git a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java index bcfb9d3d..055deb65 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java +++ b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.java @@ -67,7 +67,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener { private final MyTextView tvContent; private final View flMedia; - private final View btnShowMedia; + private final TextView btnShowMedia; private final MyNetworkImageView ivMedia1; private final MyNetworkImageView ivMedia2; @@ -150,7 +150,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener { this.buttons_for_status = bSimpleList ? null : new StatusButtons( activity, column, view, false ); this.flMedia = view.findViewById( R.id.flMedia ); - this.btnShowMedia = view.findViewById( R.id.btnShowMedia ); + this.btnShowMedia = (TextView) view.findViewById( R.id.btnShowMedia ); this.ivMedia1 = (MyNetworkImageView) view.findViewById( R.id.ivMedia1 ); this.ivMedia2 = (MyNetworkImageView) view.findViewById( R.id.ivMedia2 ); this.ivMedia3 = (MyNetworkImageView) view.findViewById( R.id.ivMedia3 ); @@ -191,6 +191,26 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener { ViewGroup.LayoutParams lp = flMedia.getLayoutParams(); lp.height = activity.app_state.media_thumb_height; + + if( ! Float.isNaN( activity.timeline_font_size_sp ) ){ + tvBoosted.setTextSize( activity.timeline_font_size_sp ); + tvFollowerName.setTextSize( activity.timeline_font_size_sp ); + tvName.setTextSize( activity.timeline_font_size_sp ); + tvMentions.setTextSize( activity.timeline_font_size_sp ); + tvContentWarning.setTextSize( activity.timeline_font_size_sp ); + tvContent.setTextSize( activity.timeline_font_size_sp ); + btnShowMedia.setTextSize( activity.timeline_font_size_sp ); + tvApplication.setTextSize( activity.timeline_font_size_sp ); + + } + + if( ! Float.isNaN( activity.acct_font_size_sp ) ){ + tvBoostedAcct.setTextSize( activity.acct_font_size_sp ); + tvBoostedTime.setTextSize( activity.acct_font_size_sp ); + tvFollowerAcct.setTextSize( activity.acct_font_size_sp ); + tvAcct.setTextSize( activity.acct_font_size_sp ); + tvTime.setTextSize( activity.acct_font_size_sp ); + } } void bind( Object item ){ @@ -343,6 +363,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener { , access_info.supplyBaseUrl( status.account.avatar ) ); } + tvContent.setText( status.decoded_content ); // if( status.decoded_tags == null ){ diff --git a/app/src/main/java/jp/juggler/subwaytooter/Pref.java b/app/src/main/java/jp/juggler/subwaytooter/Pref.java index 5de56693..528c954d 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Pref.java +++ b/app/src/main/java/jp/juggler/subwaytooter/Pref.java @@ -65,5 +65,8 @@ public class Pref { static final String KEY_LAST_COLUMN_POS = "last_column_pos"; + public static final String KEY_TIMELINE_FONT_SIZE = "timeline_font_size"; + public static final String KEY_ACCT_FONT_SIZE = "acct_font_size"; + // 項目を追加したらAppDataExporter#importPref のswitch文も更新すること } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.java b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.java index 98845416..51d7207b 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.java +++ b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.java @@ -52,6 +52,10 @@ public class SavedAccount extends TootAccount implements LinkClickContext { public static final String COL_REGISTER_KEY = "register_key"; public static final String COL_REGISTER_TIME = "register_time"; + // スキーマ16から + public static final String COL_SOUND_URI = "sound_uri"; + + public static final long INVALID_ID = - 1L; // login information @@ -66,6 +70,7 @@ public class SavedAccount extends TootAccount implements LinkClickContext { public boolean notification_boost; public boolean notification_favourite; public boolean notification_follow; + @NonNull public String sound_uri =""; public boolean confirm_follow; public boolean confirm_follow_locked; @@ -116,6 +121,9 @@ public class SavedAccount extends TootAccount implements LinkClickContext { + "," + COL_REGISTER_KEY + " text default ''" + "," + COL_REGISTER_TIME + " integer default 0" + // 以下はDBスキーマ16で更新 + + "," + COL_SOUND_URI + " text default ''" + + ")" ); @@ -187,6 +195,13 @@ public class SavedAccount extends TootAccount implements LinkClickContext { ex.printStackTrace(); } } + if( oldVersion < 16 && newVersion >= 16 ){ + try{ + db.execSQL( "alter table " + table + " add column " + COL_SOUND_URI + " text default ''" ); + }catch( Throwable ex ){ + ex.printStackTrace(); + } + } } private SavedAccount(){ @@ -250,6 +265,8 @@ public class SavedAccount extends TootAccount implements LinkClickContext { dst.register_time = cursor.getLong( cursor.getColumnIndex( COL_REGISTER_TIME )); dst.token_info = new JSONObject( cursor.getString( cursor.getColumnIndex( COL_TOKEN ) ) ); + + dst.sound_uri = cursor.getString( cursor.getColumnIndex( COL_SOUND_URI ) ); } return dst; } @@ -308,6 +325,8 @@ public class SavedAccount extends TootAccount implements LinkClickContext { cv.put( COL_CONFIRM_UNFOLLOW, confirm_unfollow ? 1 : 0 ); cv.put( COL_CONFIRM_POST, confirm_post ? 1 : 0 ); + cv.put( COL_SOUND_URI, sound_uri ); + // UIからは更新しない // notification_tag // register_key @@ -360,6 +379,8 @@ public class SavedAccount extends TootAccount implements LinkClickContext { this.notification_favourite = b.notification_favourite; this.notification_follow = b.notification_follow; this.notification_tag = b.notification_tag; + + this.sound_uri = b.sound_uri; } public static @Nullable SavedAccount loadAccount( @NonNull LogCategory log, long db_id ){ diff --git a/app/src/main/res/layout/act_account_setting.xml b/app/src/main/res/layout/act_account_setting.xml index f4c61586..d172bc83 100644 --- a/app/src/main/res/layout/act_account_setting.xml +++ b/app/src/main/res/layout/act_account_setting.xml @@ -262,6 +262,35 @@ /> + + + + + + +