1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2025-01-07 10:42:07 +00:00

Android TV: Handle DPAD input (fixes #194) (#223)

Android TV: Handle DPAD input too (fixes #194)
This commit is contained in:
Catfriend1 2019-01-16 09:24:48 +01:00 committed by GitHub
parent cfc1197987
commit 4487857785
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 206 additions and 30 deletions

View file

@ -68,4 +68,12 @@
<issue id="RelativeOverlap">
<ignore path="src/main/res/layout/activity_first_start.xml" />
</issue>
<!-- Ignore unused drawables -->
<issue id="UnusedResources" severity="ignore">
<ignore path="src/main/res/drawable-ldpi" />
<ignore path="src/main/res/drawable-hdpi" />
<ignore path="src/main/res/drawable-xhdpi" />
<ignore path="src/main/res/drawable-xxhdpi" />
<ignore path="src/main/res/drawable-xxxhdpi" />
</issue>
</lint>

View file

@ -133,6 +133,7 @@
android:value=".activities.MainActivity" />
</activity>
<activity android:name=".activities.SettingsActivity"
android:label="@string/settings_title"
android:parentActivityName=".activities.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"

View file

@ -3,14 +3,12 @@ package com.nutomic.syncthingandroid.activities;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.UiModeManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.Manifest;
import android.net.Uri;
@ -48,7 +46,7 @@ import java.lang.ref.WeakReference;
import javax.inject.Inject;
public class FirstStartActivity extends Activity {
public class FirstStartActivity extends AppCompatActivity {
private static String TAG = "FirstStartActivity";
private static final int REQUEST_COARSE_LOCATION = 141;
@ -97,7 +95,7 @@ public class FirstStartActivity extends Activity {
super.onCreate(savedInstanceState);
((SyncthingApp) getApplication()).component().inject(this);
mRunningOnTV = isRunningOnTV();
mRunningOnTV = Util.isRunningOnTV(this);
Log.d(TAG, mRunningOnTV ? "Running on a TV Device" : "Running on a non-TV Device");
/**
@ -489,6 +487,7 @@ public class FirstStartActivity extends Activity {
} else {
Toast.makeText(this, R.string.permission_granted, Toast.LENGTH_SHORT).show();
Log.i(TAG, "User granted ACCESS_COARSE_LOCATION permission.");
mNextButton.requestFocus();
}
break;
case REQUEST_WRITE_STORAGE:
@ -498,6 +497,7 @@ public class FirstStartActivity extends Activity {
} else {
Toast.makeText(this, R.string.permission_granted, Toast.LENGTH_SHORT).show();
Log.i(TAG, "User granted WRITE_EXTERNAL_STORAGE permission.");
mNextButton.requestFocus();
}
break;
default:
@ -570,11 +570,7 @@ public class FirstStartActivity extends Activity {
keygenStatus.setText(firstStartActivity.getString(R.string.key_generation_success));
Button nextButton = (Button) firstStartActivity.findViewById(R.id.btn_next);
nextButton.setVisibility(View.VISIBLE);
nextButton.requestFocus();
}
}
private Boolean isRunningOnTV() {
UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
}
}

View file

@ -77,6 +77,10 @@ public class MainActivity extends SyncthingActivity
private static final String QRCODE_BITMAP_KEY = "QRCODE_BITMAP";
private static final String DEVICEID_KEY = "DEVICEID";
private static final int FOLDER_FRAGMENT_ID = 0;
private static final int DEVICE_FRAGMENT_ID = 1;
private static final int STATUS_FRAGMENT_ID = 2;
/**
* Time after first start when usage reporting dialog should be shown.
*
@ -233,11 +237,11 @@ public class MainActivity extends SyncthingActivity
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
case FOLDER_FRAGMENT_ID:
return mFolderListFragment;
case 1:
case DEVICE_FRAGMENT_ID:
return mDeviceListFragment;
case 2:
case STATUS_FRAGMENT_ID:
return mStatusFragment;
default:
return null;
@ -257,11 +261,11 @@ public class MainActivity extends SyncthingActivity
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
case FOLDER_FRAGMENT_ID:
return getResources().getString(R.string.folders_fragment_title);
case 1:
case DEVICE_FRAGMENT_ID:
return getResources().getString(R.string.devices_fragment_title);
case 2:
case STATUS_FRAGMENT_ID:
return getResources().getString(R.string.status_fragment_title);
default:
return String.valueOf(position);
@ -453,7 +457,9 @@ public class MainActivity extends SyncthingActivity
} else {
closeDrawer();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
closeDrawer();
return true;
}
return super.onKeyDown(keyCode, e);

View file

@ -2,6 +2,7 @@ package com.nutomic.syncthingandroid.activities;
import android.Manifest;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
@ -22,8 +23,18 @@ import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.Toast;
@ -66,12 +77,13 @@ public class SettingsActivity extends SyncthingActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
mSettingsFragment = new SettingsFragment();
Bundle bundle = new Bundle();
bundle.putString(EXTRA_OPEN_SUB_PREF_SCREEN, getIntent().getStringExtra(EXTRA_OPEN_SUB_PREF_SCREEN));
mSettingsFragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, mSettingsFragment)
.replace(R.id.prefFragmentContainer, mSettingsFragment)
.commit();
}
@ -104,6 +116,15 @@ public class SettingsActivity extends SyncthingActivity {
syncthingService.registerOnServiceStateChangeListener(mSettingsFragment);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent e) {
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
finish();
return true;
}
return super.onKeyDown(keyCode, e);
}
public static class SettingsFragment extends PreferenceFragment
implements SyncthingService.OnServiceStateChangeListener,
Preference.OnPreferenceChangeListener,
@ -130,6 +151,8 @@ public class SettingsActivity extends SyncthingActivity {
@Inject NotificationHandler mNotificationHandler;
@Inject SharedPreferences mPreferences;
private Dialog mCurrentPrefScreenDialog = null;
private Preference mCategoryRunConditions;
private CheckBoxPreference mStartServiceOnBoot;
private ListPreference mPowerSource;
@ -184,6 +207,26 @@ public class SettingsActivity extends SyncthingActivity {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((SyncthingApp) getActivity().getApplication()).component().inject(this);
setHasOptionsMenu(true);
}
/**
* The ActionBar overlaps the preferences view.
* Move the preferences view below the ActionBar.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
int horizontalMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics());
int verticalMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics());
TypedValue tv = new TypedValue();
if (container.getContext().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
{
// Calculate ActionBar height
int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
view.setPadding(horizontalMargin, actionBarHeight, horizontalMargin, verticalMargin);
}
return view;
}
/**
@ -195,6 +238,7 @@ public class SettingsActivity extends SyncthingActivity {
public void onActivityCreated(Bundle savedInstanceState) {
mContext = getActivity().getApplicationContext();
super.onActivityCreated(savedInstanceState);
addPreferencesFromResource(R.xml.app_settings);
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
@ -212,9 +256,9 @@ public class SettingsActivity extends SyncthingActivity {
return false;
});
}
PreferenceScreen screen = getPreferenceScreen();
/* Run conditions */
PreferenceScreen screen = getPreferenceScreen();
mRunOnWifi =
(CheckBoxPreference) findPreference(Constants.PREF_RUN_ON_WIFI);
mRunOnMeteredWifi =
@ -349,6 +393,53 @@ public class SettingsActivity extends SyncthingActivity {
}
}
@SuppressWarnings("deprecation")
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
super.onPreferenceTreeClick(preferenceScreen, preference);
if (preference instanceof PreferenceScreen) {
// User has clicked on a sub-preferences screen.
try {
mCurrentPrefScreenDialog = ((PreferenceScreen) preference).getDialog();
LinearLayout root = (LinearLayout) mCurrentPrefScreenDialog.findViewById(android.R.id.list).getParent().getParent();
SyncthingActivity syncthingActivity = (SyncthingActivity) getActivity();
LayoutInflater layoutInflater = syncthingActivity.getLayoutInflater();
Toolbar toolbar = (Toolbar) layoutInflater.inflate(R.layout.widget_toolbar, root, false);
root.addView(toolbar, 0);
toolbar.setTitle(((PreferenceScreen) preference).getTitle());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setTouchscreenBlocksFocus(false);
}
syncthingActivity.setSupportActionBar(toolbar);
syncthingActivity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} catch (Exception e) {
/**
* The above code has been verified working but due to known bugs in the
* support library on different Android versions better be safe in case
* it breaks.
*/
Log.e(TAG, "onPreferenceTreeClick", e);
}
}
return false;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
if (mCurrentPrefScreenDialog == null) {
// User is on the top preferences screen.
getActivity().onBackPressed();
} else {
// User is on a sub-preferences screen.
mCurrentPrefScreenDialog.dismiss();
mCurrentPrefScreenDialog = null;
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void setService(SyncthingService syncthingService) {
mSyncthingService = syncthingService;
}

View file

@ -4,6 +4,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
@ -43,6 +44,9 @@ public abstract class SyncthingActivity extends AppCompatActivity implements Ser
return;
}
toolbar.setNavigationContentDescription(R.string.main_menu);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setTouchscreenBlocksFocus(false);
}
setSupportActionBar(toolbar);
//noinspection ConstantConditions

View file

@ -2,11 +2,13 @@ package com.nutomic.syncthingandroid.util;
import android.app.Activity;
import android.app.Dialog;
import android.app.UiModeManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils;
@ -329,4 +331,9 @@ public class Util {
}
return false;
}
public static Boolean isRunningOnTV(Context context) {
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:color="#1565C0" />
<item android:state_focused="true" android:state_pressed="true" android:color="#1565C0" />
<item android:state_focused="false" android:state_pressed="true" android:color="#000000" />
<item android:color="#000000" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 B

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 B

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 B

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 623 B

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 B

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,012 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 714 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 908 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/ic_device_add_black_24" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/ic_device_add_white_24" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/ic_device_add_white_24"/>
<item android:drawable="@drawable/ic_device_add_white_24" />
</selector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/ic_folder_add_black_24dp" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/ic_add_folder_24dp_white" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/ic_add_folder_24dp_white"/>
<item android:drawable="@drawable/ic_add_folder_24dp_white" />
</selector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/ic_syncthing_logo_black" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/ic_stat_notify" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/ic_stat_notify"/>
<item android:drawable="@drawable/ic_stat_notify" />
</selector>

View file

@ -39,20 +39,22 @@
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:background="@null"
android:text="@string/back"
android:textColor="@android:color/white"
android:visibility="gone" />
android:visibility="gone"
style="@style/Theme.Syncthing.GreyButton" />
<Button
android:id="@+id/btn_next"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="@null"
android:text="@string/cont"
android:textColor="@android:color/white" />
style="@style/Theme.Syncthing.GreyButton" >
<requestFocus />
</Button>
</RelativeLayout>

View file

@ -33,7 +33,7 @@
android:text="@string/ignore_doze_permission_title"
android:textColor="@android:color/white"
android:textSize="@dimen/slide_title"
android:textStyle="bold"/>
android:textStyle="bold" />
<ImageView
android:layout_width="58dp"
@ -55,7 +55,8 @@
android:paddingEnd="@dimen/grant_button_padding"
android:paddingRight="@dimen/grant_button_padding"
android:text="@string/grant_permission"
android:textSize="12sp" />
android:textSize="12sp"
style="@style/Theme.Syncthing.GreyButton" />
<TextView
android:id="@+id/tvIgnoreDozePermissionOsNotice"

View file

@ -66,7 +66,8 @@
android:paddingEnd="@dimen/grant_button_padding"
android:paddingRight="@dimen/grant_button_padding"
android:text="@string/grant_permission"
android:textSize="12sp"/>
android:textSize="12sp"
style="@style/Theme.Syncthing.GreyButton" />
</RelativeLayout>

View file

@ -54,7 +54,8 @@
android:paddingEnd="@dimen/grant_button_padding"
android:paddingRight="@dimen/grant_button_padding"
android:text="@string/grant_permission"
android:textSize="12sp" />
android:textSize="12sp"
style="@style/Theme.Syncthing.GreyButton" />
<TextView
android:layout_width="wrap_content"

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.nutomic.syncthingandroid.activities.SettingsActivity"
tools:showIn="@layout/activity_settings">
<include layout="@layout/widget_toolbar" />
<LinearLayout
android:id="@+id/prefFragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</RelativeLayout>

View file

@ -21,6 +21,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:focusable="false"
android:visibility="gone"
app:buttonTint="#76ff03"/>
@ -29,6 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:focusable="false"
android:visibility="gone"
app:buttonTint="#fff103"/>
@ -37,9 +39,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:focusable="false"
android:visibility="gone"
app:buttonTint="#ffae03"/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.v7.widget.Toolbar>

View file

@ -5,7 +5,7 @@
<item
android:id="@+id/add_device"
android:icon="@drawable/ic_add_white_24dp_active"
android:icon="@drawable/btn_add_device"
android:title="@string/add_device"
app:showAsAction="always|withText" />

View file

@ -5,7 +5,7 @@
<item
android:id="@+id/add_folder"
android:icon="@drawable/ic_add_white_24dp_active"
android:icon="@drawable/btn_add_folder"
android:title="@string/add_folder"
app:showAsAction="always|withText" />

View file

@ -33,6 +33,11 @@
<item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>
<!-- Button themes -->
<style name="Theme.Syncthing.GreyButton" parent="ThemeOverlay.AppCompat.Light">
<item name="android:textColor">@color/btn_welcome_slide_color</item>
</style>
<!-- Dialog themes -->
<eat-comment/>