From 762b09620e60b15f51a78fe5d4bb11e9bf7cb792 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Mon, 28 Jun 2021 23:03:05 +0200 Subject: [PATCH] Add copy/share to the App Details activity --- .../remote_capture/AppsResolver.java | 18 ++++--- .../activities/AppDetailsActivity.java | 50 ++++++++++++++++--- .../fragments/ConnectionsFragment.java | 6 +++ .../remote_capture/model/AppDescriptor.java | 11 ++++ .../main/res/layout/app_details_activity.xml | 6 +-- .../main/res/menu/connection_context_menu.xml | 4 ++ app/src/main/res/values/strings.xml | 6 ++- 7 files changed, 83 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java b/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java index 34f2dfe6..765c86f4 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java +++ b/app/src/main/java/com/emanuelef/remote_capture/AppsResolver.java @@ -36,21 +36,25 @@ public class AppsResolver { // NOTE: these virtual apps cannot be used as a permanent filter (via addAllowedApplication) // as they miss a valid package name mApps.put(Utils.UID_UNKNOWN, new AppDescriptor(mContext.getString(R.string.unknown_app), - mUnknownAppIcon, "unknown", Utils.UID_UNKNOWN, true)); + mUnknownAppIcon, "unknown", Utils.UID_UNKNOWN, true) + .setDescription(mContext.getString(R.string.unknown_app_info))); mApps.put(0, new AppDescriptor("Root", - mVirtualAppIcon,"root", 0, true)); + mVirtualAppIcon,"root", 0, true) + .setDescription(mContext.getString(R.string.root_app_info))); mApps.put(1000, new AppDescriptor("Android", - mVirtualAppIcon,"android", 1000, true)); + mVirtualAppIcon,"android", 1000, true) + .setDescription(mContext.getString(R.string.android_app_info))); mApps.put(1013, new AppDescriptor("MediaServer", mVirtualAppIcon,"mediaserver", 1013, true)); mApps.put(1020, new AppDescriptor("MulticastDNSResponder", - mVirtualAppIcon,"multicastdnsresponder", 1020, true)); + mVirtualAppIcon,"multicastdnsresponder", 1020, true)); mApps.put(1021, new AppDescriptor("GPS", - mVirtualAppIcon,"gps", 1021, true)); + mVirtualAppIcon,"gps", 1021, true)); mApps.put(1051, new AppDescriptor("netd", - mVirtualAppIcon,"netd", 1051, true)); + mVirtualAppIcon,"netd", 1051, true) + .setDescription(mContext.getString(R.string.netd_app_info))); mApps.put(9999, new AppDescriptor("Nobody", - mVirtualAppIcon,"nobody", 9999, true)); + mVirtualAppIcon,"nobody", 9999, true)); } public static AppDescriptor resolve(PackageManager pm, String packageName, int pm_flags) { 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 20211c46..bfe991c9 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 @@ -25,10 +25,12 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.Button; import android.widget.ImageView; +import android.widget.TableLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -42,6 +44,7 @@ import com.emanuelef.remote_capture.model.AppDescriptor; public class AppDetailsActivity extends BaseActivity { private static final String TAG = "AppDetailsActivity"; public static final String APP_UID_EXTRA = "app_uid"; + private TableLayout mTable; @Override protected void onCreate(Bundle savedInstanceState) { @@ -94,10 +97,10 @@ public class AppDetailsActivity extends BaseActivity { } } else { // This is a virtual App - findViewById(R.id.vapp_info).setVisibility(View.VISIBLE); - - if(uid == Utils.UID_UNKNOWN) - ((TextView)findViewById(R.id.vapp_info)).setText(R.string.unknown_app_info); + if(!dsc.getDescription().isEmpty()) { + ((TextView) findViewById(R.id.vapp_info)).setText(dsc.getDescription()); + findViewById(R.id.vapp_info).setVisibility(View.VISIBLE); + } findViewById(R.id.package_name_row).setVisibility(View.GONE); findViewById(R.id.version_row).setVisibility(View.GONE); @@ -109,6 +112,8 @@ public class AppDetailsActivity extends BaseActivity { findViewById(R.id.app_settings).setVisibility(View.GONE); } + mTable = findViewById(R.id.table); + findViewById(R.id.app_settings).setOnClickListener(v -> { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", dsc.getPackageName(), null)); @@ -123,9 +128,42 @@ public class AppDetailsActivity extends BaseActivity { }); } + private String asString() { + if(findViewById(R.id.permissions).getVisibility() == View.GONE) + return Utils.table2Text(mTable); + + return Utils.table2Text(mTable) + + "\n" + + getString(R.string.permissions) + + ":\n" + + ((TextView) findViewById(R.id.permissions)).getText(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.copy_share_menu, menu); + + return super.onCreateOptionsMenu(menu); + } + @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(item.getItemId() == android.R.id.home) { + int id = item.getItemId(); + + if(id == R.id.copy_to_clipboard) { + Utils.copyToClipboard(this, asString()); + return true; + } else if(id == R.id.share) { + Intent intent = new Intent(android.content.Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.app_details)); + intent.putExtra(android.content.Intent.EXTRA_TEXT, asString()); + + startActivity(Intent.createChooser(intent, getResources().getString(R.string.share))); + + return true; + } else if(item.getItemId() == android.R.id.home) { finish(); return true; } diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java index 9eb04d91..9bda1376 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java @@ -57,6 +57,7 @@ import com.emanuelef.remote_capture.CaptureService; import com.emanuelef.remote_capture.ConnectionsRegister; import com.emanuelef.remote_capture.R; import com.emanuelef.remote_capture.Utils; +import com.emanuelef.remote_capture.activities.AppDetailsActivity; import com.emanuelef.remote_capture.activities.MainActivity; import com.emanuelef.remote_capture.model.AppDescriptor; import com.emanuelef.remote_capture.model.AppState; @@ -371,6 +372,11 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener mSearchView.setIconified(false); mSearchView.setQuery(conn.l7proto, true); return true; + } else if(id == R.id.open_app_details) { + Intent intent = new Intent(requireContext(), AppDetailsActivity.class); + intent.putExtra(AppDetailsActivity.APP_UID_EXTRA, conn.uid); + startActivity(intent); + return true; } else return super.onContextItemSelected(item); diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java b/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java index 62a86a11..477f772d 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/AppDescriptor.java @@ -34,6 +34,7 @@ public class AppDescriptor implements Comparable, Serializable { private final int mUid; private final boolean mIsSystem; private Drawable mIcon; + private String mDescription; // NULL for virtual apps PackageManager mPm; @@ -45,6 +46,7 @@ public class AppDescriptor implements Comparable, Serializable { this.mPackageName = package_name; this.mUid = uid; this.mIsSystem = is_system; + this.mDescription = ""; } public AppDescriptor(PackageManager pm, PackageInfo pkgInfo) { @@ -56,6 +58,15 @@ public class AppDescriptor implements Comparable, Serializable { mPackageInfo = pkgInfo; } + public AppDescriptor setDescription(String dsc) { + mDescription = dsc; + return this; + } + + public String getDescription() { + return mDescription; + } + public String getName() { return mName; } diff --git a/app/src/main/res/layout/app_details_activity.xml b/app/src/main/res/layout/app_details_activity.xml index 6e68ab90..7ff46083 100644 --- a/app/src/main/res/layout/app_details_activity.xml +++ b/app/src/main/res/layout/app_details_activity.xml @@ -15,6 +15,7 @@ android:id="@+id/app_icon" tools:src="@drawable/ic_apps" tools:tint="@color/colorAccent" + android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" @@ -27,7 +28,7 @@ android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/app_icon" - android:layout_marginTop="16dp"> + android:layout_marginTop="20dp"> + app:layout_constraintTop_toBottomOf="@id/buttons" /> + + \ 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 c67d98cc..acb93e3d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -156,8 +156,10 @@ Installed on Last Update Permissions - This is a system daemon. - \"Unknown\" marks connections whose app could not be determined + System daemons running with maximum privileges. + The system daemon which performs the DNS resolutions. + The Android system. + \"Unknown\" marks connections whose app could not be determined. Packets Dropped