Skip to content

App permissions added #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 50 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
6e9ee17
Update Util.kt
bugrevealingbme Oct 20, 2024
aef2384
Update InstalledAppsPlugin.kt
bugrevealingbme Oct 20, 2024
fca7f05
Update app_info.dart
bugrevealingbme Oct 20, 2024
bd1e664
Update Util.kt
bugrevealingbme Oct 20, 2024
6670c4d
Update app_info.dart
bugrevealingbme Oct 20, 2024
37a37ff
Update app_info.dart
bugrevealingbme Oct 20, 2024
835ee26
Update app_info.dart
bugrevealingbme Oct 20, 2024
50a040f
Update app_info.dart
bugrevealingbme Oct 20, 2024
9392970
Update app_info.dart
bugrevealingbme Oct 20, 2024
bd13c0d
Update app_info.dart
bugrevealingbme Oct 20, 2024
57f902c
Update Util.kt
bugrevealingbme Oct 20, 2024
c338d55
Update app_info.dart
bugrevealingbme Oct 20, 2024
fe79441
Update app_info.dart
bugrevealingbme Oct 20, 2024
cdbb371
Update Util.kt
bugrevealingbme Oct 20, 2024
3387e9b
Update BuiltWithUtil.kt
bugrevealingbme Nov 19, 2024
5be269e
Update BuiltWithUtil.kt
bugrevealingbme Nov 19, 2024
6caa61a
Update BuiltWithUtil.kt
bugrevealingbme Nov 19, 2024
2f673bb
Update BuiltWithUtil.kt
bugrevealingbme Nov 19, 2024
3d1f502
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 19, 2024
ea03232
Create PlatfromType.kt
bugrevealingbme Nov 19, 2024
2816b61
Update Util.kt
bugrevealingbme Nov 19, 2024
3aa46dc
Update installed_apps.dart
bugrevealingbme Nov 19, 2024
d6ab727
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 19, 2024
443f5a5
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
21ff9cf
Update installed_apps.dart
bugrevealingbme Nov 27, 2024
02dc38a
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
450df3f
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
fa60995
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
afce2ae
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
918e072
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
2d2c204
Update installed_apps.dart
bugrevealingbme Nov 27, 2024
6d0e305
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
fc363ee
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 27, 2024
6a6ca65
Update installed_apps.dart
bugrevealingbme Nov 27, 2024
eb12710
Update installed_apps.dart
bugrevealingbme Nov 27, 2024
6069d7e
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
e108b21
Update installed_apps.dart
bugrevealingbme Nov 28, 2024
6354733
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
aad18f7
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
96ce2ee
Update installed_apps.dart
bugrevealingbme Nov 28, 2024
5f6ed55
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
271ddc5
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
bafd416
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
0d1400f
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 28, 2024
022c23d
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 29, 2024
e3d37cb
Update installed_apps.dart
bugrevealingbme Nov 29, 2024
5e8d667
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 29, 2024
4a56c9e
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 29, 2024
028d181
Update InstalledAppsPlugin.kt
bugrevealingbme Nov 29, 2024
4c54ffe
Update InstalledAppsPlugin.kt
bugrevealingbme Apr 27, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ class BuiltWithUtil {

}

}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package com.sharmadhiraj.installed_apps

import android.util.Log
import android.provider.Settings
import android.app.ActivityManager
import android.view.accessibility.AccessibilityManager
import android.app.AppOpsManager
import android.os.Build
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager
import android.content.pm.ApplicationInfo
import android.net.Uri
import android.app.usage.UsageStatsManager
import android.provider.Settings.ACTION_USAGE_ACCESS_SETTINGS
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
import android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import android.widget.Toast.LENGTH_SHORT
Expand All @@ -19,34 +28,22 @@ import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.PluginRegistry.Registrar
import java.util.Locale.ENGLISH


