diff --git a/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsStatsAdapter.java b/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsStatsAdapter.java index 217caccb..99ef1685 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsStatsAdapter.java +++ b/app/src/main/java/com/emanuelef/remote_capture/adapters/AppsStatsAdapter.java @@ -20,6 +20,7 @@ package com.emanuelef.remote_capture.adapters; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; @@ -29,29 +30,37 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.RecyclerView; +import com.emanuelef.remote_capture.CaptureService; +import com.emanuelef.remote_capture.PCAPdroid; import com.emanuelef.remote_capture.R; import com.emanuelef.remote_capture.Utils; import com.emanuelef.remote_capture.model.AppDescriptor; import com.emanuelef.remote_capture.model.AppStats; import com.emanuelef.remote_capture.AppsResolver; +import com.emanuelef.remote_capture.model.MatchList; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class AppsStatsAdapter extends RecyclerView.Adapter { - private static final String TAG = "ConnectionsAdapter"; + private static final String TAG = "AppsStatsAdapter"; private final Context mContext; private final LayoutInflater mLayoutInflater; private final Drawable mUnknownIcon; + private final MatchList mBlocklist; private View.OnClickListener mListener; private List mStats; private final AppsResolver mApps; + private final SharedPreferences mPrefs; + private int mClickedPosition; - public static class ViewHolder extends RecyclerView.ViewHolder { + public class ViewHolder extends RecyclerView.ViewHolder { ImageView icon; + ImageView blockedFlag; TextView info; TextView traffic; @@ -59,27 +68,29 @@ public class AppsStatsAdapter extends RecyclerView.Adapter 1) - info_txt += " (" + Utils.formatNumber(context, stats.numConnections) + ")"; + info_txt += " (" + Utils.formatNumber(mContext, stats.numConnections) + ")"; info.setText(info_txt); traffic.setText(Utils.formatBytes(stats.sentBytes + stats.rcvdBytes)); + blockedFlag.setVisibility(mBlocklist.matchesApp(stats.getUid()) ? View.VISIBLE : View.INVISIBLE); } } @@ -88,8 +99,10 @@ public class AppsStatsAdapter extends RecyclerView.Adapter(); + mPrefs = PreferenceManager.getDefaultSharedPreferences(context); setHasStableIds(true); } @@ -106,7 +119,21 @@ public class AppsStatsAdapter extends RecyclerView.Adapter { + // see registerForContextMenu + mClickedPosition = holder.getAbsoluteAdapterPosition(); + return false; + }); + } else + view.setLongClickable(false); + + return holder; } @Override @@ -116,7 +143,7 @@ public class AppsStatsAdapter extends RecyclerView.Adapter { + // see registerForContextMenu mClickedPosition = holder.getAbsoluteAdapterPosition(); return false; }); diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java index 6cafa488..acea6885 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java @@ -26,7 +26,11 @@ import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.util.Log; +import android.view.ContextMenu; import android.view.LayoutInflater; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -36,13 +40,17 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.localbroadcastmanager.content.LocalBroadcastManager; +import com.emanuelef.remote_capture.Billing; import com.emanuelef.remote_capture.CaptureService; import com.emanuelef.remote_capture.ConnectionsRegister; +import com.emanuelef.remote_capture.PCAPdroid; import com.emanuelef.remote_capture.R; import com.emanuelef.remote_capture.activities.AppDetailsActivity; import com.emanuelef.remote_capture.adapters.AppsStatsAdapter; import com.emanuelef.remote_capture.interfaces.ConnectionsListener; +import com.emanuelef.remote_capture.model.AppStats; import com.emanuelef.remote_capture.model.ConnectionDescriptor; +import com.emanuelef.remote_capture.model.MatchList; import com.emanuelef.remote_capture.views.EmptyRecyclerView; public class AppsFragment extends Fragment implements ConnectionsListener { @@ -78,6 +86,7 @@ public class AppsFragment extends Fragment implements ConnectionsListener { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { mRecyclerView = view.findViewById(R.id.apps_stats_view); mRecyclerView.setLayoutManager(new EmptyRecyclerView.MyLinearLayoutManager(getContext())); + registerForContextMenu(mRecyclerView); mAdapter = new AppsStatsAdapter(getContext()); doRefreshApps(); @@ -129,6 +138,47 @@ public class AppsFragment extends Fragment implements ConnectionsListener { } } + @Override + public void onCreateContextMenu(@NonNull ContextMenu menu, @NonNull View v, + @Nullable ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + Log.d(TAG, "onCreateContextMenu"); + + MenuInflater inflater = requireActivity().getMenuInflater(); + inflater.inflate(R.menu.app_context_menu, menu); + + AppStats stats = mAdapter.getItem(mAdapter.getClickedItemPos()); + if(stats == null) + return; + + // TODO unblock + menu.findItem(R.id.block_app).setVisible(true); + menu.findItem(R.id.unblock_app).setVisible(false); + } + + @Override + public boolean onContextItemSelected(@NonNull MenuItem item) { + int id = item.getItemId(); + MatchList blocklist = PCAPdroid.getInstance().getBlocklist(); + int itemPos = mAdapter.getClickedItemPos(); + AppStats app = mAdapter.getItem(itemPos); + + if(id == R.id.block_app) + blocklist.addApp(app.getUid()); + else + return super.onContextItemSelected(item); + + // refresh the blocklist + blocklist.save(); + if(CaptureService.isServiceActive()) + CaptureService.requireInstance().reloadBlocklist(); + + // refresh the item + mAdapter.notifyItemChanged(itemPos); + + return true; + } + private void registerConnsListener() { if (!listenerSet) { ConnectionsRegister reg = CaptureService.getConnsRegister(); diff --git a/app/src/main/res/layout/app_item.xml b/app/src/main/res/layout/app_item.xml index e555024d..80392efc 100644 --- a/app/src/main/res/layout/app_item.xml +++ b/app/src/main/res/layout/app_item.xml @@ -6,6 +6,7 @@ android:orientation="horizontal" android:paddingHorizontal="4dp" android:paddingVertical="2dp" + android:gravity="center_vertical" android:layout_height="wrap_content"> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f720ab64..117fe3ff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -349,4 +349,6 @@ Firewall is disabled Firewall is enabled App info + Block + Unblock