Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 1 addition & 25 deletions longan/src/main/java/com/dylanc/longan/AppInitializer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,8 @@ class AppInitializer : Initializer<Unit> {
private var started = 0

override fun create(context: Context) {
application = context as Application
application.doOnActivityLifecycle(
onActivityCreated = { activity, _ ->
activityCache.add(activity)
},
onActivityStarted = { activity ->
started++
if (started == 1) {
onAppStatusChangedListener?.onForeground(activity)
}
},
onActivityStopped = { activity ->
started--
if (started == 0) {
onAppStatusChangedListener?.onBackground(activity)
}
},
onActivityDestroyed = { activity ->
activityCache.remove(activity)
}
)
Longan.initialize(context as Application)
}

override fun dependencies() = emptyList<Class<Initializer<*>>>()

companion object {
internal var onAppStatusChangedListener: OnAppStatusChangedListener? = null
}
}
5 changes: 2 additions & 3 deletions longan/src/main/java/com/dylanc/longan/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import android.content.res.Configuration.UI_MODE_NIGHT_MASK
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Process
import android.provider.Settings
import androidx.core.content.pm.PackageInfoCompat

Expand Down Expand Up @@ -67,7 +66,7 @@ fun relaunchApp(killProcess: Boolean = true) =
application.packageManager.getLaunchIntentForPackage(packageName)?.let {
it.addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_CLEAR_TOP)
startActivity(it)
if (killProcess) Process.killProcess(Process.myPid())
if (killProcess) killProcess()
}

fun doOnAppStatusChanged(onForeground: ((Activity) -> Unit)? = null, onBackground: ((Activity) -> Unit)? = null) =
Expand All @@ -82,7 +81,7 @@ fun doOnAppStatusChanged(onForeground: ((Activity) -> Unit)? = null, onBackgroun
})

fun doOnAppStatusChanged(listener: OnAppStatusChangedListener) {
AppInitializer.onAppStatusChangedListener = listener
Longan.onAppStatusChangedListener = listener
}

interface OnAppStatusChangedListener {
Expand Down
48 changes: 48 additions & 0 deletions longan/src/main/java/com/dylanc/longan/Longan.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2021. Reone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.dylanc.longan

import android.app.Application

object Longan {
private var started = 0
internal var onAppStatusChangedListener: OnAppStatusChangedListener? = null

fun initialize(app: Application) {
application = app
application.doOnActivityLifecycle(
onActivityCreated = { activity, _ ->
activityCache.add(activity)
},
onActivityStarted = { activity ->
started++
if (started == 1) {
onAppStatusChangedListener?.onForeground(activity)
}
},
onActivityStopped = { activity ->
started--
if (started == 0) {
onAppStatusChangedListener?.onBackground(activity)
}
},
onActivityDestroyed = { activity ->
activityCache.remove(activity)
}
)
}
}
66 changes: 66 additions & 0 deletions longan/src/main/java/com/dylanc/longan/Process.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2021. Reone
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@file:Suppress("unused")

package com.dylanc.longan

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.Application
import android.content.Context
import android.os.Build
import android.os.Process

fun killProcess(pid: Int = Process.myPid()) {
Process.killProcess(pid)
}

val Context.currentProcessName: String?
get() {
if (!cacheName.isNullOrEmpty()) {
return cacheName
}
cacheName = nameFromApplication ?: nameFromActivityThread ?: nameFromActivityManager
return cacheName
}

private var cacheName: String? = null
private val nameFromApplication: String?
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) Application.getProcessName() else null
private val nameFromActivityThread: String?
@SuppressLint("PrivateApi")
get() {
return runCatching {
var processName: String?
Class.forName("android.app.ActivityThread", false, Application::class.java.classLoader)
.getDeclaredMethod("currentProcessName", *arrayOfNulls<Class<*>?>(0)).let {
it.isAccessible = true
processName = it.invoke(null, *arrayOfNulls(0)) as String
}
return processName
}.getOrNull()
}
private val Context.nameFromActivityManager: String?
get() {
val pid = Process.myPid()
(context.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager)?.runningAppProcesses?.forEach {
if (it.pid == pid) {
return it.processName
}
}
return null
}
19 changes: 11 additions & 8 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,22 @@
</activity>
<activity android:name=".ui.DialogsActivity" />
<activity
android:name=".ui.SpannableStringActivity"
android:exported="true"></activity>
android:name=".ui.SpannableStringActivity"
android:exported="true" />
<activity android:name=".ui.InputTextActivity" />
<activity android:name=".ui.ActivityResultActivity" />
<activity
android:name=".ui.ProcessActivity"
android:process=":other" />

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>

Expand Down
7 changes: 4 additions & 3 deletions sample/src/main/java/com/dylanc/longan/sample/App.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.dylanc.longan.sample

import android.app.Application
import com.dylanc.longan.fileProviderAuthority
import com.dylanc.longan.initLogger
import com.dylanc.longan.saveCrashLogLocally
import com.dylanc.longan.*

/**
* @author Dylan Cai
Expand All @@ -12,6 +10,9 @@ class App : Application() {

override fun onCreate() {
super.onCreate()
if (currentProcessName != BuildConfig.APPLICATION_ID) {
Longan.initialize(this)
}
initLogger(BuildConfig.DEBUG)
saveCrashLogLocally()
fileProviderAuthority = "$packageName.provider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.dylanc.viewbinding.binding
class MainActivity : AppCompatActivity() {

private val binding: ActivityRecyclerViewBinding by binding()
private val items = listOf(R.string.dialogs, R.string.spannable_string, R.string.activity_result)
private val items = listOf(R.string.dialogs, R.string.spannable_string, R.string.activity_result, R.string.activity_process)
private val adapter by simpleIntListAdapter<ItemTextBinding> {
tvTitle.setText(it)
}
Expand All @@ -27,6 +27,7 @@ class MainActivity : AppCompatActivity() {
R.string.dialogs -> startActivity<DialogsActivity>()
R.string.spannable_string -> startActivity<SpannableStringActivity>()
R.string.activity_result -> startActivity<ActivityResultActivity>()
R.string.activity_process -> startActivity<ProcessActivity>()
}
}
pressBackTwiceToExitApp(R.string.exit_app)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.dylanc.longan.sample.ui

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.dylanc.longan.currentProcessName
import com.dylanc.longan.packageInfo
import com.dylanc.longan.sample.databinding.ActivityRecyclerViewBinding
import com.dylanc.longan.sample.databinding.ItemTextBinding
import com.dylanc.viewbinding.base.simpleStringListAdapter
import com.dylanc.viewbinding.binding

class ProcessActivity : AppCompatActivity() {

private val binding: ActivityRecyclerViewBinding by binding()
private val items = listOf(packageInfo.packageName, packageInfo.versionName, "process: $currentProcessName")
private val adapter by simpleStringListAdapter<ItemTextBinding> {
tvTitle.text = it
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.recyclerView.adapter = adapter
adapter.submitList(items)
}
}
1 change: 1 addition & 0 deletions sample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<string name="dialogs">Dialogs</string>
<string name="spannable_string">SpannableString</string>
<string name="activity_result">ActivityResult</string>
<string name="activity_process">OtherProcessInit</string>
<string name="selector">selector</string>
<string name="single_choice_selector">single choice selector</string>
<string name="multi_choice_selector">multi choice selector</string>
Expand Down