diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/AppDetailsActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/AppDetailsActivity.java index 247fc3d6..e9104831 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/AppDetailsActivity.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/AppDetailsActivity.java @@ -21,6 +21,8 @@ package com.emanuelef.remote_capture.activities; import android.content.Intent; import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; @@ -28,11 +30,13 @@ import androidx.fragment.app.FragmentActivity; import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.viewpager2.widget.ViewPager2; +import com.emanuelef.remote_capture.Log; import com.emanuelef.remote_capture.R; import com.emanuelef.remote_capture.Utils; import com.emanuelef.remote_capture.fragments.AppOverview; import com.emanuelef.remote_capture.fragments.ConnectionsFragment; import com.emanuelef.remote_capture.model.FilterDescriptor; +import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; public class AppDetailsActivity extends BaseActivity { @@ -112,4 +116,34 @@ public class AppDetailsActivity extends BaseActivity { tab.setText(getString(pageAdapter.getPageTitle(position))) ).attach(); } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // This is required to properly handle the DPAD down press on Android TV, to properly + // focus the tab content + if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + View view = getCurrentFocus(); + + Log.d(TAG, "onKeyDown focus " + view.getClass().getName()); + + if (view instanceof TabLayout.TabView) { + int pos = mPager.getCurrentItem(); + View focusOverride = null; + + Log.d(TAG, "TabLayout.TabView focus pos " + pos); + + if (pos == POS_OVERVIEW) + focusOverride = findViewById(R.id.app_overview); + else if (pos == POS_CONNECTIONS) + focusOverride = findViewById(R.id.connections); + + if (focusOverride != null) { + focusOverride.requestFocus(); + return true; + } + } + } + + return super.onKeyDown(keyCode, event); + } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/ConnectionDetailsActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/ConnectionDetailsActivity.java index 34705e9d..f62cbdfc 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/ConnectionDetailsActivity.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/ConnectionDetailsActivity.java @@ -29,6 +29,8 @@ import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.view.KeyEvent; +import android.view.View; import com.emanuelef.remote_capture.CaptureService; import com.emanuelef.remote_capture.ConnectionsRegister; @@ -39,6 +41,7 @@ import com.emanuelef.remote_capture.fragments.ConnectionPayload; import com.emanuelef.remote_capture.interfaces.ConnectionsListener; import com.emanuelef.remote_capture.model.ConnectionDescriptor; import com.emanuelef.remote_capture.model.PayloadChunk; +import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; import java.util.ArrayList; @@ -296,4 +299,34 @@ public class ConnectionDetailsActivity extends BaseActivity implements Connectio if(mConn.status >= ConnectionDescriptor.CONN_STATUS_CLOSED) unregisterConnsListener(); } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // This is required to properly handle the DPAD down press on Android TV, to properly + // focus the tab content + if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + View view = getCurrentFocus(); + + Log.d(TAG, "onKeyDown focus " + view.getClass().getName()); + + if (view instanceof TabLayout.TabView) { + int pos = mPager.getCurrentItem(); + View focusOverride = null; + + Log.d(TAG, "TabLayout.TabView focus pos " + pos); + + if (pos == POS_OVERVIEW) + focusOverride = findViewById(R.id.connection_overview); + else + focusOverride = findViewById(R.id.payload); + + if (focusOverride != null) { + focusOverride.requestFocus(); + return true; + } + } + } + + return super.onKeyDown(keyCode, event); + } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/FirewallActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/FirewallActivity.java index 76ea2cd5..923cf0c0 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/FirewallActivity.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/FirewallActivity.java @@ -22,6 +22,8 @@ package com.emanuelef.remote_capture.activities; import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; @@ -36,6 +38,7 @@ import com.emanuelef.remote_capture.fragments.EditListFragment; import com.emanuelef.remote_capture.fragments.FirewallStatus; import com.emanuelef.remote_capture.model.ListInfo; import com.emanuelef.remote_capture.model.Prefs; +import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; public class FirewallActivity extends BaseActivity { @@ -118,4 +121,34 @@ public class FirewallActivity extends BaseActivity { // TODO fix DPAD navigation on Android TV, see MainActivity.onKeyDown } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // This is required to properly handle the DPAD down press on Android TV, to properly + // focus the tab content + if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + View view = getCurrentFocus(); + + Log.d(TAG, "onKeyDown focus " + view.getClass().getName()); + + if (view instanceof TabLayout.TabView) { + int pos = mPager.getCurrentItem(); + View focusOverride = null; + + Log.d(TAG, "TabLayout.TabView focus pos " + pos); + + if (pos == POS_STATUS) + focusOverride = findViewById(R.id.firewall_status); + else if ((pos == POS_BLOCKLIST) || (pos == POS_WHITELIST)) + focusOverride = findViewById(R.id.listview); + + if (focusOverride != null) { + focusOverride.requestFocus(); + return true; + } + } + } + + return super.onKeyDown(keyCode, event); + } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/MalwareDetection.java b/app/src/main/java/com/emanuelef/remote_capture/activities/MalwareDetection.java index e8120bee..af39069c 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/MalwareDetection.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/MalwareDetection.java @@ -20,6 +20,8 @@ package com.emanuelef.remote_capture.activities; import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; @@ -33,6 +35,7 @@ import com.emanuelef.remote_capture.fragments.EditListFragment; import com.emanuelef.remote_capture.fragments.BlacklistsFragment; import com.emanuelef.remote_capture.fragments.MalwareStatusFragment; import com.emanuelef.remote_capture.model.ListInfo; +import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; public class MalwareDetection extends BaseActivity { @@ -99,4 +102,34 @@ public class MalwareDetection extends BaseActivity { // TODO fix DPAD navigation on Android TV, see MainActivity.onKeyDown } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // This is required to properly handle the DPAD down press on Android TV, to properly + // focus the tab content + if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + View view = getCurrentFocus(); + + Log.d(TAG, "onKeyDown focus " + view.getClass().getName()); + + if (view instanceof TabLayout.TabView) { + int pos = mPager.getCurrentItem(); + View focusOverride = null; + + Log.d(TAG, "TabLayout.TabView focus pos " + pos); + + if (pos == POS_STATUS) + focusOverride = findViewById(R.id.mw_detection_status); + else if ((pos == POS_BLACKLISTS) || (pos == POS_WHITELIST)) + focusOverride = findViewById(R.id.listview); + + if (focusOverride != null) { + focusOverride.requestFocus(); + return true; + } + } + } + + return super.onKeyDown(keyCode, event); + } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/adapters/BlacklistsAdapter.java b/app/src/main/java/com/emanuelef/remote_capture/adapters/BlacklistsAdapter.java index 275da77d..96ad298d 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/adapters/BlacklistsAdapter.java +++ b/app/src/main/java/com/emanuelef/remote_capture/adapters/BlacklistsAdapter.java @@ -62,7 +62,6 @@ public class BlacklistsAdapter extends ArrayAdapter { TextView label = convertView.findViewById(R.id.label); label.setText(bl.label); - label.setOnClickListener(v -> openUrl(ctx, bl.url)); TextView status = convertView.findViewById(R.id.status); status.setText(bl.getStatusLabel(ctx)); @@ -75,9 +74,4 @@ public class BlacklistsAdapter extends ArrayAdapter { return convertView; } - - private void openUrl(Context ctx, String url) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - Utils.startActivity(ctx, intent); - } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/BlacklistsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/BlacklistsFragment.java index e8641406..c7207f03 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/BlacklistsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/BlacklistsFragment.java @@ -19,6 +19,9 @@ package com.emanuelef.remote_capture.fragments; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -40,9 +43,11 @@ import com.emanuelef.remote_capture.CaptureService; import com.emanuelef.remote_capture.Log; import com.emanuelef.remote_capture.PCAPdroid; import com.emanuelef.remote_capture.R; +import com.emanuelef.remote_capture.Utils; import com.emanuelef.remote_capture.adapters.BlacklistsAdapter; import com.emanuelef.remote_capture.interfaces.BlacklistsStateListener; import com.emanuelef.remote_capture.Blacklists; +import com.emanuelef.remote_capture.model.BlacklistDescriptor; public class BlacklistsFragment extends Fragment implements BlacklistsStateListener, MenuProvider { private static final String TAG = "BlacklistsFragment"; @@ -65,11 +70,22 @@ public class BlacklistsFragment extends Fragment implements BlacklistsStateListe ListView listView = view.findViewById(R.id.listview); listView.setAdapter(mAdapter); + listView.setOnItemClickListener((parent, view1, position, id) -> { + BlacklistDescriptor bl = mAdapter.getItem(position); + if (bl != null) + openUrl(view1.getContext(), bl.url); + }); + mHandler = new Handler(Looper.getMainLooper()); CaptureService.observeStatus(this, serviceStatus -> refreshStatus()); } + private void openUrl(Context ctx, String url) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + Utils.startActivity(ctx, intent); + } + @Override public void onResume() { super.onResume(); diff --git a/app/src/main/res/layout/app_overview.xml b/app/src/main/res/layout/app_overview.xml index 0974e3ef..1e49b84c 100644 --- a/app/src/main/res/layout/app_overview.xml +++ b/app/src/main/res/layout/app_overview.xml @@ -2,12 +2,14 @@ diff --git a/app/src/main/res/layout/blacklist_item.xml b/app/src/main/res/layout/blacklist_item.xml index 98c7a39c..b6cdb8b4 100644 --- a/app/src/main/res/layout/blacklist_item.xml +++ b/app/src/main/res/layout/blacklist_item.xml @@ -1,9 +1,11 @@ - @@ -20,10 +22,8 @@ android:textSize="17sp" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:drawableRight="@drawable/ic_external" + app:drawableEndCompat="@drawable/ic_external" android:drawablePadding="5dp" - android:clickable="true" - android:focusable="true" tools:text="Blacklist Name" /> diff --git a/app/src/main/res/layout/firewall_status.xml b/app/src/main/res/layout/firewall_status.xml index 753c4b8f..f06a1401 100644 --- a/app/src/main/res/layout/firewall_status.xml +++ b/app/src/main/res/layout/firewall_status.xml @@ -1,5 +1,6 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/malware_detection_status.xml b/app/src/main/res/layout/malware_detection_status.xml index b33f666c..1cb8f1e9 100644 --- a/app/src/main/res/layout/malware_detection_status.xml +++ b/app/src/main/res/layout/malware_detection_status.xml @@ -1,5 +1,6 @@ + app:tint="@color/colorTabText" /> diff --git a/app/src/main/res/layout/scrollable_dialog.xml b/app/src/main/res/layout/scrollable_dialog.xml index ab2fc8bd..617e2464 100644 --- a/app/src/main/res/layout/scrollable_dialog.xml +++ b/app/src/main/res/layout/scrollable_dialog.xml @@ -1,8 +1,6 @@ \ No newline at end of file diff --git a/app/src/main/res/layout/simple_list.xml b/app/src/main/res/layout/simple_list.xml index 0677d81e..142cccb7 100644 --- a/app/src/main/res/layout/simple_list.xml +++ b/app/src/main/res/layout/simple_list.xml @@ -7,6 +7,7 @@ android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent" + android:descendantFocusability="afterDescendants" android:scrollbarStyle="outsideOverlay" />