|
@ -96,200 +96,7 @@ public class FragmentAbout extends FragmentEx { |
|
|
@Override |
|
|
@Override |
|
|
protected Long onLoad(Context context, Bundle args) |
|
|
protected Long onLoad(Context context, Bundle args) |
|
|
throws UnsupportedEncodingException { |
|
|
throws UnsupportedEncodingException { |
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
|
Locale locale = Locale.US; |
|
|
|
|
|
|
|
|
|
|
|
sb.append(context.getString(R.string.title_debug_info_remark) + "\n\n\n\n"); |
|
|
|
|
|
|
|
|
|
|
|
// Get version info |
|
|
|
|
|
sb.append( |
|
|
|
|
|
String.format( |
|
|
|
|
|
locale, |
|
|
|
|
|
"%s: %s %s/%s%s\r\n", |
|
|
|
|
|
context.getString(R.string.app_name), |
|
|
|
|
|
BuildConfig.APPLICATION_ID, |
|
|
|
|
|
BuildConfig.VERSION_NAME, |
|
|
|
|
|
Helper.hasValidFingerprint(context) ? "1" : "3", |
|
|
|
|
|
"+")); |
|
|
|
|
|
sb.append( |
|
|
|
|
|
String.format( |
|
|
|
|
|
locale, |
|
|
|
|
|
"Android: %s (SDK %d)\r\n", |
|
|
|
|
|
Build.VERSION.RELEASE, |
|
|
|
|
|
Build.VERSION.SDK_INT)); |
|
|
|
|
|
sb.append("\r\n"); |
|
|
|
|
|
|
|
|
|
|
|
// Get device info |
|
|
|
|
|
sb.append(String.format(locale, "Brand: %s\r\n", Build.BRAND)); |
|
|
|
|
|
sb.append(String.format(locale, "Manufacturer: %s\r\n", Build.MANUFACTURER)); |
|
|
|
|
|
sb.append(String.format(locale, "Model: %s\r\n", Build.MODEL)); |
|
|
|
|
|
sb.append(String.format(locale, "Product: %s\r\n", Build.PRODUCT)); |
|
|
|
|
|
sb.append(String.format(locale, "Device: %s\r\n", Build.DEVICE)); |
|
|
|
|
|
sb.append(String.format(locale, "Host: %s\r\n", Build.HOST)); |
|
|
|
|
|
sb.append(String.format(locale, "Display: %s\r\n", Build.DISPLAY)); |
|
|
|
|
|
sb.append(String.format(locale, "Id: %s\r\n", Build.ID)); |
|
|
|
|
|
sb.append("\r\n"); |
|
|
|
|
|
|
|
|
|
|
|
boolean ignoring = CompatibilityUtils.isIgnoringOptimizations(getContext()); |
|
|
|
|
|
sb.append(String.format(locale, "Battery optimizations: %b\r\n", !ignoring)); |
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { |
|
|
|
|
|
UsageStatsManager usm = getContext().getSystemService(UsageStatsManager.class); |
|
|
|
|
|
int bucket = usm.getAppStandbyBucket(); |
|
|
|
|
|
sb.append(String.format(locale, "Standby bucket: %d\r\n", bucket)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { |
|
|
|
|
|
ConnectivityManager cm = getContext().getSystemService(ConnectivityManager.class); |
|
|
|
|
|
boolean saving = |
|
|
|
|
|
(cm.getRestrictBackgroundStatus() |
|
|
|
|
|
== ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED); |
|
|
|
|
|
sb.append(String.format(locale, "Data saving: %b\r\n", saving)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sb.append("\r\n"); |
|
|
|
|
|
|
|
|
|
|
|
String body = "<pre>" + sb.toString().replaceAll("\\r?\\n", "<br />") + "</pre>"; |
|
|
|
|
|
|
|
|
|
|
|
EntityMessage draft; |
|
|
|
|
|
DB db = DB.getInstance(context); |
|
|
|
|
|
try { |
|
|
|
|
|
db.beginTransaction(); |
|
|
|
|
|
|
|
|
|
|
|
EntityFolder drafts = db.folder().getPrimaryDrafts(); |
|
|
|
|
|
if (drafts == null) { |
|
|
|
|
|
throw new IllegalArgumentException( |
|
|
|
|
|
context.getString(R.string.title_no_primary_drafts)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
draft = new EntityMessage(); |
|
|
|
|
|
draft.account = drafts.account; |
|
|
|
|
|
draft.folder = drafts.id; |
|
|
|
|
|
draft.msgid = EntityMessage.generateMessageId(); |
|
|
|
|
|
draft.to = new Address[] {Helper.myAddress()}; |
|
|
|
|
|
draft.subject = |
|
|
|
|
|
context.getString(R.string.app_name) |
|
|
|
|
|
+ " " |
|
|
|
|
|
+ BuildConfig.VERSION_NAME |
|
|
|
|
|
+ " debug info"; |
|
|
|
|
|
draft.content = true; |
|
|
|
|
|
draft.received = new Date().getTime(); |
|
|
|
|
|
draft.seen = false; |
|
|
|
|
|
draft.ui_seen = false; |
|
|
|
|
|
draft.flagged = false; |
|
|
|
|
|
draft.ui_flagged = false; |
|
|
|
|
|
draft.ui_hide = false; |
|
|
|
|
|
draft.ui_found = false; |
|
|
|
|
|
draft.ui_ignored = false; |
|
|
|
|
|
draft.id = db.message().insertMessage(draft); |
|
|
|
|
|
draft.write(context, body); |
|
|
|
|
|
|
|
|
|
|
|
// Attach recent log |
|
|
|
|
|
{ |
|
|
|
|
|
EntityAttachment log = new EntityAttachment(); |
|
|
|
|
|
log.message = draft.id; |
|
|
|
|
|
log.sequence = 1; |
|
|
|
|
|
log.name = "log.txt"; |
|
|
|
|
|
log.type = "text/plain"; |
|
|
|
|
|
log.size = null; |
|
|
|
|
|
log.progress = 0; |
|
|
|
|
|
log.id = db.attachment().insertAttachment(log); |
|
|
|
|
|
|
|
|
|
|
|
OutputStream os = null; |
|
|
|
|
|
File file = EntityAttachment.getFile(context, log.id); |
|
|
|
|
|
try { |
|
|
|
|
|
os = new BufferedOutputStream(new FileOutputStream(file)); |
|
|
|
|
|
|
|
|
|
|
|
int size = 0; |
|
|
|
|
|
long from = new Date().getTime() - 24 * 3600 * 1000L; |
|
|
|
|
|
DateFormat DF = SimpleDateFormat.getTimeInstance(); |
|
|
|
|
|
for (EntityLog entry : db.log().getLogs(from)) { |
|
|
|
|
|
String line = String.format("%s %s\r\n", DF.format(entry.time), entry.data); |
|
|
|
|
|
byte[] bytes = line.getBytes(); |
|
|
|
|
|
os.write(bytes); |
|
|
|
|
|
size += bytes.length; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.size = size; |
|
|
|
|
|
log.progress = null; |
|
|
|
|
|
log.available = true; |
|
|
|
|
|
db.attachment().updateAttachment(log); |
|
|
|
|
|
} finally { |
|
|
|
|
|
if (os != null) { |
|
|
|
|
|
os.close(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Attach logcat |
|
|
|
|
|
{ |
|
|
|
|
|
EntityAttachment logcat = new EntityAttachment(); |
|
|
|
|
|
logcat.message = draft.id; |
|
|
|
|
|
logcat.sequence = 2; |
|
|
|
|
|
logcat.name = "logcat.txt"; |
|
|
|
|
|
logcat.type = "text/plain"; |
|
|
|
|
|
logcat.size = null; |
|
|
|
|
|
logcat.progress = 0; |
|
|
|
|
|
logcat.id = db.attachment().insertAttachment(logcat); |
|
|
|
|
|
|
|
|
|
|
|
Process proc = null; |
|
|
|
|
|
BufferedReader br = null; |
|
|
|
|
|
OutputStream os = null; |
|
|
|
|
|
File file = EntityAttachment.getFile(context, logcat.id); |
|
|
|
|
|
try { |
|
|
|
|
|
os = new BufferedOutputStream(new FileOutputStream(file)); |
|
|
|
|
|
|
|
|
|
|
|
String[] cmd = |
|
|
|
|
|
new String[] { |
|
|
|
|
|
"logcat", |
|
|
|
|
|
"-d", |
|
|
|
|
|
"-v", |
|
|
|
|
|
"threadtime", |
|
|
|
|
|
// "-t", "1000", |
|
|
|
|
|
Helper.TAG + ":I" |
|
|
|
|
|
}; |
|
|
|
|
|
proc = Runtime.getRuntime().exec(cmd); |
|
|
|
|
|
br = new BufferedReader(new InputStreamReader(proc.getInputStream())); |
|
|
|
|
|
|
|
|
|
|
|
int size = 0; |
|
|
|
|
|
String line; |
|
|
|
|
|
while ((line = br.readLine()) != null) { |
|
|
|
|
|
line += "\r\n"; |
|
|
|
|
|
byte[] bytes = line.getBytes(); |
|
|
|
|
|
os.write(bytes); |
|
|
|
|
|
size += bytes.length; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
logcat.size = size; |
|
|
|
|
|
logcat.progress = null; |
|
|
|
|
|
logcat.available = true; |
|
|
|
|
|
db.attachment().updateAttachment(logcat); |
|
|
|
|
|
} finally { |
|
|
|
|
|
if (os != null) { |
|
|
|
|
|
os.close(); |
|
|
|
|
|
} |
|
|
|
|
|
if (br != null) { |
|
|
|
|
|
br.close(); |
|
|
|
|
|
} |
|
|
|
|
|
if (proc != null) { |
|
|
|
|
|
proc.destroy(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
EntityOperation.queue(db, draft, EntityOperation.ADD); |
|
|
|
|
|
|
|
|
|
|
|
db.setTransactionSuccessful(); |
|
|
|
|
|
} catch (IOException ex) { |
|
|
|
|
|
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); |
|
|
|
|
|
return null; |
|
|
return null; |
|
|
} finally { |
|
|
|
|
|
db.endTransaction(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
EntityOperation.process(context); |
|
|
|
|
|
|
|
|
|
|
|
return draft.id; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|