Remove activity dependency on fragments

This commit is contained in:
emanuele-f 2021-02-07 12:44:40 +01:00
parent c389468037
commit b3f222cd3a
6 changed files with 76 additions and 128 deletions

View File

@ -19,9 +19,14 @@
package com.emanuelef.remote_capture;
interface AppStateListener {
void appStateReady();
void appStateStarting();
void appStateRunning();
void appStateStopping();
/* App state handling: ready -> starting -> running -> stopping -> ready */
enum AppState {
ready,
starting,
running,
stopping
}
interface AppStateListener {
void appStateChanged(AppState state);
}

View File

@ -364,4 +364,5 @@ public class CaptureService extends VpnService implements Runnable {
public static native void runPacketLoop(int fd, CaptureService vpn, int sdk);
public static native void stopPacketLoop();
public static native void askConnectionsDump();
}

View File

@ -39,20 +39,21 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
public class ConnectionsFragment extends Fragment {
private static final String TAG = "ConnectionsFragment";
private MainActivity activity;
private MainActivity mActivity;
private ConnectionsAdapter mAdapter;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
activity = (MainActivity) context;
mActivity = (MainActivity) context;
}
@Override
public void onDestroy() {
activity.setConnectionsFragment(null);
super.onDestroy();
mActivity = null;
}
@Override
@ -67,7 +68,7 @@ public class ConnectionsFragment extends Fragment {
TextView emptyText = view.findViewById(R.id.no_connections);
connList.setEmptyView(emptyText);
mAdapter = new ConnectionsAdapter(activity);
mAdapter = new ConnectionsAdapter(mActivity);
connList.setAdapter(mAdapter);
connList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
@ -76,7 +77,7 @@ public class ConnectionsFragment extends Fragment {
if(item != null) {
Intent intent = new Intent(getContext(), ConnectionDetails.class);
AppDescriptor app = activity.findAppByUid(item.uid);
AppDescriptor app = mActivity.findAppByUid(item.uid);
String app_name = null;//;1051
if(app != null)
@ -96,7 +97,7 @@ public class ConnectionsFragment extends Fragment {
}
});
LocalBroadcastManager bcast_man = LocalBroadcastManager.getInstance(activity);
LocalBroadcastManager bcast_man = LocalBroadcastManager.getInstance(mActivity);
/* Register for connections update */
bcast_man.registerReceiver(new BroadcastReceiver() {
@ -105,34 +106,13 @@ public class ConnectionsFragment extends Fragment {
processConnectionsDump(intent);
}
}, new IntentFilter(CaptureService.ACTION_CONNECTIONS_DUMP));
if(savedInstanceState != null) {
ConnDescriptor connections[] = (ConnDescriptor[]) savedInstanceState.getSerializable("connections");
if(connections != null) {
mAdapter.updateConnections(connections);
Log.d(TAG, "Restored " + connections.length + " connections");
}
}
/* Important: call this after all the fields have been initialized */
activity.setConnectionsFragment(this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
ConnDescriptor items[] = new ConnDescriptor[mAdapter.getCount()];
public void onResume() {
super.onResume();
for(int i = 0; i<items.length; i++) {
ConnDescriptor conn = mAdapter.getItem(i);
if(conn != null)
items[i] = conn;
}
outState.putSerializable("connections", items);
Log.d(TAG, "Saved " + items.length + " connections");
CaptureService.askConnectionsDump();
}
private void processConnectionsDump(Intent intent) {

View File

@ -57,7 +57,7 @@ import java.util.List;
import cat.ereza.customactivityoncrash.config.CaocConfig;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<AppDescriptor>>, AppStateListener {
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<AppDescriptor>> {
SharedPreferences mPrefs;
Menu mMenu;
Drawable mFilterIcon;
@ -65,10 +65,9 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
boolean mOpenAppsWhenDone;
List<AppDescriptor> mInstalledApps;
AppState mState;
StatusFragment mStatusFragment;
ConnectionsFragment mConnectionsFragment;
ViewPager2 viewPager2;
TabLayout tabLayout;
AppStateListener mStateListener;
private final static int POS_STATUS = 0;
private final static int POS_CONNECTIONS = 1;
private final static int TOTAL_COUNT = 2;
@ -81,14 +80,6 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
public static final String GITHUB_PROJECT_URL = "https://github.com/emanuele-f/PCAPdroid";
public static final String GITHUB_DOCS_URL = "https://emanuele-f.github.io/PCAPdroid";
/* App state handling: ready -> starting -> running -> stopping -> ready */
enum AppState {
ready,
starting,
running,
stopping
}
private static class MainStateAdapter extends FragmentStateAdapter {
MainStateAdapter(final FragmentActivity fa) {
super(fa);
@ -119,8 +110,7 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
mFilterApp = CaptureService.getAppFilter();
mOpenAppsWhenDone = false;
mInstalledApps = null;
mStatusFragment = null;
mConnectionsFragment = null;
mStateListener = null;
CaocConfig.Builder.create()
.errorDrawable(R.drawable.ic_app_crash)
@ -148,10 +138,6 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
if (savedInstanceState != null) {
mConnectionsFragment = (ConnectionsFragment) getSupportFragmentManager().getFragment(savedInstanceState, "ConnectionsFragment");
}
startLoadingApps();
LocalBroadcastManager bcast_man = LocalBroadcastManager.getInstance(this);
@ -173,53 +159,38 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
}, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(mConnectionsFragment != null)
getSupportFragmentManager().putFragment(outState, "ConnectionsFragment", mConnectionsFragment);
}
@Override
public void appStateReady() {
mState = AppState.ready;
if (mStatusFragment != null)
mStatusFragment.appStateReady();
mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(true);
if(mStateListener != null)
mStateListener.appStateChanged(AppState.ready);
}
@Override
public void appStateStarting() {
mState = AppState.starting;
if (mStatusFragment != null)
mStatusFragment.appStateStarting();
mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(false);
if(mStateListener != null)
mStateListener.appStateChanged(AppState.starting);
}
@Override
public void appStateRunning() {
mState = AppState.running;
mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(false);
if (mStatusFragment != null)
mStatusFragment.appStateRunning();
if (mConnectionsFragment != null)
mConnectionsFragment.reset();
if(mStateListener != null)
mStateListener.appStateChanged(AppState.running);
}
@Override
public void appStateStopping() {
mState = AppState.stopping;
if (mStatusFragment != null)
mStatusFragment.appStateStopping();
if(mStateListener != null)
mStateListener.appStateChanged(AppState.stopping);
mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(false);
}
@ -231,7 +202,7 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
mMenu = menu;
mFilterIcon = mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).getIcon();
recheckFragments();
initAppState();
return true;
}
@ -379,8 +350,7 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
return (null);
}
/* Try to determine the current app state */
private void setAppState() {
private void initAppState() {
boolean is_active = CaptureService.isServiceActive();
if (!is_active)
@ -419,22 +389,8 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
}
}
void setStatusFragment(StatusFragment screen) {
mStatusFragment = screen;
recheckFragments();
}
void setConnectionsFragment(ConnectionsFragment view) {
mConnectionsFragment = view;
recheckFragments();
}
private void recheckFragments() {
/* Must wait for the fragments to properly update them */
if((mStatusFragment != null) && (mConnectionsFragment != null) && (mMenu != null)) {
// Possibly set an initial app state
setAppState();
}
void setAppStateListener(AppStateListener listener) {
mStateListener = listener;
}
AppState getState() {

View File

@ -58,7 +58,7 @@ public class StatusFragment extends Fragment implements AppStateListener {
@Override
public void onDestroy() {
mActivity.setStatusFragment(null);
mActivity.setAppStateListener(null);
mActivity = null;
super.onDestroy();
}
@ -101,7 +101,7 @@ public class StatusFragment extends Fragment implements AppStateListener {
mPrefs.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
if((mActivity != null) && (mActivity.getState() == MainActivity.AppState.ready))
if((mActivity != null) && (mActivity.getState() == AppState.ready))
refreshPcapDumpInfo();
}
});
@ -125,35 +125,7 @@ public class StatusFragment extends Fragment implements AppStateListener {
}, new IntentFilter(CaptureService.ACTION_TRAFFIC_STATS_UPDATE));
/* Important: call this after all the fields have been initialized */
mActivity.setStatusFragment(this);
}
@Override
public void appStateReady() {
mStartButton.setText(R.string.start_button);
mStartButton.setEnabled(true);
mCaptureStatus.setText(R.string.ready);
refreshPcapDumpInfo();
}
@Override
public void appStateStarting() {
mStartButton.setEnabled(false);
}
@Override
public void appStateRunning() {
mStartButton.setText(R.string.stop_button);
mStartButton.setEnabled(true);
mCaptureStatus.setText(Utils.formatBytes(CaptureService.getBytes()));
refreshPcapDumpInfo();
}
@Override
public void appStateStopping() {
mStartButton.setEnabled(false);
mActivity.setAppStateListener(this);
}
private void processStatsUpdateIntent(Intent intent) {
@ -203,4 +175,30 @@ public class StatusFragment extends Fragment implements AppStateListener {
mCollectorInfo.setText(info);
}
@Override
public void appStateChanged(AppState state) {
switch(state) {
case starting:
mStartButton.setEnabled(false);
break;
case stopping:
mStartButton.setEnabled(false);
break;
case ready:
mStartButton.setText(R.string.start_button);
mStartButton.setEnabled(true);
mCaptureStatus.setText(R.string.ready);
refreshPcapDumpInfo();
break;
case running:
mStartButton.setText(R.string.stop_button);
mStartButton.setEnabled(true);
mCaptureStatus.setText(Utils.formatBytes(CaptureService.getBytes()));
refreshPcapDumpInfo();
break;
}
}
}

View File

@ -79,6 +79,7 @@ typedef struct jni_classes {
static jni_classes_t cls;
static jni_methods_t mids;
static bool running = false;
static bool dump_connections_now = false;
/* TCP/IP packet to hold the mitmproxy header */
static char mitmproxy_pkt_buffer[] = {
@ -1000,7 +1001,8 @@ housekeeping:
sendCaptureStats(&proxy);
proxy.capture_stats.new_stats = false;
proxy.capture_stats.last_update_ms = now_ms;
} else if((now_ms - last_connections_dump) >= CONNECTION_DUMP_UPDATE_FREQUENCY_MS) {
} else if(((now_ms - last_connections_dump) >= CONNECTION_DUMP_UPDATE_FREQUENCY_MS) || dump_connections_now) {
dump_connections_now = false;
sendConnectionsDump(tun, &proxy);
last_connections_dump = now_ms;
} else if((proxy.java_dump.buffer_idx > 0)
@ -1065,3 +1067,9 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl
run_tun(env, vpn, tapfd, sdk);
close(tapfd);
}
JNIEXPORT void JNICALL
Java_com_emanuelef_remote_1capture_CaptureService_askConnectionsDump(JNIEnv *env, jclass clazz) {
if(running)
dump_connections_now = true;
}