diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index f8221b48..eda98a50 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -36,6 +36,7 @@ import android.support.v4.app.FragmentTransaction; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; +import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -46,12 +47,19 @@ import android.widget.CheckBox; import android.widget.ListView; import android.widget.TextView; +import java.util.Date; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.mail.Address; +import javax.mail.internet.InternetAddress; public class ActivityView extends ActivityBase implements FragmentManager.OnBackStackChangedListener, SharedPreferences.OnSharedPreferenceChangeListener { private DrawerLayout drawerLayout; private ListView drawerList; private ActionBarDrawerToggle drawerToggle; + private ExecutorService executor = Executors.newCachedThreadPool(); static final int LOADER_ACCOUNT_PUT = 1; static final int LOADER_IDENTITY_PUT = 2; @@ -113,6 +121,9 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack case R.string.menu_setup: onMenuSetup(); break; + case R.string.menu_debug: + onMenuDebug(); + break; } if (!item.isCheckable()) @@ -240,6 +251,7 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack drawerArray.add(new DrawerItem(ActivityView.this, R.string.menu_identities)); drawerArray.add(new DrawerItem(ActivityView.this, R.string.menu_theme, "dark".equals(prefs.getString("theme", "light")))); drawerArray.add(new DrawerItem(ActivityView.this, R.string.menu_setup)); + drawerArray.add(new DrawerItem(ActivityView.this, R.string.menu_debug)); drawerList.setAdapter(drawerArray); } @@ -284,6 +296,40 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack startActivity(new Intent(ActivityView.this, ActivitySetup.class)); } + private void onMenuDebug() { + executor.submit(new Runnable() { + @Override + public void run() { + try { + DB db = DB.getInstance(ActivityView.this); + EntityFolder drafts = db.folder().getPrimaryDraftFolder(); + if (drafts != null) { + StringBuilder info = Helper.getDebugInfo(); + + Address to = new InternetAddress("marcel+email@faircode.eu", "FairCode"); + + EntityMessage draft = new EntityMessage(); + draft.account = drafts.account; + draft.folder = drafts.id; + draft.to = MessageHelper.encodeAddresses(new Address[]{to}); + draft.subject = BuildConfig.APPLICATION_ID + " debug info"; + draft.body = "
" + info.toString().replaceAll("\\r?\\n", "
") + "
"; + draft.received = new Date().getTime(); + draft.seen = false; + draft.ui_seen = false; + draft.ui_hide = false; + draft.id = db.message().insertMessage(draft); + + startActivity(new Intent(ActivityView.this, ActivityCompose.class) + .putExtra("id", draft.id)); + } + } catch (Throwable ex) { + Log.w(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + } + } + }); + } + private class DrawerItem { private int id; private String title; diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 70521df9..9a91b48f 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -21,9 +21,15 @@ package eu.faircode.email; import android.content.Context; import android.content.res.Resources; +import android.os.Build; import android.text.TextUtils; +import android.util.Log; import android.util.TypedValue; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + public class Helper { static final String TAG = BuildConfig.APPLICATION_ID; @@ -60,4 +66,52 @@ public class Helper { } return sb.toString(); } + + static StringBuilder getDebugInfo() { + StringBuilder sb = new StringBuilder(); + + // Get version info + sb.append(String.format("%s: %s/%d\r\n", BuildConfig.APPLICATION_ID, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)); + sb.append(String.format("Android: %s (SDK %d)\r\n", Build.VERSION.RELEASE, Build.VERSION.SDK_INT)); + sb.append("\r\n"); + + // Get device info + sb.append(String.format("Brand: %s\r\n", Build.BRAND)); + sb.append(String.format("Manufacturer: %s\r\n", Build.MANUFACTURER)); + sb.append(String.format("Model: %s\r\n", Build.MODEL)); + sb.append(String.format("Product: %s\r\n", Build.PRODUCT)); + sb.append(String.format("Device: %s\r\n", Build.DEVICE)); + sb.append(String.format("Host: %s\r\n", Build.HOST)); + sb.append(String.format("Display: %s\r\n", Build.DISPLAY)); + sb.append(String.format("Id: %s\r\n", Build.ID)); + sb.append("\r\n"); + + // Get logcat + Process proc = null; + BufferedReader br = null; + try { + String[] cmd = new String[]{"logcat", "-d", "-v", "threadtime"}; + proc = Runtime.getRuntime().exec(cmd); + br = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line; + while ((line = br.readLine()) != null) + sb.append(line).append("\r\n"); + } catch (IOException ex) { + Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); + } finally { + if (br != null) + try { + br.close(); + } catch (IOException ignored) { + } + if (proc != null) + try { + proc.destroy(); + } catch (Throwable ex) { + Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); + } + } + + return sb; + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index abf79dab..0aa71ebb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ Identities Dark theme Setup + Debug info THIS SOFTWARE IS PROVIDED BY THE AUTHOR \'\'AS IS\'\' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. I agree