Skip to content

Commit

Permalink
load activities of disabled apps
Browse files Browse the repository at this point in the history
  • Loading branch information
sdex committed Nov 14, 2022
1 parent 3150c66 commit 4513356
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 73 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 5.2.0 (14 Nov 2022)
- Load activities of disabled apps

## 5.1.1 (23 Oct 2022)
- Make saving intent launch to history optional

Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
applicationId "com.activitymanager"
minSdkVersion 21
targetSdkVersion 33
versionCode 511
versionName "5.1.1"
versionCode 520
versionName "5.2.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.sdex.activityrunner.db.cache.ApplicationModel
import com.sdex.activityrunner.extensions.addDividerItemDecoration
import com.sdex.activityrunner.extensions.serializable
import com.sdex.activityrunner.preferences.AppPreferences
import com.sdex.activityrunner.util.IntentUtils
import com.sdex.activityrunner.util.UIUtils
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
Expand Down Expand Up @@ -63,22 +62,15 @@ class ActivitiesListActivity : BaseActivity() {

viewModel.getItems(app.packageName).observe(this) {
adapter.submitList(it)
if (app.enabled) {
val size = it.size
setSubtitle(resources.getQuantityString(R.plurals.activities_count, size, size))
binding.empty.isVisible = (size == 0 && searchText == null)
}
binding.disabled.isVisible = !app.enabled
val size = it.size
setSubtitle(resources.getQuantityString(R.plurals.activities_count, size, size))
binding.empty.isVisible = (size == 0 && searchText == null)
}

binding.showNonExported.setOnClickListener {
viewModel.reloadItems(app.packageName, true)
}

binding.openAppInfo.setOnClickListener {
IntentUtils.openApplicationInfo(this, app.packageName)
}

if (!appPreferences.showNotExported
&& !appPreferences.isNotExportedDialogShown
&& appPreferences.appOpenCounter > 3
Expand All @@ -89,15 +81,6 @@ class ActivitiesListActivity : BaseActivity() {
}
}

override fun onStart() {
super.onStart()
val enabled = viewModel.isAppEnabled(app.packageName)
if (enabled != app.enabled) {
app = app.copy(enabled = enabled)
viewModel.reloadItems(app.packageName)
}
}

public override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString(STATE_SEARCH_TEXT, searchText)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.sdex.activityrunner.app

import androidx.annotation.WorkerThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.*
import com.sdex.activityrunner.preferences.AppPreferences
import com.sdex.activityrunner.util.PackageInfoProvider
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -30,10 +27,6 @@ class ActivitiesListViewModel @Inject constructor(
return liveData
}

fun reloadItems(packageName: String) {
reloadItems(packageName, appPreferences.showNotExported)
}

fun reloadItems(packageName: String, showNotExported: Boolean) {
viewModelScope.launch(Dispatchers.IO) {
list = getActivitiesList(packageName, showNotExported)
Expand All @@ -58,10 +51,6 @@ class ActivitiesListViewModel @Inject constructor(
}
}

fun isAppEnabled(packageName: String): Boolean {
return packageInfoProvider.isAppEnabled(packageName)
}

@WorkerThread
private fun getActivitiesList(packageName: String, showNotExported: Boolean) = try {
packageInfoProvider.getActivities(packageName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ data class ActivityModel(
val packageName: String,
val className: String,
val label: String?,
val exported: Boolean
var exported: Boolean,
var enabled: Boolean,
) : Serializable {

val componentName: ComponentName
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.sdex.activityrunner.manifest

import com.sdex.activityrunner.app.ActivityModel
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import timber.log.Timber
import java.io.StringReader

class ManifestParser(
private val manifestXml: String
) {

fun getActivities(packageName: String): List<ActivityModel> {
val activities = mutableListOf<ActivityModel>()
try {
val factory = XmlPullParserFactory.newInstance()
factory.isNamespaceAware = true
val parser = factory.newPullParser()
parser.setInput(StringReader(manifestXml))
var eventType = parser.eventType
var activityModel: ActivityModel? = null
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG &&
(parser.name == "activity" || parser.name == "activity-alias")
) {
val className = parser.getAttributeValue(null, "name")
val activityName = className.split(".").last()
val activityLabel = parser.getAttributeValue(null, "label")
val enabledAttributeValue = parser.getAttributeValue(null, "enabled")
val enabled = if (enabledAttributeValue.isNullOrEmpty()) {
true
} else {
java.lang.Boolean.parseBoolean(enabledAttributeValue)
}
val model = ActivityModel(
activityName,
packageName,
className,
activityLabel,
exported = false,
enabled
)

val exportedAttributeValue = parser.getAttributeValue(null, "exported")
if (exportedAttributeValue.isNullOrEmpty()) {
// if the activity has "intent-filter" the exported is true, otherwise false
activityModel = model
} else {
model.exported = java.lang.Boolean.parseBoolean(exportedAttributeValue)
activities.add(model)
}
} else if (eventType == XmlPullParser.START_TAG &&
parser.name == "intent-filter" && activityModel != null
) {
activityModel.exported = true
activities.add(activityModel)
activityModel = null
} else if (eventType == XmlPullParser.END_TAG &&
(parser.name == "activity" || parser.name == "activity-alias") &&
activityModel != null
) {
activityModel.exported = false
activities.add(activityModel)
activityModel = null
}
eventType = parser.next()
}
} catch (e: Exception) {
Timber.e(e)
}
return activities
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.sdex.activityrunner.util
import android.content.Context
import android.content.pm.ActivityInfo
import com.sdex.activityrunner.app.ActivityModel
import com.sdex.activityrunner.manifest.ManifestParser
import net.dongliu.apk.parser.ApkFile

class PackageInfoProvider(
context: Context,
Expand All @@ -11,20 +13,24 @@ class PackageInfoProvider(
private val packageManager = context.packageManager

fun getActivities(packageName: String): List<ActivityModel> {
return getPackageInfo(packageManager, packageName).activities
.map { it.toActivityModel() }
}

fun isAppEnabled(packageName: String): Boolean {
val packageInfo = getPackageInfo(packageManager, packageName)
return packageInfo.applicationInfo.enabled
if (packageInfo.applicationInfo.enabled) {
return packageInfo.activities.map { it.toActivityModel() }
} else {
val publicSourceDir = packageInfo.applicationInfo.publicSourceDir
ApkFile(publicSourceDir).use { apkFile ->
val manifestParser = ManifestParser(apkFile.manifestXml)
return manifestParser.getActivities(packageName)
}
}
}

private fun ActivityInfo.toActivityModel() = ActivityModel(
name.split(".").last(),
packageName,
name,
loadLabel(packageManager).toString(),
exported && isEnabled
exported,
enabled,
)
}
29 changes: 1 addition & 28 deletions app/src/main/res/layout/activity_activities_list.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="gone">
tools:visibility="visible">

<TextView
android:layout_width="wrap_content"
Expand All @@ -58,33 +58,6 @@

</LinearLayout>

<LinearLayout
android:id="@+id/disabled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="16dp"
android:text="@string/application_disabled_description"
android:textAppearance="?attr/textAppearanceTitleLarge" />

<Button
android:id="@+id/openAppInfo"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/application_option_open_info" />

</LinearLayout>

</FrameLayout>

</LinearLayout>
1 change: 0 additions & 1 deletion app/src/main/res/values-uk/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<string name="application_option_action_launch">Відкрити в GooglePlay</string>
<string name="application_disabled">Вимкнено</string>
<string name="application_system">Системний</string>
<string name="application_disabled_description">Неможливо відобразити компоненти, додаток вимкнений</string>

<!-- create shortcut -->
<string name="shortcut_name">Назва</string>
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
<string name="application_option_action_launch">Open in GooglePlay</string>
<string name="application_disabled">Disabled</string>
<string name="application_system">System</string>
<string name="application_disabled_description">Cannot load activities, this application is disabled</string>

<!-- create shortcut -->
<string name="shortcut_name">Label</string>
Expand Down
2 changes: 1 addition & 1 deletion app/src/prod/play/release-notes/en-US/default.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
- Load manifest for bundles
- Load activities of disabled apps

0 comments on commit 4513356

Please sign in to comment.