Commit a621f762 authored by fanghaitong's avatar fanghaitong

增加崩溃重启

parent 240ca20c
......@@ -63,6 +63,7 @@ dependencies {
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation project(path: ':printer')
implementation project(path: ':rebootoncrash')
// implementation 'com.android.tools.build:gradle:3.1.1'
// implementation 'com.android.tools.lint:lint-gradle:26.1.1'
implementation 'com.guolindev.permissionx:permissionx:1.5.1'
......
package com.qimai.android.widget
import android.app.Application
import com.qmai.rebootoncrash.config.CaocConfig
import zs.qimai.com.printer2.utils.PrintManagerUtils
class App : Application() {
override fun onCreate() {
super.onCreate()
PrintManagerUtils.getInstance().init(this)
CaocConfig.Builder.create()
.errorDrawable(R.mipmap.ic_launcher)
.restartActivity(TopBarActivity::class.java)
.apply()
}
}
\ No newline at end of file
......@@ -10,6 +10,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.qimai.android.widgetlib.popup.QmTipOverlayDrawable
import com.qimai.android.widgetlib.toast.HolderContext
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.RuntimeException
class MainActivity : AppCompatActivity() {
......@@ -57,6 +58,9 @@ class MainActivity : AppCompatActivity() {
findViewById<Button>(R.id.btn_log).setOnClickListener {
startActivity(Intent(this, LogActivity::class.java))
}
findViewById<Button>(R.id.btn_crash).setOnClickListener {
throw RuntimeException("主线程崩溃")
}
keyboard.btnText = "结账"
keyboard.invalidate()
}
......
......@@ -10,6 +10,7 @@ import android.os.Environment
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import com.eclipsesource.v8.JavaVoidCallback
import com.eclipsesource.v8.V8
import com.eclipsesource.v8.V8Array
......
......@@ -51,6 +51,11 @@
android:text="日志"
android:layout_width="match_parent"
android:layout_height="50dp" />
<Button
android:id="@+id/btn_crash"
android:text="崩溃"
android:layout_width="match_parent"
android:layout_height="50dp" />
<TextView
android:layout_width="match_parent"
......
/build
\ No newline at end of file
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'com.whl.gradle-publish-plugin'
}
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
group 'com.qmai.android.rebootoncrash'
version '1.0.2'
gradlePublish {
sourceJarEnabled = true
javaDocEnabled = false
signEnabled = false
releaseRepository {
url = "https://hub.zmcms.cn/repository/maven-releases/"
userName = "wanglei1"
password = "woshiwanglei123"
}
snapshotRepository {
url = "https://hub.zmcms.cn/repository/maven-snapshots/"
userName = "wanglei1"
password = "woshiwanglei123"
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.qmai.rebootoncrash
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.qmai.rebootoncrash.test", appContext.packageName)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.qmai.rebootoncrash">
<application>
<activity
android:name=".activity.DefaultErrorActivity"
android:process=":error_activity" />
<provider
android:name=".provider.CaocInitProvider"
android:authorities="${applicationId}.customactivityoncrashinitprovider"
android:exported="false"
android:initOrder="101" />
</application>
</manifest>
\ No newline at end of file
package com.qmai.rebootoncrash.activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.res.ResourcesCompat
import com.qmai.rebootoncrash.CustomActivityOnCrash
import com.qmai.rebootoncrash.R
import com.qmai.rebootoncrash.config.CaocConfig
class DefaultErrorActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//This is needed to avoid a crash if the developer has not specified
//an app-level theme that extends Theme.AppCompat
//This is needed to avoid a crash if the developer has not specified
//an app-level theme that extends Theme.AppCompat
val a = obtainStyledAttributes(R.styleable.AppCompatTheme)
if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
setTheme(R.style.Theme_AppCompat_Light_DarkActionBar)
}
a.recycle()
setContentView(R.layout.activity_default_error)
//Close/restart button logic:
//If a class if set, use restart.
//Else, use close and just finish the app.
//It is recommended that you follow this logic if implementing a custom error activity.
//Close/restart button logic:
//If a class if set, use restart.
//Else, use close and just finish the app.
//It is recommended that you follow this logic if implementing a custom error activity.
val restartButton =
findViewById<Button>(R.id.customactivityoncrash_error_activity_restart_button)
val config: CaocConfig? = CustomActivityOnCrash.getConfigFromIntent(intent)
if (config == null) {
//This should never happen - Just finish the activity to avoid a recursive crash.
finish()
return
}
if (config.isShowRestartButton() && config.restartActivityClass != null) {
restartButton.setText(R.string.customactivityoncrash_error_activity_restart_app)
restartButton.setOnClickListener {
CustomActivityOnCrash.restartApplication(
this@DefaultErrorActivity,
config
)
}
} else {
restartButton.setOnClickListener {
CustomActivityOnCrash.closeApplication(
this@DefaultErrorActivity,
config
)
}
}
val moreInfoButton =
findViewById<Button>(R.id.customactivityoncrash_error_activity_more_info_button)
if (config.isShowErrorDetails()) {
moreInfoButton.setOnClickListener { //We retrieve all the error data and show it
val dialog = AlertDialog.Builder(this@DefaultErrorActivity)
.setTitle(R.string.customactivityoncrash_error_activity_error_details_title)
.setMessage(
CustomActivityOnCrash.getAllErrorDetailsFromIntent(
this@DefaultErrorActivity,
intent
)
)
.setPositiveButton(
R.string.customactivityoncrash_error_activity_error_details_close,
null
)
.setNeutralButton(
R.string.customactivityoncrash_error_activity_error_details_copy
) { _, _ -> copyErrorToClipboard() }
.show()
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.BLACK);
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(Color.BLACK);
val textView = dialog.findViewById<TextView>(android.R.id.message)
textView?.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
resources.getDimension(R.dimen.customactivityoncrash_error_activity_error_details_text_size)
)
}
} else {
moreInfoButton.visibility = View.GONE
}
val defaultErrorActivityDrawableId: Int? = config.errorDrawable
val errorImageView =
findViewById<ImageView>(R.id.customactivityoncrash_error_activity_image)
if (defaultErrorActivityDrawableId != null) {
errorImageView.setImageDrawable(
ResourcesCompat.getDrawable(
resources, defaultErrorActivityDrawableId,
theme
)
)
}
}
private fun copyErrorToClipboard() {
val errorInformation: String = CustomActivityOnCrash.getAllErrorDetailsFromIntent(
this@DefaultErrorActivity,
intent
)
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
//Are there any devices without clipboard...?
if (clipboard != null) {
val clip = ClipData.newPlainText(
getString(R.string.customactivityoncrash_error_activity_error_details_clipboard_label),
errorInformation
)
clipboard.setPrimaryClip(clip)
Toast.makeText(
this@DefaultErrorActivity,
R.string.customactivityoncrash_error_activity_error_details_copied,
Toast.LENGTH_SHORT
).show()
}
}
}
\ No newline at end of file
package com.qmai.rebootoncrash.provider
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
import com.qmai.rebootoncrash.CustomActivityOnCrash
/**
*
* @author: tongzi
* @date: 2021/12/28
*
*/
class CaocInitProvider : ContentProvider() {
override fun onCreate(): Boolean {
CustomActivityOnCrash.install(context)
return false
}
override fun query(
uri: Uri,
projection: Array<String?>?,
selection: String?,
selectionArgs: Array<String?>?,
sortOrder: String?
): Cursor? {
return null
}
override fun getType(uri: Uri): String? {
return null
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
return null
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String?>?): Int {
return 0
}
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<String?>?
): Int {
return 0
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="UselessParent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="@dimen/customactivityoncrash_activity_vertical_margin"
android:paddingLeft="@dimen/customactivityoncrash_activity_horizontal_margin"
android:paddingRight="@dimen/customactivityoncrash_activity_horizontal_margin"
android:paddingTop="@dimen/customactivityoncrash_activity_vertical_margin">
<ImageView
android:id="@+id/customactivityoncrash_error_activity_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/customactivityoncrash_activity_vertical_margin"
android:gravity="center"
android:text="@string/customactivityoncrash_error_activity_error_occurred_explanation"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="@+id/customactivityoncrash_error_activity_restart_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/customactivityoncrash_activity_vertical_margin"
android:text="@string/customactivityoncrash_error_activity_close_app" />
<Button
android:id="@+id/customactivityoncrash_error_activity_more_info_button"
style="?borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/customactivityoncrash_error_activity_error_details"
android:textColor="?colorPrimary" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="customactivityoncrash_activity_horizontal_margin">16dp</dimen>
<dimen name="customactivityoncrash_activity_vertical_margin">16dp</dimen>
<dimen name="customactivityoncrash_error_activity_error_details_text_size">12sp</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="customactivityoncrash_error_activity_error_occurred_explanation">出小差啦~</string>
<string name="customactivityoncrash_error_activity_restart_app">重启 app</string>
<string name="customactivityoncrash_error_activity_close_app">关闭 app</string>
<string name="customactivityoncrash_error_activity_error_details">错误详情</string>
<string name="customactivityoncrash_error_activity_error_details_title">错误详情</string>
<string name="customactivityoncrash_error_activity_error_details_close">关闭</string>
<string name="customactivityoncrash_error_activity_error_details_copy">复制到粘贴板</string>
<string name="customactivityoncrash_error_activity_error_details_copied">已复制到粘贴板</string>
<string name="customactivityoncrash_error_activity_error_details_clipboard_label">错误详情</string>
</resources>
package com.qmai.rebootoncrash
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
\ No newline at end of file
......@@ -7,3 +7,4 @@ include ':wheelview'
include ':pickerview'
include ':dialog'
include ':websocket'
include ':rebootoncrash'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment