mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-16 21:10:57 +08:00
Ability to copy/share stats and connection details
This commit is contained in:
parent
3ad73afcec
commit
3f1028604d
@ -7,6 +7,7 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" /> <!-- https://developer.android.com/preview/privacy/package-visibility -->
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.WRITE_CLIPS" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@ -39,6 +39,8 @@ import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -320,4 +322,28 @@ public class Utils {
|
||||
|
||||
return new BitmapDrawable(res, bitmap);
|
||||
}
|
||||
|
||||
// Converts a TableLayout (two columns, label and value) to a string which can be copied
|
||||
public static String table2Text(TableLayout table) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < table.getChildCount(); i++) {
|
||||
View v = table.getChildAt(i);
|
||||
|
||||
if ((v instanceof TableRow) && (v.getVisibility() == View.VISIBLE)
|
||||
&& (((TableRow) v).getChildCount() == 2)) {
|
||||
View label = ((TableRow) v).getChildAt(0);
|
||||
View value = ((TableRow) v).getChildAt(1);
|
||||
|
||||
if((label instanceof TextView) && (value instanceof TextView)) {
|
||||
builder.append(((TextView) label).getText());
|
||||
builder.append(": ");
|
||||
builder.append(((TextView) value).getText());
|
||||
builder.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,11 +19,18 @@
|
||||
|
||||
package com.emanuelef.remote_capture.activities;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.emanuelef.remote_capture.R;
|
||||
@ -31,8 +38,10 @@ import com.emanuelef.remote_capture.Utils;
|
||||
import com.emanuelef.remote_capture.model.ConnectionDescriptor;
|
||||
|
||||
public class ConnectionDetailsActivity extends AppCompatActivity {
|
||||
private static final String TAG = "ConnectionDetails";
|
||||
public static final String CONN_EXTRA_KEY = "conn_descriptor";
|
||||
public static final String APP_NAME_EXTRA_KEY = "app_name";
|
||||
private TableLayout mTable;
|
||||
private TextView mBytesView;
|
||||
private TextView mPacketsView;
|
||||
private TextView mDurationView;
|
||||
@ -58,6 +67,7 @@ public class ConnectionDetailsActivity extends AppCompatActivity {
|
||||
View info_row = findViewById(R.id.detail_info_row);
|
||||
TextView source = findViewById(R.id.detail_source);
|
||||
TextView destination = findViewById(R.id.detail_destination);
|
||||
mTable = findViewById(R.id.table);
|
||||
mBytesView = findViewById(R.id.detail_bytes);
|
||||
mPacketsView = findViewById(R.id.detail_packets);
|
||||
mDurationView = findViewById(R.id.detail_duration);
|
||||
@ -76,7 +86,7 @@ public class ConnectionDetailsActivity extends AppCompatActivity {
|
||||
source.setText(String.format(getResources().getString(R.string.ip_and_port), conn.src_ip, conn.src_port));
|
||||
destination.setText(String.format(getResources().getString(R.string.ip_and_port), conn.dst_ip, conn.dst_port));
|
||||
|
||||
if(conn.info != null) {
|
||||
if((conn.info != null) && (!conn.info.isEmpty())) {
|
||||
if(conn.l7proto.equals("DNS"))
|
||||
info_label.setText(R.string.query);
|
||||
else if(conn.l7proto.equals("HTTP"))
|
||||
@ -113,4 +123,41 @@ public class ConnectionDetailsActivity extends AppCompatActivity {
|
||||
mStatus.setText(R.string.conn_status_open);
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if(id == R.id.copy_to_clipboard) {
|
||||
String contents = Utils.table2Text(mTable);
|
||||
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(getString(R.string.connection_details), contents);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
Utils.showToast(this, R.string.copied_to_clipboard);
|
||||
return true;
|
||||
} else if(id == R.id.share) {
|
||||
String contents = Utils.table2Text(mTable);
|
||||
|
||||
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.connection_details));
|
||||
intent.putExtra(android.content.Intent.EXTRA_TEXT, contents);
|
||||
|
||||
startActivity(Intent.createChooser(intent, getResources().getString(R.string.share)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,16 +19,23 @@
|
||||
|
||||
package com.emanuelef.remote_capture.activities;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.emanuelef.remote_capture.CaptureService;
|
||||
@ -49,12 +56,14 @@ public class StatsActivity extends AppCompatActivity {
|
||||
private TextView mOpenSocks;
|
||||
private TextView mDnsServer;
|
||||
private TextView mDnsQueries;
|
||||
private TableLayout mTable;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_stats);
|
||||
|
||||
mTable = findViewById(R.id.table);
|
||||
mBytesSent = findViewById(R.id.bytes_sent);
|
||||
mBytesRcvd = findViewById(R.id.bytes_rcvd);
|
||||
mPacketsSent = findViewById(R.id.packets_sent);
|
||||
@ -113,4 +122,41 @@ public class StatsActivity extends AppCompatActivity {
|
||||
if(stats.num_dropped_conns > 0)
|
||||
mDroppedConns.setTextColor(Color.RED);
|
||||
}
|
||||
|
||||
@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) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if(id == R.id.copy_to_clipboard) {
|
||||
String contents = Utils.table2Text(mTable);
|
||||
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(getString(R.string.stats), contents);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
Utils.showToast(this, R.string.copied_to_clipboard);
|
||||
return true;
|
||||
} else if(id == R.id.share) {
|
||||
String contents = Utils.table2Text(mTable);
|
||||
|
||||
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.stats));
|
||||
intent.putExtra(android.content.Intent.EXTRA_TEXT, contents);
|
||||
|
||||
startActivity(Intent.createChooser(intent, getResources().getString(R.string.share)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/drawable/ic_content_copy.xml
Normal file
5
app/src/main/res/drawable/ic_content_copy.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/ic_share.xml
Normal file
5
app/src/main/res/drawable/ic_share.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||
</vector>
|
||||
@ -1,10 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<TableLayout
|
||||
android:id="@+id/table"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp">
|
||||
@ -25,7 +27,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="com.emanuelef.remote_capture (14503)" />
|
||||
tools:text="com.emanuelef.remote_capture (14503)" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -44,7 +46,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="TLS (TCP)" />
|
||||
tools:text="TLS (TCP)" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -65,7 +67,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="ssl.example.com" />
|
||||
tools:text="ssl.example.com" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -85,7 +87,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="1.2.3.4:14631" />
|
||||
tools:text="1.2.3.4:14631" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -104,7 +106,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="5.6.7.8:443" />
|
||||
tools:text="5.6.7.8:443" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -123,7 +125,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="Open" />
|
||||
tools:text="Open" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -142,7 +144,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="example.com/test" />
|
||||
tools:text="example.com/test" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -162,8 +164,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="1.5 MB down - 0.1 up" />
|
||||
|
||||
tools:text="1.5 MB down - 0.1 up" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -182,8 +183,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="1.1 K down - 98 down" />
|
||||
|
||||
tools:text="1.1 K down - 98 down" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -202,7 +202,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="2 min" />
|
||||
tools:text="2 min" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -221,7 +221,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="01/02/20 00:45:01" />
|
||||
tools:text="01/02/20 00:45:01" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
@ -240,7 +240,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.75"
|
||||
android:textIsSelectable="true"
|
||||
android:text="01/02/20 00:47:01" />
|
||||
tools:text="01/02/20 00:47:01" />
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
|
||||
@ -7,7 +7,8 @@ android:layout_height="fill_parent">
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp">
|
||||
android:padding="8dp"
|
||||
android:id="@+id/table">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
|
||||
19
app/src/main/res/menu/copy_share_menu.xml
Normal file
19
app/src/main/res/menu/copy_share_menu.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/copy_to_clipboard"
|
||||
android:title="@string/copy_to_clipboard"
|
||||
android:orderInCategory="10"
|
||||
android:icon="@drawable/ic_content_copy"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/share"
|
||||
android:title="@string/share"
|
||||
android:orderInCategory="20"
|
||||
android:icon="@drawable/ic_share"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
||||
@ -105,5 +105,7 @@
|
||||
<string name="first_seen">First Seen</string>
|
||||
<string name="last_seen">Last Seen</string>
|
||||
<string name="conn_status_closed">Closed</string>
|
||||
<string name="copy_to_clipboard">Copy to clipboard</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard!</string>
|
||||
</resources>
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
<resources>
|
||||
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user