Remove deprecated LocalBroadcastManager

Replaced with LiveData

Closes #187
This commit is contained in:
emanuele-f 2022-08-17 01:08:23 +02:00
parent e9fed41efb
commit e687380850
8 changed files with 98 additions and 245 deletions

View File

@ -39,7 +39,6 @@ import android.net.NetworkRequest;
import android.net.Uri;
import android.net.VpnService;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
@ -54,7 +53,9 @@ import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.preference.PreferenceManager;
import com.emanuelef.remote_capture.activities.CaptureCtrl;
@ -148,7 +149,8 @@ public class CaptureService extends VpnService implements Runnable {
private String mSocks5Address;
private int mSocks5Port;
private String mSocks5Auth;
private CaptureStats mLastStats;
private static final MutableLiveData<CaptureStats> lastStats = new MutableLiveData<>();
private static final MutableLiveData<ServiceStatus> serviceStatus = new MutableLiveData<>();
private boolean mLowMemory;
private BroadcastReceiver mNewAppsInstallReceiver;
@ -168,11 +170,10 @@ public class CaptureService extends VpnService implements Runnable {
* After the analysis, requests will be routed to the primary DNS server. */
public static final String VPN_VIRTUAL_DNS_SERVER = "10.215.173.2";
public static final String ACTION_STATS_DUMP = "stats_dump";
public static final String ACTION_SERVICE_STATUS = "service_status";
public static final String SERVICE_STATUS_KEY = "status";
public static final String SERVICE_STATUS_STARTED = "started";
public static final String SERVICE_STATUS_STOPPED = "stopped";
public enum ServiceStatus {
STOPPED,
STARTED
}
static {
/* Load native library */
@ -202,7 +203,7 @@ public class CaptureService extends VpnService implements Runnable {
private int abortStart() {
stopService();
sendServiceStatus(SERVICE_STATUS_STOPPED);
updateServiceStatus(ServiceStatus.STOPPED);
return START_NOT_STICKY;
}
@ -1039,7 +1040,7 @@ public class CaptureService extends VpnService implements Runnable {
// Notify
mHandler.post(() -> {
sendServiceStatus(SERVICE_STATUS_STOPPED);
updateServiceStatus(ServiceStatus.STOPPED);
CaptureCtrl.notifyCaptureStopped(this, getStats());
});
}
@ -1273,29 +1274,28 @@ public class CaptureService extends VpnService implements Runnable {
}
}
// called from native
public void sendStatsDump(CaptureStats stats) {
//Log.d(TAG, "sendStatsDump");
mLastStats = stats;
Bundle bundle = new Bundle();
bundle.putSerializable("value", stats);
Intent intent = new Intent(ACTION_STATS_DUMP);
intent.putExtras(bundle);
last_bytes = stats.bytes_sent + stats.bytes_rcvd;
last_connections = stats.tot_conns;
mHandler.post(this::updateNotification);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
// notify the observers
lastStats.postValue(stats);
}
// also called from native
// called from native
private void sendServiceStatus(String cur_status) {
Intent intent = new Intent(ACTION_SERVICE_STATUS);
intent.putExtra(SERVICE_STATUS_KEY, cur_status);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
updateServiceStatus(cur_status.equals("started") ? ServiceStatus.STARTED : ServiceStatus.STOPPED);
}
if(cur_status.equals(SERVICE_STATUS_STARTED)) {
private void updateServiceStatus(ServiceStatus cur_status) {
// notify the observers
serviceStatus.postValue(cur_status);
if(cur_status == ServiceStatus.STARTED) {
if(mMalwareDetectionEnabled)
reloadMalwareWhitelist();
reloadBlocklist();
@ -1391,10 +1391,18 @@ public class CaptureService extends VpnService implements Runnable {
}
public static @NonNull CaptureStats getStats() {
CaptureStats stats = (INSTANCE != null) ? INSTANCE.mLastStats : null;
CaptureStats stats = lastStats.getValue();
return((stats != null) ? stats : new CaptureStats());
}
public static void observeStats(LifecycleOwner lifecycleOwner, Observer<CaptureStats> observer) {
lastStats.observe(lifecycleOwner, observer);
}
public static void observeStatus(LifecycleOwner lifecycleOwner, Observer<ServiceStatus> observer) {
serviceStatus.observe(lifecycleOwner, observer);
}
public static void waitForCaptureStop() {
if(INSTANCE == null)
return;

View File

@ -20,17 +20,16 @@
package com.emanuelef.remote_capture;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.util.Log;
import android.util.LruCache;
import android.util.SparseArray;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import com.emanuelef.remote_capture.interfaces.ConnectionsListener;
import com.emanuelef.remote_capture.interfaces.MitmListener;
@ -67,15 +66,14 @@ import java.util.StringTokenizer;
public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener {
private static final String TAG = "MitmReceiver";
public static final int TLS_DECRYPTION_PROXY_PORT = 7780;
public static final String ACTION_MITM_ADDON_STATUS_CHANGED = "addon_status_changed";
private Thread mThread;
private final ConnectionsRegister mReg;
private final Context mContext;
private final MitmAddon mAddon;
private final MitmAPI.MitmConfig mConfig;
private static final MutableLiveData<Boolean> proxyRunning = new MutableLiveData<>();
private ParcelFileDescriptor mSocketFd;
private BufferedOutputStream mKeylog;
private boolean mProxyRunning;
// Shared state
private final LruCache<Integer, Integer> mPortToConnId = new LruCache<>(64);
@ -140,7 +138,7 @@ public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener
public boolean start() throws IOException {
Log.d(TAG, "starting");
mProxyRunning = false;
proxyRunning.postValue(false);
if(!mAddon.connect(Context.BIND_IMPORTANT)) {
Utils.showToastLong(mContext, R.string.mitm_start_failed);
@ -182,7 +180,7 @@ public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener
public void run() {
if(mSocketFd == null) {
Log.d(TAG, "Null socket, abort");
mProxyRunning = false;
proxyRunning.postValue(false);
return;
}
@ -237,9 +235,10 @@ public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener
if(type == MsgType.MASTER_SECRET)
logMasterSecret(msg);
else if(type == MsgType.RUNNING)
handleProxyRunning();
else {
else if(type == MsgType.RUNNING) {
Log.d(TAG, "MITM proxy is running");
proxyRunning.postValue(true);
} else {
ConnectionDescriptor conn = getConnByLocalPort(port);
//Log.d(TAG, "MSG." + type.name() + "[" + msg_len + " B]: port=" + port + ", match=" + (conn != null));
@ -258,7 +257,7 @@ public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener
mKeylog = null;
}
mProxyRunning = false;
proxyRunning.postValue(false);
Log.d(TAG, "End receiving data");
}
@ -286,17 +285,6 @@ public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener
}
}
private void handleProxyRunning() {
Log.d(TAG, "MITM proxy is running");
mProxyRunning = true;
// Notify the StatusFragment
new Handler(Looper.getMainLooper()).post(() -> {
Intent intent = new Intent(ACTION_MITM_ADDON_STATUS_CHANGED);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
});
}
private void handleMessage(ConnectionDescriptor conn, MsgType type, byte[] message, long tstamp) {
// NOTE: we are possibly accessing the conn concurrently
if((type == MsgType.TLS_ERROR) || (type == MsgType.HTTP_ERROR) || (type == MsgType.TCP_ERROR)) {
@ -376,7 +364,11 @@ public class MitmReceiver implements Runnable, ConnectionsListener, MitmListener
}
public boolean isProxyRunning() {
return mProxyRunning;
return Boolean.TRUE.equals(proxyRunning.getValue());
}
public static void observeRunning(LifecycleOwner lifecycleOwner, Observer<Boolean> observer) {
proxyRunning.observe(lifecycleOwner, observer);
}
@Override

View File

@ -21,10 +21,7 @@ package com.emanuelef.remote_capture.activities;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.UriPermission;
import android.content.pm.PackageInfo;
@ -46,7 +43,6 @@ import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.adapter.FragmentStateAdapter;
@ -87,7 +83,6 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashSet;
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener {
@ -97,7 +92,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
private AppStateListener mListener;
private Uri mPcapUri;
private File mKeylogFile;
private BroadcastReceiver mReceiver;
private String mPcapFname;
private DrawerLayout mDrawer;
private SharedPreferences mPrefs;
@ -170,54 +164,40 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
setupTabs();
/* Register for service status */
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String status = intent.getStringExtra(CaptureService.SERVICE_STATUS_KEY);
CaptureService.observeStatus(this, serviceStatus -> {
Log.d(TAG, "Service status: " + serviceStatus.name());
if (status != null) {
Log.d(TAG, "Service status: " + status);
if (serviceStatus == CaptureService.ServiceStatus.STARTED)
appStateRunning();
else /* STOPPED */ {
// The service may still be active (on premature native termination)
if (CaptureService.isServiceActive())
CaptureService.stopService();
if (status.equals(CaptureService.SERVICE_STATUS_STARTED))
appStateRunning();
else if (status.equals(CaptureService.SERVICE_STATUS_STOPPED)) {
// The service may still be active (on premature native termination)
if (CaptureService.isServiceActive())
CaptureService.stopService();
mKeylogFile = MitmReceiver.getKeylogFilePath(MainActivity.this);
if(!mKeylogFile.exists() || !CaptureService.isDecryptingTLS())
mKeylogFile = null;
mKeylogFile = MitmReceiver.getKeylogFilePath(MainActivity.this);
if(!mKeylogFile.exists() || !CaptureService.isDecryptingTLS())
mKeylogFile = null;
Log.d(TAG, "sslkeylog? " + (mKeylogFile != null));
Log.d(TAG, "sslkeylog? " + (mKeylogFile != null));
if((mPcapUri != null) && (Prefs.getDumpMode(mPrefs) == Prefs.DumpMode.PCAP_FILE)) {
showPcapActionDialog(mPcapUri);
mPcapUri = null;
mPcapFname = null;
if((mPcapUri != null) && (Prefs.getDumpMode(mPrefs) == Prefs.DumpMode.PCAP_FILE)) {
showPcapActionDialog(mPcapUri);
mPcapUri = null;
mPcapFname = null;
// will export the keylogfile after saving/sharing pcap
} else if(mKeylogFile != null)
startExportSslkeylogfile();
// will export the keylogfile after saving/sharing pcap
} else if(mKeylogFile != null)
startExportSslkeylogfile();
appStateReady();
}
}
appStateReady();
}
};
LocalBroadcastManager.getInstance(this)
.registerReceiver(mReceiver, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mReceiver != null)
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(mReceiver);
mCapHelper = null;
}

View File

@ -21,13 +21,9 @@ package com.emanuelef.remote_capture.activities;
import androidx.annotation.NonNull;
import androidx.core.view.MenuProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
@ -45,7 +41,6 @@ import com.emanuelef.remote_capture.model.CaptureStats;
import java.util.Locale;
public class StatsActivity extends BaseActivity implements MenuProvider {
private BroadcastReceiver mReceiver;
private TextView mBytesSent;
private TextView mBytesRcvd;
private TextView mPacketsSent;
@ -94,33 +89,13 @@ public class StatsActivity extends BaseActivity implements MenuProvider {
} else
findViewById(R.id.row_pkts_dropped).setVisibility(View.GONE);
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateStats(intent);
}
};
/* Register for updates */
LocalBroadcastManager.getInstance(this)
.registerReceiver(mReceiver, new IntentFilter(CaptureService.ACTION_STATS_DUMP));
// Listen for stats updates
CaptureService.observeStats(this, this::updateStats);
CaptureService.askStatsDump();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mReceiver != null)
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(mReceiver);
}
private void updateStats(Intent intent) {
CaptureStats stats = Utils.getSerializableExtra(intent, "value", CaptureStats.class);
assert(stats != null);
private void updateStats(CaptureStats stats) {
mBytesSent.setText(Utils.formatBytes(stats.bytes_sent));
mBytesRcvd.setText(Utils.formatBytes(stats.bytes_rcvd));
mPacketsSent.setText(Utils.formatIntShort(stats.pkts_sent));

View File

@ -19,10 +19,7 @@
package com.emanuelef.remote_capture.fragments;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@ -38,7 +35,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.emanuelef.remote_capture.CaptureService;
import com.emanuelef.remote_capture.ConnectionsRegister;
@ -59,7 +55,6 @@ public class AppsFragment extends Fragment implements ConnectionsListener {
private Handler mHandler;
private boolean mRefreshApps;
private boolean listenerSet;
private BroadcastReceiver mReceiver;
@Override
public void onPause() {
@ -107,34 +102,15 @@ public class AppsFragment extends Fragment implements ConnectionsListener {
});
/* Register for service status */
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String status = intent.getStringExtra(CaptureService.SERVICE_STATUS_KEY);
if(CaptureService.SERVICE_STATUS_STARTED.equals(status)) {
if(listenerSet) {
// register the new connection register
unregisterConnsListener();
registerConnsListener();
}
CaptureService.observeStatus(this, serviceStatus -> {
if(serviceStatus == CaptureService.ServiceStatus.STARTED) {
if(listenerSet) {
// register the new connection register
unregisterConnsListener();
registerConnsListener();
}
}
};
LocalBroadcastManager.getInstance(requireContext())
.registerReceiver(mReceiver, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
}
@Override
public void onDestroyView() {
super.onDestroyView();
if(mReceiver != null) {
LocalBroadcastManager.getInstance(requireContext())
.unregisterReceiver(mReceiver);
mReceiver = null;
}
});
}
@Override

View File

@ -19,10 +19,6 @@
package com.emanuelef.remote_capture.fragments;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@ -40,7 +36,6 @@ import androidx.annotation.Nullable;
import androidx.core.view.MenuProvider;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.emanuelef.remote_capture.CaptureService;
import com.emanuelef.remote_capture.PCAPdroid;
@ -54,7 +49,6 @@ public class BlacklistsFragment extends Fragment implements BlacklistsStateListe
private BlacklistsAdapter mAdapter;
private Blacklists mBlacklists;
private MenuItem mUpdateItem;
private BroadcastReceiver mReceiver;
private Handler mHandler;
@Override
@ -73,33 +67,19 @@ public class BlacklistsFragment extends Fragment implements BlacklistsStateListe
mHandler = new Handler(Looper.getMainLooper());
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String status = intent.getStringExtra(CaptureService.SERVICE_STATUS_KEY);
if(status != null)
refreshStatus();
}
};
CaptureService.observeStatus(this, serviceStatus -> refreshStatus());
}
@Override
public void onResume() {
super.onResume();
mBlacklists.addOnChangeListener(this);
LocalBroadcastManager.getInstance(requireContext())
.registerReceiver(mReceiver, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
}
@Override
public void onPause() {
super.onPause();
mBlacklists.removeOnChangeListener(this);
LocalBroadcastManager.getInstance(requireContext())
.unregisterReceiver(mReceiver);
}
@Override

View File

@ -21,10 +21,8 @@ package com.emanuelef.remote_capture.fragments;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@ -49,7 +47,6 @@ import androidx.appcompat.widget.SearchView;
import androidx.core.view.MenuProvider;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.RecyclerView;
@ -95,7 +92,6 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
private MenuItem mMenuFilter;
private MenuItem mMenuItemSearch;
private MenuItem mSave;
private BroadcastReceiver mReceiver;
private Uri mCsvFname;
private AppsResolver mApps;
private SearchView mSearchView;
@ -261,41 +257,23 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
mQueryToApply = search;
// Register for service status
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String status = intent.getStringExtra(CaptureService.SERVICE_STATUS_KEY);
if(CaptureService.SERVICE_STATUS_STARTED.equals(status)) {
// register the new connection register
if(listenerSet) {
unregisterConnsListener();
registerConnsListener();
}
autoScroll = true;
showFabDown(false);
mOldConnectionsText.setVisibility(View.GONE);
mEmptyText.setText(R.string.no_connections);
mApps.clear();
CaptureService.observeStatus(this, serviceStatus -> {
if(serviceStatus == CaptureService.ServiceStatus.STARTED) {
// register the new connection register
if(listenerSet) {
unregisterConnsListener();
registerConnsListener();
}
refreshMenuIcons();
autoScroll = true;
showFabDown(false);
mOldConnectionsText.setVisibility(View.GONE);
mEmptyText.setText(R.string.no_connections);
mApps.clear();
}
};
LocalBroadcastManager.getInstance(requireContext())
.registerReceiver(mReceiver, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
}
@Override
public void onDestroyView() {
super.onDestroyView();
if(mReceiver != null) {
LocalBroadcastManager.getInstance(requireContext())
.unregisterReceiver(mReceiver);
}
refreshMenuIcons();
});
}
@Override
@ -718,7 +696,6 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener
return;
boolean is_enabled = (CaptureService.getConnsRegister() != null);
Context ctx = requireContext();
mMenuItemSearch.setVisible(is_enabled); // NOTE: setEnabled does not work for this
//mMenuFilter.setEnabled(is_enabled);

View File

@ -21,10 +21,7 @@ package com.emanuelef.remote_capture.fragments;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@ -48,7 +45,6 @@ import androidx.appcompat.widget.SwitchCompat;
import androidx.core.view.MenuProvider;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
import com.emanuelef.remote_capture.AppsLoader;
@ -84,7 +80,6 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr
private View mQuickSettings;
private MainActivity mActivity;
private SharedPreferences mPrefs;
private BroadcastReceiver mReceiver;
private TextView mFilterDescription;
private SwitchCompat mAppFilterSwitch;
private String mAppFilter;
@ -109,37 +104,6 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr
public void onResume() {
super.onResume();
refreshStatus();
/* Register for stats update */
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(CaptureService.ACTION_STATS_DUMP))
processStatsUpdateIntent(intent);
else if(action.equals(MitmReceiver.ACTION_MITM_ADDON_STATUS_CHANGED))
refreshDecryptionStatus();
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(CaptureService.ACTION_STATS_DUMP);
filter.addAction(MitmReceiver.ACTION_MITM_ADDON_STATUS_CHANGED);
LocalBroadcastManager.getInstance(requireContext())
.registerReceiver(mReceiver, filter);
}
@Override
public void onPause() {
super.onPause();
if(mReceiver != null) {
LocalBroadcastManager.getInstance(requireContext())
.unregisterReceiver(mReceiver);
mReceiver = null;
}
}
@Override
@ -205,6 +169,10 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr
mActivity.startCapture();
});
// Register for updates
MitmReceiver.observeRunning(this, running -> refreshDecryptionStatus());
CaptureService.observeStats(this, this::onStatsUpdate);
// Make URLs clickable
mCollectorInfo.setMovementMethod(LinkMovementMethod.getInstance());
@ -282,10 +250,7 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr
recheckFilterWarning();
}
private void processStatsUpdateIntent(Intent intent) {
CaptureStats stats = Utils.getSerializableExtra(intent, "value", CaptureStats.class);
assert(stats != null);
private void onStatsUpdate(CaptureStats stats) {
Log.d("MainReceiver", "Got StatsUpdate: bytes_sent=" + stats.pkts_sent + ", bytes_rcvd=" +
stats.bytes_rcvd + ", pkts_sent=" + stats.pkts_sent + ", pkts_rcvd=" + stats.pkts_rcvd);
@ -431,7 +396,7 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr
dialog.show();
// NOTE: run this after dialog.show
mOpenAppsList = (AppsListView) dialog.findViewById(R.id.apps_list);
mOpenAppsList = dialog.findViewById(R.id.apps_list);
mEmptyAppsView = dialog.findViewById(R.id.no_apps);
mEmptyAppsView.setText(R.string.loading_apps);