Fix Android TV navigation

Fixed views:
- Build info
- Firewall status
- Malware detection status
- Connection payload navigation
- App details

Fixes #295
This commit is contained in:
emanuele-f 2023-02-09 10:46:03 +01:00
parent 26f53c03a9
commit 5f94fb47a6
16 changed files with 168 additions and 19 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -62,7 +62,6 @@ public class BlacklistsAdapter extends ArrayAdapter<BlacklistDescriptor> {
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<BlacklistDescriptor> {
return convertView;
}
private void openUrl(Context ctx, String url) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
Utils.startActivity(ctx, intent);
}
}

View File

@ -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();

View File

@ -2,12 +2,14 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/app_overview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:padding="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:descendantFocusability="blocksDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content">

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:descendantFocusability="blocksDescendants"
android:paddingHorizontal="5dp"
android:paddingVertical="5dp">
@ -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" />
<TextView

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/connection_overview"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"

View File

@ -2,6 +2,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/connections"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/firewall_status"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@ -27,6 +28,7 @@
tools:text="@string/firewall_is_enabled" />
<ScrollView
android:id="@+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="30dp"
@ -37,6 +39,7 @@
android:columnCount="2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:useDefaultMargins="true">
<com.google.android.material.card.MaterialCardView

View File

@ -45,10 +45,5 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/adContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/mw_detection_status"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@ -36,6 +37,7 @@
android:columnCount="2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:useDefaultMargins="true">
<com.google.android.material.card.MaterialCardView

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:focusableInTouchMode="true"
android:nextFocusDown="@id/expand_button"
android:paddingHorizontal="3sp">
<LinearLayout
@ -70,5 +72,5 @@
android:layout_marginEnd="4dp"
android:adjustViewBounds="true"
android:src="@drawable/ic_expand_more"
android:tint="@color/colorTabText" />
app:tint="@color/colorTabText" />
</LinearLayout>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:padding="8dp"
android:paddingTop="12dp"
android:layout_width="match_parent"
@ -12,5 +10,6 @@
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:textIsSelectable="true" />
</ScrollView>

View File

@ -7,6 +7,7 @@
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="afterDescendants"
android:scrollbarStyle="outsideOverlay" />
<TextView