From f75cb3739def3c277dc902ef2fd79cbdfa5e6a52 Mon Sep 17 00:00:00 2001 From: oujunhui <313127320@qq.com> Date: Tue, 4 Aug 2020 20:39:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5Bugly=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E6=9B=B4=E6=96=B0SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 3 +- app/src/main/AndroidManifest.xml | 19 +++ .../erban/application/XChatApplication.java | 155 ++++++++++++++++-- .../erban/ui/setting/SettingActivity.java | 5 +- app/src/main/res/layout/upgrade_dialog.xml | 152 +++++++++++++++++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/xml/provider_paths.xml | 8 +- .../res/drawable-xhdpi/update_banner.webp | Bin 0 -> 6998 bytes core/build.gradle | 2 +- core/proguard-rules.pro | 4 + 10 files changed, 325 insertions(+), 24 deletions(-) create mode 100644 app/src/main/res/layout/upgrade_dialog.xml create mode 100644 app/src/module_upgrade_app/res/drawable-xhdpi/update_banner.webp diff --git a/app/build.gradle b/app/build.gradle index 52c3fca13..9c597f5b5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -193,7 +193,7 @@ def supportLibraryVersion = "27.1.1" def Lombok = "1.16.20" dependencies { - api fileTree(include: ['*.jar'], dir: 'libs') + api fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', { @@ -217,7 +217,6 @@ dependencies { api "com.darsh.multipleimageselect:multipleimageselect:1.0.4" api "me.shaohui.advancedluban:library:1.3.5" - api "com.tencent.bugly:crashreport:2.8.6" api "pl.droidsonroids.gif:android-gif-drawable:1.2.7" // api "com.jude:rollviewpager:1.4.6" implementation 'com.github.dongxingrong:RollViewPager:V1.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ee8ce2e58..2122c3b90 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -125,6 +125,18 @@ android:name="android.max_aspect" android:value="2.4" /> + + + + + + + { throwable.printStackTrace(); // print it @@ -231,11 +234,14 @@ public class XChatApplication extends Application { CrashReport.setAppChannel(this, channel); } - if (!isDebug()) { - CrashReport.initCrashReport(this.getApplicationContext(), XChatConstants.BUGLY_KEY_RELEASE, false); - } else { - CrashReport.initCrashReport(this.getApplicationContext(), XChatConstants.BUGLY_KEY_DEBUG, true); + + initBuglyUpdate(); + Bugly.init(this, BuildConfig.DEBUG ? XChatConstants.BUGLY_KEY_DEBUG : XChatConstants.BUGLY_KEY_RELEASE, BuildConfig.DEBUG); + if (!TextUtils.isEmpty(channel)) { + Bugly.setAppChannel(this, channel); } + + //生命周期监听 if (lifeManager == null) { lifeManager = new ActivityLifeManager(); @@ -339,6 +345,7 @@ public class XChatApplication extends Application { SDKOptions options = new SDKOptions(); options.disableAwake = true; options.asyncInitSDK = true; +// options.customPushContentType = ""; if (isDebug()) { options.checkManifestConfig = true; } @@ -416,9 +423,9 @@ public class XChatApplication extends Application { } else if (customAttachment instanceof OpenSignInAttachment) { return getContentFromOpenSignIn(customAttachment); } - else if (customAttachment.getFirst() == CUSTOM_MSG_PUSH_NOTIFIFICATION){ - return getContentRoomInvite(customAttachment); - } +// else if (customAttachment.getFirst() == CUSTOM_MSG_PUSH_NOTIFIFICATION){ +// return getContentRoomInvite(customAttachment); +// } } // 采用SDK默认文案 return "收到一条消息"; @@ -428,12 +435,15 @@ public class XChatApplication extends Application { public String makeTicker(String nick, IMMessage message) { if (message.getMsgType() == MsgTypeEnum.custom) { CustomAttachment customAttachment = (CustomAttachment) message.getAttachment(); - if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI) { - return message.getFromNick(); - } else if (customAttachment instanceof OpenSignInAttachment) { - return getContentFromOpenSignIn(customAttachment); - } else if (customAttachment instanceof RoomInviteFansAttachment){ - return getContentRoomInvite(customAttachment); + if (customAttachment != null){ + if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI) { + return message.getFromNick(); + } else if (customAttachment instanceof OpenSignInAttachment) { + return getContentFromOpenSignIn(customAttachment); + } +// else if (customAttachment instanceof RoomInviteFansAttachment){ +// return getContentRoomInvite(customAttachment); +// } } } // 采用SDK默认文案 @@ -459,7 +469,7 @@ public class XChatApplication extends Application { if (attachment instanceof RoomInviteFansAttachment) { RoomInviteFansInfo roomInviteFansInfo = ((RoomInviteFansAttachment) attachment).getRoomInviteFansInfo(); if (roomInviteFansInfo != null) { - result = roomInviteFansInfo.getPushTitle(); + result = roomInviteFansInfo.getData().getData().getContent(); } } if (TextUtils.isEmpty(result)) { @@ -486,6 +496,115 @@ public class XChatApplication extends Application { return packageName.equals(processName); } + /** + * 初始化bugly版本升级 + */ + private void initBuglyUpdate() { + /***** Beta高级设置 *****/ + /** + * true表示app启动自动初始化升级模块; + * false不会自动初始化; + * 开发者如果担心sdk初始化影响app启动速度,可以设置为false, + * 在后面某个时刻手动调用Beta.init(getApplicationContext(),false); + */ +// Beta.autoInit = true; + /** + * true表示初始化时自动检查升级; + * false表示不会自动检查升级,需要手动调用Beta.checkUpgrade()方法; + */ +// Beta.autoCheckUpgrade = true; + /** + * 设置升级检查周期为60s(默认检查周期为0s),60s内SDK不重复向后台请求策略); + */ +// Beta.upgradeCheckPeriod = 60 * 1000; + + /** + * 设置启动延时为1s(默认延时3s),APP启动1s后初始化SDK,避免影响APP启动速度; + */ + Beta.initDelay = 5 * 1000; + + /** + * 设置sd卡的Download为更新资源保存目录; + * 后续更新资源会保存在此目录,需要在manifest中添加WRITE_EXTERNAL_STORAGE权限; + */ +// Beta.storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + + /** + * 点击过确认的弹窗在APP下次启动自动检查更新时会再次显示; + */ + Beta.showInterruptedStrategy = true; + + /** + * 只允许在MainActivity上显示更新弹窗,其他activity上不显示弹窗; + * 不设置会默认所有activity都可以显示弹窗; + */ + Beta.canShowUpgradeActs.add(MainActivity.class); + + /** + * 自定义布局 + */ + Beta.upgradeDialogLayoutId = R.layout.upgrade_dialog;//关键代码写这个布局添加自己想要的 + + /** + * 设置自定义tip弹窗UI布局 + * 注意:因为要保持接口统一,需要用户在指定控件按照以下方式设置tag,否则会影响您的正常使用: + * 标题:beta_title,如:android:tag="beta_title" + * 提示信息:beta_tip_message 如: android:tag="beta_tip_message" + * 取消按钮:beta_cancel_button 如:android:tag="beta_cancel_button" + * 确定按钮:beta_confirm_button 如:android:tag="beta_confirm_button" + * 详见layout/tips_dialog.xml + */ + //Beta.tipsDialogLayoutId = R.layout.tips_dialog; + +// Beta.upgradeDialogLifecycleListener = new UILifecycleListener() { +// @Override +// public void onCreate(Context context, View view, UpgradeInfo upgradeInfo) { +// +// // 通过tag方式获取控件,并更改布局内容 +// TextView textView = (TextView) view.findViewWithTag("beta_upgrade_feature"); +// // 更多的操作:比如设置控件的点击事件 +// textView.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// +// } +// }); +// } +// +// @Override +// public void onStart(Context context, View view, UpgradeInfo upgradeInfo) { +// +// } +// +// @Override +// public void onResume(Context context, View view, UpgradeInfo upgradeInfo) { +// +// // 注:可通过这个回调方式获取布局的控件,如果设置了id,可通过findViewById方式获取,如果设置了tag,可以通过findViewWithTag,具体参考下面例子: +// +// +// } +// +// @Override +// public void onPause(Context context, View view, UpgradeInfo upgradeInfo) { +// +// } +// +// @Override +// public void onStop(Context context, View view, UpgradeInfo upgradeInfo) { +// +// } +// +// @Override +// public void onDestroy(Context context, View view, UpgradeInfo upgradeInfo) { +// +//// ToastUtils.showGravityToast(MyApplication.this,"更新后注意通知栏下载进度..."); +// } +// +// }; + + + } + /** * 获取当前进程名 * diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java index 132c8abc3..8103f085b 100644 --- a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java @@ -12,6 +12,7 @@ import android.text.TextUtils; import android.view.View; import com.netease.nim.uikit.StatusBarUtil; +import com.tencent.bugly.beta.Beta; import com.tongdaxing.erban.upgrade.AppUpgradeHelper; import com.trello.rxlifecycle3.android.ActivityEvent; import com.yizhuan.erban.R; @@ -174,8 +175,8 @@ public class SettingActivity extends BaseActivity implements View.OnClickListene startActivity(new Intent(getApplicationContext(), AboutActivity.class)); break; case R.id.rly_check://检查更新 - AppUpgradeHelper.checkAppUpgrade(this, true); - +// AppUpgradeHelper.checkAppUpgrade(this, true); + Beta.checkUpgrade(); break; case R.id.rly_lab: startActivity(new Intent(getApplicationContext(), LabActivity.class)); diff --git a/app/src/main/res/layout/upgrade_dialog.xml b/app/src/main/res/layout/upgrade_dialog.xml new file mode 100644 index 000000000..197a3ec64 --- /dev/null +++ b/app/src/main/res/layout/upgrade_dialog.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d31cfcdcd..4d0013064 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -535,5 +535,6 @@ #FF6B82 #4d000000 + #80000000 diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml index e7c873c61..b44f1fcdd 100644 --- a/app/src/main/res/xml/provider_paths.xml +++ b/app/src/main/res/xml/provider_paths.xml @@ -2,5 +2,11 @@ - + + + \ No newline at end of file diff --git a/app/src/module_upgrade_app/res/drawable-xhdpi/update_banner.webp b/app/src/module_upgrade_app/res/drawable-xhdpi/update_banner.webp new file mode 100644 index 0000000000000000000000000000000000000000..ba602f504c5b3efad1acd883a3f2148ecf74fb9d GIT binary patch literal 6998 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