diff --git a/appbase/src/beta/AndroidManifest.xml b/appbase/src/beta/AndroidManifest.xml index 26dcaf0..f8f4deb 100644 --- a/appbase/src/beta/AndroidManifest.xml +++ b/appbase/src/beta/AndroidManifest.xml @@ -10,6 +10,14 @@ tools:replace="android:icon" android:icon="@drawable/ic_winboll_beta"> + + + + \ No newline at end of file diff --git a/appbase/src/beta/res/values/strings.xml b/appbase/src/beta/res/values/strings.xml index 49fc4c9..7aa8e1f 100644 --- a/appbase/src/beta/res/values/strings.xml +++ b/appbase/src/beta/res/values/strings.xml @@ -2,5 +2,8 @@ APPBase+ + 邮件设置 + 异常邮件接收设置 + 快捷方式不可用 diff --git a/appbase/src/beta/res/xml/shortcuts.xml b/appbase/src/beta/res/xml/shortcuts.xml new file mode 100644 index 0000000..dc09e5c --- /dev/null +++ b/appbase/src/beta/res/xml/shortcuts.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/App.java b/appbase/src/main/java/cc/winboll/studio/appbase/App.java index 39c7e3c..ed1c15c 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/App.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/App.java @@ -55,7 +55,9 @@ public class App extends GlobalApplication { this, getPackageName(), stackTraceStr, - CrashActivity.class + CrashActivity.class, + "APPBase", + "studio@winboll.cc" ); } } diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java b/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java index b26c08e..be83a7f 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java @@ -1,12 +1,8 @@ package cc.winboll.studio.appbase; import android.app.Activity; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.ShortcutInfo; -import android.content.pm.ShortcutManager; -import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Bundle; import android.view.Menu; @@ -69,31 +65,11 @@ public class MainActivity extends Activity { /** * 注册桌面图标静态快捷方式 * 长按桌面图标后显示快捷菜单,点击可直接打开异常邮件接收设置页面 + * 静态快捷方式已通过 res/xml/shortcuts.xml 配置,此处无需动态注册 */ private void setupShortcuts() { - if (!"cc.winboll.studio.appbase.beta".equals(getPackageName())) { - return; - } - - ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); - if (shortcutManager == null) { - return; - } - - Intent intent = new Intent(this, APPExcetionMailSettingsActivity.class); - intent.setAction(Intent.ACTION_VIEW); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "exception_mail_settings") - .setShortLabel("邮件设置") - .setLongLabel("异常邮件接收设置") - .setIcon(Icon.createWithResource(this, R.drawable.ic_winboll)) - .setIntent(intent) - .build(); - - shortcutManager.setDynamicShortcuts( - java.util.Arrays.asList(shortcut) - ); + // 静态快捷方式仅在 beta 渠道生效,通过 AndroidManifest.xml 中的 meta-data 配置 + // beta 渠道使用 res/xml/shortcuts.xml 定义快捷方式 } /** diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java index 06f9d73..29b10de 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java @@ -67,11 +67,15 @@ public class CrashHandleNotifyUtils { * @param hostPackageName 宿主应用包名 * @param errorLog 崩溃日志内容 * @param reportCrashActivity 崩溃详情跳转Activity类 + * @param appAPKName 应用APK名称(用于邮件标题) + * @param emailTo 邮件接收者地址 */ public static void handleUncaughtException(final android.app.Application hostApp, final String hostPackageName, final String errorLog, - final Class reportCrashActivity) { + final Class reportCrashActivity, + final String appAPKName, + final String emailTo) { LogUtils.d(TAG, "handleUncaughtException 进入方法"); if (hostApp == null || TextUtils.isEmpty(hostPackageName) || TextUtils.isEmpty(errorLog)) { LogUtils.e(TAG, "handleUncaughtException 参数为空校验不通过"); @@ -87,7 +91,14 @@ public class CrashHandleNotifyUtils { sCrashLogCacheFilePath = crashLogFilePath; final Intent shareIntent = new Intent(hostApp, ShareLogActivity.class); shareIntent.putExtra(ShareLogActivity.EXTRA_CRASH_LOG_FILEPATH, crashLogFilePath); - shareIntent.putExtra(ShareLogActivity.EXTRA_CRASH_LOG_SUBJECT, "崩溃日志"); + String subject = "崩溃日志"; + if (appAPKName != null && !appAPKName.isEmpty()) { + subject = appAPKName + " - 崩溃日志"; + } + shareIntent.putExtra(ShareLogActivity.EXTRA_CRASH_LOG_SUBJECT, subject); + if (emailTo != null && !emailTo.isEmpty()) { + shareIntent.putExtra(ShareLogActivity.EXTRA_CRASH_LOG_EMAIL_TO, emailTo); + } shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); final PendingIntent sharePendingIntent = createSharePendingIntent(hostApp, shareIntent); sendCrashNotification(hostApp, hostPackageName, hostAppName, errorLog, reportCrashActivity, sharePendingIntent); @@ -109,7 +120,21 @@ public class CrashHandleNotifyUtils { LogUtils.w(TAG, "未携带宿主包名,默认使用应用自身包名"); } final String errorLog = intent.getStringExtra(CrashHandler.EXTRA_CRASH_LOG); - handleUncaughtException(hostApp, hostPackageName, errorLog, reportCrashActivity); + handleUncaughtException(hostApp, hostPackageName, errorLog, reportCrashActivity, null, null); + } + + /** + * 重载兼容方法:适配原有调用方式 + * @param hostApp 宿主Application实例 + * @param hostPackageName 宿主应用包名 + * @param errorLog 崩溃日志内容 + * @param reportCrashActivity 崩溃详情跳转Activity类 + */ + public static void handleUncaughtException(final android.app.Application hostApp, + final String hostPackageName, + final String errorLog, + final Class reportCrashActivity) { + handleUncaughtException(hostApp, hostPackageName, errorLog, reportCrashActivity, null, null); } /** @@ -355,7 +380,7 @@ public class CrashHandleNotifyUtils { .setWhen(System.currentTimeMillis()) .setPriority(Notification.PRIORITY_DEFAULT); if (shareIntent != null) { - builder.addAction(android.R.drawable.ic_menu_send, "分享日志", shareIntent); + builder.addAction(android.R.drawable.ic_menu_send, "发送日志给开发组", shareIntent); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return builder.build(); diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/ShareLogActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/ShareLogActivity.java index a9edd48..b7a7662 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/ShareLogActivity.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/ShareLogActivity.java @@ -2,6 +2,9 @@ package cc.winboll.studio.libappbase.utils; import android.app.Activity; import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; import android.util.Log; import android.widget.Toast; @@ -21,6 +24,7 @@ public class ShareLogActivity extends Activity { public static final String TAG = "ShareLogActivity"; public static final String EXTRA_CRASH_LOG_FILEPATH = "crash_log_filepath"; public static final String EXTRA_CRASH_LOG_SUBJECT = "crash_log_subject"; + public static final String EXTRA_CRASH_LOG_EMAIL_TO = "crash_log_email_to"; @Override protected void onCreate(final Bundle savedInstanceState) { @@ -43,10 +47,40 @@ public class ShareLogActivity extends Activity { } final String subject = intent.getStringExtra(EXTRA_CRASH_LOG_SUBJECT); - handleShareCrashLog(crashLogFilePath, subject); + final String emailTo = intent.getStringExtra(EXTRA_CRASH_LOG_EMAIL_TO); + handleShareCrashLog(crashLogFilePath, subject, emailTo); } - private void handleShareCrashLog(final String crashLogFilePath, final String subject) { + private String getAppInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("========== 应用信息 ==========\n"); + try { + PackageInfo pkgInfo = getPackageManager().getPackageInfo(getPackageName(), 0); + sb.append("应用包名: ").append(getPackageName()).append("\n"); + sb.append("版本名称: ").append(pkgInfo.versionName).append("\n"); + sb.append("版本号: ").append(pkgInfo.versionCode).append("\n"); + } catch (PackageManager.NameNotFoundException e) { + sb.append("应用包名: ").append(getPackageName()).append("\n"); + sb.append("版本信息: 获取失败\n"); + } + sb.append("\n"); + return sb.toString(); + } + + private String getDeviceInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("========== 设备信息 ==========\n"); + sb.append("设备制造商: ").append(Build.MANUFACTURER).append("\n"); + sb.append("设备型号: ").append(Build.MODEL).append("\n"); + sb.append("设备名称: ").append(Build.DEVICE).append("\n"); + sb.append("Android版本: ").append(Build.VERSION.RELEASE).append("\n"); + sb.append("Android API: ").append(Build.VERSION.SDK_INT).append("\n"); + sb.append("系统指纹: ").append(Build.FINGERPRINT).append("\n"); + sb.append("\n"); + return sb.toString(); + } + + private void handleShareCrashLog(final String crashLogFilePath, final String subject, final String emailTo) { Log.d(TAG, "handleShareCrashLog crashLogFilePath = " + crashLogFilePath); final File crashLogFile = new File(crashLogFilePath); @@ -67,16 +101,25 @@ public class ShareLogActivity extends Activity { } final String logContent = sb.toString(); - final Intent shareIntent = new Intent(Intent.ACTION_SEND); - shareIntent.setType("text/plain"); - shareIntent.putExtra(Intent.EXTRA_TEXT, logContent); + final StringBuilder emailContent = new StringBuilder(); + emailContent.append(getAppInfo()); + emailContent.append(getDeviceInfo()); + emailContent.append("========== 崩溃日志 ==========\n"); + emailContent.append(logContent); + + final Intent shareIntent = new Intent(Intent.ACTION_SENDTO); + shareIntent.setData(android.net.Uri.parse("mailto:")); + shareIntent.putExtra(Intent.EXTRA_TEXT, emailContent.toString()); if (subject != null && !subject.isEmpty()) { shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject); } else { shareIntent.putExtra(Intent.EXTRA_SUBJECT, "崩溃日志"); } + if (emailTo != null && !emailTo.isEmpty()) { + shareIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{emailTo}); + } - startActivity(Intent.createChooser(shareIntent, "分享日志到")); + startActivity(Intent.createChooser(shareIntent, "发送日志到")); Log.d(TAG, "handleShareCrashLog 分享成功"); } catch (Exception e) { Log.e(TAG, "handleShareCrashLog 异常", e);