class InstalledAppsPlugin() : MethodCallHandler, FlutterPlugin, ActivityAware {

companion object {

var context: Context? = null
import java.util.Locale.ENGLISH

@JvmStatic
fun registerWith(registrar: Registrar) {
context = registrar.context()
register(registrar.messenger())
}
class InstalledAppsPlugin : MethodCallHandler, FlutterPlugin, ActivityAware {

@JvmStatic
fun register(messenger: BinaryMessenger) {
val channel = MethodChannel(messenger, "installed_apps")
channel.setMethodCallHandler(InstalledAppsPlugin())
}
}
private lateinit var channel: MethodChannel
private var context: Context? = null

override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
register(binding.binaryMessenger)
context = binding.applicationContext
channel = MethodChannel(binding.binaryMessenger, "installed_apps")
channel.setMethodCallHandler(this)
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}

override fun onAttachedToActivity(activityPluginBinding: ActivityPluginBinding) {
Expand All @@ -68,23 +65,34 @@ class InstalledAppsPlugin() : MethodCallHandler, FlutterPlugin, ActivityAware {
}
when (call.method) {
"getInstalledApps" -> {
val includeSystemApps = call.argument("exclude_system_apps") ?: true
val withIcon = call.argument("with_icon") ?: false
val packageNamePrefix: String = call.argument("package_name_prefix") ?: ""
val includeSystemApps = call.argument<Boolean>("exclude_system_apps") ?: true
val withIcon = call.argument<Boolean>("with_icon") ?: false
val packageNamePrefix = call.argument<String>("package_name_prefix") ?: ""
val platformTypeName = call.argument<String>("platform_type") ?: ""
Thread {
val apps: List<Map<String, Any?>> =
getInstalledApps(includeSystemApps, withIcon, packageNamePrefix)
val apps: List<Map<String, Any?>> =
getInstalledApps(includeSystemApps, withIcon, packageNamePrefix, PlatformType.fromString(platformTypeName))
result.success(apps)
}.start()
}

"getRunningApps" -> {
val excludeSystemApps = call.argument("exclude_system_apps") ?: true
val withIcon = call.argument("with_icon") ?: false
val platformTypeName: String = call.argument("platform_type") ?: ""
Thread {
val apps = getRunningApps(excludeSystemApps, withIcon, PlatformType.fromString(platformTypeName))
result.success(apps)
}.start()
}

"startApp" -> {
val packageName: String? = call.argument("package_name")
val packageName = call.argument<String>("package_name")
result.success(startApp(packageName))
}

"openSettings" -> {
val packageName: String? = call.argument("package_name")
val packageName = call.argument<String>("package_name")
openSettings(packageName)
}

Expand All @@ -95,48 +103,183 @@ class InstalledAppsPlugin() : MethodCallHandler, FlutterPlugin, ActivityAware {
}

"getAppInfo" -> {
val packageName: String = call.argument("package_name") ?: ""
result.success(getAppInfo(getPackageManager(context!!), packageName))
val packageName = call.argument<String>("package_name") ?: ""
val platformTypeName = call.argument<String>("platform_type") ?: ""
val platformType = PlatformType.fromString(platformTypeName)
result.success(getAppInfo(getPackageManager(context!!), packageName, platformType))
}

"isSystemApp" -> {
val packageName: String = call.argument("package_name") ?: ""
val packageName = call.argument<String>("package_name") ?: ""
result.success(isSystemApp(getPackageManager(context!!), packageName))
}

"uninstallApp" -> {
val packageName: String = call.argument("package_name") ?: ""
val packageName = call.argument<String>("package_name") ?: ""
result.success(uninstallApp(packageName))
}

"isAppInstalled" -> {
val packageName: String = call.argument("package_name") ?: ""
val packageName = call.argument<String>("package_name") ?: ""
result.success(isAppInstalled(packageName))
}

"checkUsageAccessPermission" -> {
val isGranted = isUsageAccessGranted()
result.success(isGranted)
}

"checkAccessibilityPermission" -> {
result.success(isAccessibilityPermissionGranted())
}

"requestAccessibilityPermission" -> {
checkAndRequestAccessibilityPermission()
result.success(null) // İşlem başlatıldığı için geri dönecek bir sonuç yok
}

"openUsageAccessSettings" -> {
openUsageAccessSettings()
result.success(null)
}

else -> result.notImplemented()
}
}

private fun openUsageAccessSettings() {
val intent = Intent().apply {
flags = FLAG_ACTIVITY_NEW_TASK
action = ACTION_USAGE_ACCESS_SETTINGS
}

context!!.startActivity(intent)
}

private fun checkAndRequestAccessibilityPermission() {
val intent = Intent().apply {
flags = FLAG_ACTIVITY_NEW_TASK
action = ACTION_ACCESSIBILITY_SETTINGS
}

context!!.startActivity(intent)
}

private fun isAccessibilityPermissionGranted(): Boolean {
val accessibilityManager = context!!.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager

val enabledServices = Settings.Secure.getString(
context!!.contentResolver,
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
)
val myServiceName = "${context!!.packageName}/net.permission.man.MyAccessibilityService"

// Kontrol: MyAccessibilityService etkin mi?
return enabledServices?.contains(myServiceName) == true &&
accessibilityManager.isEnabled
}

private fun isUsageAccessGranted(): Boolean {
val appOpsManager = context!!.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
appOpsManager.unsafeCheckOpNoThrow(
AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(),
context!!.packageName
)
} else {
appOpsManager.checkOpNoThrow(
AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(),
context!!.packageName
)
}
return mode == AppOpsManager.MODE_ALLOWED
}

