diff --git a/gander/src/main/AndroidManifest.xml b/gander/src/main/AndroidManifest.xml
index c9e458c..d822760 100644
--- a/gander/src/main/AndroidManifest.xml
+++ b/gander/src/main/AndroidManifest.xml
@@ -21,6 +21,17 @@
android:name=".internal.ui.details.TransactionDetailsActivity"
android:parentActivityName=".internal.ui.list.TransactionListActivity"
android:theme="@style/Gander.Theme" />
+
+
+
+
+
\ No newline at end of file
diff --git a/gander/src/main/java/com/ashokvarma/gander/internal/support/FormatUtils.java b/gander/src/main/java/com/ashokvarma/gander/internal/support/FormatUtils.java
index 080a1bb..870f088 100644
--- a/gander/src/main/java/com/ashokvarma/gander/internal/support/FormatUtils.java
+++ b/gander/src/main/java/com/ashokvarma/gander/internal/support/FormatUtils.java
@@ -1,24 +1,31 @@
package com.ashokvarma.gander.internal.support;
import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
import android.text.Spannable;
import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;
import androidx.annotation.NonNull;
+import androidx.core.content.FileProvider;
import com.ashokvarma.gander.R;
import com.ashokvarma.gander.internal.data.HttpHeader;
import com.ashokvarma.gander.internal.ui.HttpTransactionUIHelper;
+import com.ashokvarma.gander.internal.ui.details.TransactionDetailsActivity;
import org.json.JSONArray;
import org.json.JSONObject;
import org.xml.sax.InputSource;
+import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
@@ -153,8 +160,21 @@ public static CharSequence formatFormEncoded(String formEncoded) {
}
}
- public static CharSequence getShareText(Context context, HttpTransactionUIHelper transactionUIHelper) {
- SpannableStringBuilder text = new SpannableStringBuilder();
+ public static CharSequence getShareText(Context context, HttpTransactionUIHelper transactionUIHelper, int position) {
+ StringBuilder text = new StringBuilder();
+ if (position == TransactionDetailsActivity.POSITION_OVERVIEW) {
+ text.append(getOverviewText(context, transactionUIHelper));
+ } else if (position == TransactionDetailsActivity.POSITION_REQUEST) {
+ text.append(getRequestText(context, transactionUIHelper));
+ } else if (position == TransactionDetailsActivity.POSITION_RESPONSE) {
+ text.append(getResponseText(context, transactionUIHelper));
+ }
+ return text;
+ }
+
+ @SuppressWarnings("all")
+ private static CharSequence getOverviewText(Context context, HttpTransactionUIHelper transactionUIHelper) {
+ StringBuilder text = new StringBuilder();
text.append(context.getString(R.string.gander_url)).append(": ").append(v(transactionUIHelper.getUrl())).append("\n");
text.append(context.getString(R.string.gander_method)).append(": ").append(v(transactionUIHelper.getMethod())).append("\n");
text.append(context.getString(R.string.gander_protocol)).append(": ").append(v(transactionUIHelper.getProtocol())).append("\n");
@@ -170,6 +190,12 @@ public static CharSequence getShareText(Context context, HttpTransactionUIHelper
text.append(context.getString(R.string.gander_response_size)).append(": ").append(v(transactionUIHelper.getResponseSizeString())).append("\n");
text.append(context.getString(R.string.gander_total_size)).append(": ").append(v(transactionUIHelper.getTotalSizeString())).append("\n");
text.append("\n");
+ return text;
+ }
+
+
+ private static CharSequence getRequestText(Context context, HttpTransactionUIHelper transactionUIHelper) {
+ StringBuilder text = new StringBuilder();
text.append("---------- ").append(context.getString(R.string.gander_request)).append(" ----------\n\n");
CharSequence headers = formatHeaders(transactionUIHelper.getRequestHeaders(), false);
if (!TextUtil.isNullOrWhiteSpace(headers)) {
@@ -178,8 +204,14 @@ public static CharSequence getShareText(Context context, HttpTransactionUIHelper
text.append((transactionUIHelper.requestBodyIsPlainText()) ? v(transactionUIHelper.getFormattedRequestBody()) :
context.getString(R.string.gander_body_omitted));
text.append("\n\n");
+ return text;
+ }
+
+ private static CharSequence getResponseText(Context context, HttpTransactionUIHelper
+ transactionUIHelper) {
+ StringBuilder text = new StringBuilder();
text.append("---------- ").append(context.getString(R.string.gander_response)).append(" ----------\n\n");
- headers = formatHeaders(transactionUIHelper.getResponseHeaders(), false);
+ CharSequence headers = formatHeaders(transactionUIHelper.getResponseHeaders(), false);
if (!TextUtil.isNullOrWhiteSpace(headers)) {
text.append(headers).append("\n");
}
@@ -188,6 +220,40 @@ public static CharSequence getShareText(Context context, HttpTransactionUIHelper
return text;
}
+ public static File getShareFile(Context context, HttpTransactionUIHelper transactionUIHelper) {
+ File file = new File(context.getCacheDir(), transactionUIHelper.getId() + ".txt");
+ StringBuilder text = new StringBuilder();
+ text.append(getOverviewText(context, transactionUIHelper));
+ text.append(getRequestText(context, transactionUIHelper));
+ text.append(getResponseText(context, transactionUIHelper));
+ BufferedWriter bw = null;
+ try {
+ if (!file.exists() && !file.createNewFile()) {
+ return null;
+ }
+ bw = new BufferedWriter(new FileWriter(file));
+ bw.write(text.toString());
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ if (bw != null) {
+ bw.close();
+ }
+ } catch (IOException ignored) {
+ }
+ }
+ return file;
+ }
+
+ public static Uri getFileUri(Context context, File file) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ return FileProvider.getUriForFile(context, context.getPackageName() + ".file.path.share", file);
+ }
+ return Uri.fromFile(file);
+ }
+
public static String getShareCurlCommand(HttpTransactionUIHelper transactionUIHelper) {
boolean compressed = false;
StringBuilder curlCmd = new StringBuilder("curl");
diff --git a/gander/src/main/java/com/ashokvarma/gander/internal/support/GanderFileProvider.java b/gander/src/main/java/com/ashokvarma/gander/internal/support/GanderFileProvider.java
new file mode 100644
index 0000000..bd5671c
--- /dev/null
+++ b/gander/src/main/java/com/ashokvarma/gander/internal/support/GanderFileProvider.java
@@ -0,0 +1,9 @@
+package com.ashokvarma.gander.internal.support;
+
+import androidx.core.content.FileProvider;
+
+/**
+ * Created by ssyijiu on 2020/7/24.
+ */
+public class GanderFileProvider extends FileProvider {
+}
diff --git a/gander/src/main/java/com/ashokvarma/gander/internal/ui/details/TransactionDetailsActivity.java b/gander/src/main/java/com/ashokvarma/gander/internal/ui/details/TransactionDetailsActivity.java
index 4985081..5683fb2 100644
--- a/gander/src/main/java/com/ashokvarma/gander/internal/ui/details/TransactionDetailsActivity.java
+++ b/gander/src/main/java/com/ashokvarma/gander/internal/ui/details/TransactionDetailsActivity.java
@@ -2,6 +2,7 @@
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
@@ -9,6 +10,7 @@
import android.view.View;
import android.view.WindowInsets;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
@@ -31,6 +33,7 @@
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.tabs.TabLayout;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -46,6 +49,11 @@ public class TransactionDetailsActivity extends BaseGanderActivity {
private static final String ARG_TRANSACTION_ID = "transaction_id";
private static final String ARG_TRANSACTION_STATUS = "transaction_status";
private static final String ARG_TRANSACTION_RESPONSE_CODE = "transaction_response_code";
+
+ public static final int POSITION_OVERVIEW = 0;
+ public static final int POSITION_REQUEST = 1;
+ public static final int POSITION_RESPONSE = 2;
+ private static int SELECTED_TAB_POSITION = POSITION_OVERVIEW;
public static void start(Context context, long transactionId, HttpTransactionUIHelper.Status status, Integer responseCode) {
Intent intent = new Intent(context, TransactionDetailsActivity.class);
@@ -55,8 +63,6 @@ public static void start(Context context, long transactionId, HttpTransactionUIH
context.startActivity(intent);
}
- private static int SELECTED_TAB_POSITION = 0;
-
private TextView mTitleView;
private Adapter mAdapter;
private AppBarLayout mAppBarLayout;
@@ -122,13 +128,23 @@ public boolean onCreateOptionsMenu(Menu menu) {
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.share_text) {
if (mTransaction != null)
- share(FormatUtils.getShareText(this, mTransaction));
+ share(FormatUtils.getShareText(this, mTransaction, SELECTED_TAB_POSITION));
return true;
} else if (item.getItemId() == R.id.share_curl) {
if (mTransaction != null)
share(FormatUtils.getShareCurlCommand(mTransaction));
return true;
- } else {
+ } else if (item.getItemId() == R.id.share_file) {
+ if (mTransaction != null) {
+ File file = FormatUtils.getShareFile(this, mTransaction);
+ if (file != null) {
+ shareFile(file);
+ } else {
+ Toast.makeText(this, R.string.gander_failed_to_write_file, Toast.LENGTH_SHORT).show();
+ }
+ }
+ return true;
+ }else {
return super.onOptionsItemSelected(item);
}
}
@@ -166,6 +182,16 @@ private void share(CharSequence content) {
startActivity(Intent.createChooser(sendIntent, null));
}
+ private void shareFile(File file) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.setType("text/plain");
+ sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ Uri uri = FormatUtils.getFileUri(this, file);
+ sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ startActivity(Intent.createChooser(sendIntent, null));
+ }
+
static class Adapter extends FragmentPagerAdapter {
final List fragments = new ArrayList<>();
private final List fragmentTitles = new ArrayList<>();
diff --git a/gander/src/main/res/menu/gander_details_menu.xml b/gander/src/main/res/menu/gander_details_menu.xml
index 8cd37e9..5231a55 100644
--- a/gander/src/main/res/menu/gander_details_menu.xml
+++ b/gander/src/main/res/menu/gander_details_menu.xml
@@ -10,6 +10,9 @@
+
diff --git a/gander/src/main/res/values/strings.xml b/gander/src/main/res/values/strings.xml
index 16f0d4a..cc24458 100644
--- a/gander/src/main/res/values/strings.xml
+++ b/gander/src/main/res/values/strings.xml
@@ -25,6 +25,7 @@
No
Share
Share as text
+ Share as file
Share as curl command
(encoded or binary body omitted)
Search
@@ -33,4 +34,5 @@
Gander HTTP notifications
Search Request and Headers
Search Response and Headers
+ "Failed to write file"
diff --git a/gander/src/main/res/xml/gander_file_paths.xml b/gander/src/main/res/xml/gander_file_paths.xml
new file mode 100644
index 0000000..a5596a9
--- /dev/null
+++ b/gander/src/main/res/xml/gander_file_paths.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file