private fun getInstalledApps(
excludeSystemApps: Boolean,
withIcon: Boolean,
packageNamePrefix: String
packageNamePrefix: String,
platformType: PlatformType?,
): List<Map<String, Any?>> {
val packageManager = getPackageManager(context!!)
var installedApps = packageManager.getInstalledApplications(0)
var installedApps = packageManager.getInstalledApplications(PackageManager.GET_PERMISSIONS)
if (excludeSystemApps)
installedApps =
installedApps.filter { app -> !isSystemApp(packageManager, app.packageName) }
installedApps = installedApps.filter { app -> !isSystemApp(packageManager, app.packageName) }
if (packageNamePrefix.isNotEmpty())
installedApps = installedApps.filter { app ->
app.packageName.startsWith(
packageNamePrefix.lowercase(ENGLISH)
)
}
return installedApps.map { app -> convertAppToMap(packageManager, app, withIcon) }
return installedApps.map { app -> convertAppToMap(packageManager, app, withIcon, platformType) }
}

private fun getRunningApps(
excludeSystemApps: Boolean,
withIcon: Boolean,
platformType: PlatformType?
): List<Map<String, Any?>> {
val packageManager = getPackageManager(context!!)
val runningApps = mutableListOf<Map<String, Any?>>()

// 1. Kullanıcı İstatistiklerini Kullanma
val usageStatsManager = context!!.getSystemService(Context.USAGE_STATS_SERVICE) as android.app.usage.UsageStatsManager
val currentTime = System.currentTimeMillis()
val endTime = currentTime
val startTime = currentTime - 1000 * 60 * 60 * 1 // Last 1 hour

val usageStats = usageStatsManager.queryUsageStats(
android.app.usage.UsageStatsManager.INTERVAL_DAILY,
startTime,
endTime
)

if (usageStats != null) {
val uniquePackages = mutableSetOf<String>()

usageStats.forEach { stat ->
val packageName = stat.packageName
if (packageName != null && uniquePackages.add(packageName)) {
try {
val appInfo = packageManager.getApplicationInfo(packageName, 0)
val isSystemApp = (appInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0
if (!excludeSystemApps || !isSystemApp) {
val appMap = convertAppToMap(packageManager, appInfo, withIcon, platformType)
runningApps.add(appMap)
}
} catch (e: PackageManager.NameNotFoundException) {
// Paket bulunamadı, devam et
}
}
}
}

// 2. Çalışan İşlemleri Kullanma (Eski Yöntem)
val activityManager = context!!.getSystemService(Context.ACTIVITY_SERVICE) as android.app.ActivityManager
val runningProcesses = activityManager.runningAppProcesses
runningProcesses?.forEach { processInfo ->
processInfo.pkgList?.forEach { packageName ->
try {
if (!runningApps.any { it["packageName"] == packageName }) { // Eğer daha önce eklenmediyse
val appInfo = packageManager.getApplicationInfo(packageName, 0)
val isSystemApp = (appInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0
if (!excludeSystemApps || !isSystemApp) {
val appMap = convertAppToMap(packageManager, appInfo, withIcon, platformType)
runningApps.add(appMap)
}
}
} catch (e: PackageManager.NameNotFoundException) {
// Uygulama bilgisi bulunamadı, devam et
}
}
}

return runningApps
}


private fun startApp(packageName: String?): Boolean {
if (packageName.isNullOrBlank()) return false
return try {
Expand Down Expand Up @@ -178,12 +321,13 @@ class InstalledAppsPlugin() : MethodCallHandler, FlutterPlugin, ActivityAware {

private fun getAppInfo(
packageManager: PackageManager,
packageName: String
packageName: String,
platformType: PlatformType?
): Map<String, Any?>? {
var installedApps = packageManager.getInstalledApplications(0)
installedApps = installedApps.filter { app -> app.packageName == packageName }
return if (installedApps.isEmpty()) null
else convertAppToMap(packageManager, installedApps[0], true)
else convertAppToMap(packageManager, installedApps[0], true, platformType)
}

private fun uninstallApp(packageName: String): Boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.sharmadhiraj.installed_apps
enum class PlatformType(val value: String) {
FLUTTER("flutter"),
REACT_NATIVE("react_native"),
XAMARIN("xamarin"),
IONIC("ionic"),
NATIVE_OR_OTHERS("native_or_others");

companion object {
fun fromString(platform: String): PlatformType? {
if (platform.isEmpty()) return null;
return when (platform.lowercase()) {
"flutter" -> FLUTTER
"react_native" -> REACT_NATIVE
"xamarin" -> XAMARIN
"ionic" -> IONIC
else -> NATIVE_OR_OTHERS
}
}
}
}
26 changes: 22 additions & 4 deletions android/src/main/kotlin/com/sharmadhiraj/installed_apps/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,39 @@ class Util {
fun convertAppToMap(
packageManager: PackageManager,
app: ApplicationInfo,
withIcon: Boolean
withIcon: Boolean,
platformType: PlatformType?,
): HashMap<String, Any?> {
val map = HashMap<String, Any?>()
map["name"] = packageManager.getApplicationLabel(app)
map["package_name"] = app.packageName
map["icon"] =
if (withIcon) DrawableUtil.drawableToByteArray(app.loadIcon(packageManager))
else ByteArray(0)
val packageInfo = packageManager.getPackageInfo(app.packageName, 0)

val packageInfo = packageManager.getPackageInfo(app.packageName, PackageManager.GET_PERMISSIONS)
map["version_name"] = packageInfo.versionName
map["version_code"] = getVersionCode(packageInfo)
map["built_with"] = BuiltWithUtil.getPlatform(packageInfo.applicationInfo)
map["built_with"] = platformType?.value ?: BuiltWithUtil.getPlatform(packageInfo.applicationInfo)
map["installed_timestamp"] = File(packageInfo.applicationInfo.sourceDir).lastModified()

if (packageInfo.requestedPermissions != null) {
val permissionsStatus = packageInfo.requestedPermissions.map { permission ->
val isGranted = checkPermissionStatus(packageManager, app.packageName, permission)
mapOf("permission" to permission, "granted" to isGranted)
}
map["permissions"] = permissionsStatus
} else {
map["permissions"] = emptyList<Map<String, Any?>>()
}

return map
}

fun checkPermissionStatus(packageManager: PackageManager, packageName: String, permission: String): Boolean {
val permissionCheck = packageManager.checkPermission(permission, packageName)
return permissionCheck == PackageManager.PERMISSION_GRANTED
}


fun getPackageManager(context: Context): PackageManager {
Expand All @@ -44,4 +62,4 @@ class Util {

}

}
}
Loading