实战|Android后台启动Activity实践之路

Android 10 后台启动Activity(app切换到前台) 目录 过程分析 解决方案 在AndroidManifest.xml上添加权限 检查是否开启悬浮窗权限 打开悬浮窗权限设置页 最近需要开发一个某些时候需要把app唤醒并置于前台的功能。刚开发时,在模拟器正常,后来上真机出问题了。进行排查发现模拟器api是28的,真机是api29(Android 10),查资料发现,api29版本禁止后台启动activity,而造成的。 过程分析 具体资料如下: 从后台启动 Activity 的限制 Android10(Api 29)新特... 阅读详情

概述

前几天产品提了一个需求,想在后台的时候启动我们 APP 的一个 Activity,随着 Android 版本的更新,以及各家 ROM 厂商的无限改造,这种影响用户体验的功能许多都受到了限制,没办法,虽然是比较流氓的功能,但拿人钱财替人消灾,于是开启了哼哧哼哧的调研之路。

原生Android ROM

首先从 Android 的原生 ROM 开始,根据官方的介绍,后台启动 Activity 的限制是从 Android 10(API 29) 才开始的,在此之前原生 ROM 是没有这个限制的,于是我分别启动了一个 Android 9(API 28) 和 10(API 29) 版本的模拟器,发现在 API 28 上可以直接从后台启动 Activity,而在 API 29 上则受到了限制无法直接启动。参照官方 从后台启动 Activity 的限制 的说明,给出了一些不受限制的例外情况,此外官方的推荐是对于后台启动的需求,先向用户展示一个 Notification 而不是直接启动 Activity,然后在用户点击 Notification 后才处理对应的逻辑。还可以在设置 Notification 时通过 setFullScreenIntent 添加一个全屏 Intent 对象,该方法经过测试,可以在 Android 10 的模拟器上从后台启动一个 Activity 界面(需要 android.permission.USE_FULL_SCREEN_INTENT 权限)。代码如下:

object NotificationUtils {
    private const val ID = "channel_1"
    private const val NAME = "notification"

    private var manager: NotificationManager? = null

    private fun getNotificationManagerManager(context: Context): NotificationManager? {
        if (manager == null) {
            manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
        }
        return manager
    }

    fun sendNotificationFullScreen(context: Context, title: String?, content: String?) {
        if (Build.VERSION.SDK_INT >= 26) {
            clearAllNotification(context)
            val channel = NotificationChannel(ID, NAME, NotificationManager.IMPORTANCE_HIGH)
            channel.setSound(null, null)
            getNotificationManagerManager(context)?.createNotificationChannel(channel)
            val notification = getChannelNotificationQ(context, title, content)
            getNotificationManagerManager(context)?.notify(1, notification)
        }
    }

    private fun clearAllNotification(context: Context) {
        getNotificationManagerManager(context)?.cancelAll()
    }

    private fun getChannelNotificationQ(context: Context, title: String?, content: String?): Notification {
        val fullScreenPendingIntent = PendingIntent.getActivity(
            context,
            0,
            DemoActivity.genIntent(context),
            PendingIntent.FLAG_UPDATE_CURRENT
        )
        val notificationBuilder = NotificationCompat.Builder(context, ID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle(title)
            .setContentText(content)
            .setSound(null)
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setCategory(Notification.CATEGORY_CALL)
            .setOngoing(true)
            .setFullScreenIntent(fullScreenPendingIntent, true)
        return notificationBuilder.build()
    }
}

到现在,整体上感觉还是不错的,现阶段的 Android 原生 ROM 都能正常地从后台启动 Activity 界面,无论是 Android 9 还是 10 版本,都美滋滋。

定制化ROM

问题开始浮出水面,由于各大厂商对 Android 的定制化各有不一,而 Android 并没有继承 GPL 协议,它使用的是 Apache 开源许可协议,即第三方厂商在修改代码后可以闭源,因此也无法得知厂商 ROM 的源码到底做了哪些修改。有的机型增加了一项权限——后台弹出界面,比如说在 MIUI 上便新增了这项权限且默认是关闭的,除非加入了它们的白名单,小米开放平台的文档 里有说明:该权限默认为拒绝的,既为应用默认不允许在后台弹出页面,针对特殊应用会提供白名单,例如音乐(歌词显示)、运动、VOIP(来电)等;白名单应用一旦出现推广等恶意行为,将永久取消白名单。

检测后台弹出界面权限

在小米机型上,新增的这个 后台弹出界面 的权限是在 AppOpsService 里扩展了新的权限,查看 AppOpsManager 源代码,可以在里面看到许多熟悉的常量:

@SystemService(Context.APP_OPS_SERVICE)
public class AppOpsManager {
    public static final int OP_GPS = 2;
    public static final int OP_READ_CONTACTS = 4;
    // ...
}

因此可以通过 AppOpsService 来检测是否具有 后台弹出界面 的权限,那么这个权限对应的 OpCode 是啥呢?网上有知情人士透露这个权限的 Code 是 10021,因此可以使用 AppOpsManager.checkOpNoThrow 或 AppOpsManager.noteOpNoThrow 等系列的方法检测该权限是否存在,不过这些方法都是 @hide 标识的,需要使用反射:

fun checkOpNoThrow(context: Context, op: Int): Boolean {
    val ops = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    try {
        val method: Method = ops.javaClass.getMethod(
            "checkOpNoThrow", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, String::class.java
        )
        val result = method.invoke(ops, op, myUid(), context.packageName) as Int
        return result == AppOpsManager.MODE_ALLOWED
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return false
}

fun noteOpNoThrow(context: Context, op: Int): Int {
    val ops = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    try {
        val method: Method = ops.javaClass.getMethod(
            "noteOpNoThrow", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, String::class.java
        )
        return method.invoke(ops, op, myUid(), context.packageName) as Int
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return -100
}

另外如果想知道其它新增权限的 code, 可以通过上面的方法去遍历某个范围(如10000~10100)内的 code 的权限,然后手机操作去开关想要查询的权限,根据遍历的结果,就大致可以得到对应权限的 code 了。

Android P后台启动权限

在小米 Max3 上测试发现了两种方式可以实现从后台启动 Activity 界面,其系统是基于 Android 9 的 MIUI 系统。

方式一:moveTaskToFront

这种方式不算是直接从后台启动 Activity,而是换了一个思路,在后台启动目标 Activity 之前先将应用切换到前台,然后再启动目标 Activity,如果有必要的话,还可以通过 Activity.moveTaskToBack 方法将之前切换到前台的 Activity 重新移入后台,经过测试,在 Android 10 上这个方法已经失效了…但是 10 以下的版本还是可以抢救一下的(需要声明 android.permission.REORDER_TASKS 权限)。

启动目标 Activity 之前先判断一下应用是否在后台,判断方法可以借助 ActivityManager.getRunningAppProcesses 方法或者 Application.ActivityLifecycleCallbacks 来监听前后台,这两种方法网上都有文章讲解,就不赘述了。直接贴出后台切换到前台的代码:

fun moveToFront(context: Context) {
    val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager
    activityManager?.getRunningTasks(100)?.forEach { taskInfo ->
        if (taskInfo.topActivity?.packageName == context.packageName) {
            Log.d("LLL", "Try to move to front")
            activityManager.moveTaskToFront(taskInfo.id, 0)
            return
        }
    }
}

fun startActivity(activity: Activity, intent: Intent) {
    if (!isRunningForeground(activity)) {
        Log.d("LLL", "Now is in background")
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            // TODO 防止 moveToFront 失败,可以多尝试调用几次
            moveToFront(activity)
            activity.startActivity(intent)
            activity.moveTaskToBack(true)
        } else {
            NotificationUtils.sendNotificationFullScreen(activity, "", "")
        }
    } else {
        Log.d("LLL", "Now is in foreground")
        activity.startActivity(intent)
    }
}

方式二:Hook

由于 MIUI 系统不开源,因此尝试再研究研究 AOSP 源码,死马当活马医看能不能找到什么蛛丝马迹。首先从 Activity.startActivity 方法开始追,如果阅读过 Activity 启动源码流程的话可以知道 Activity.startActivity 或调用到 Instrumentation.execStartActivity 中,然后通过 Binder 调用到 AMS 相关的方法,权限认证就在 AMS 中完成,如果权限不满足自然启动就失败了(Android 10)。

// APP 进程
public ActivityResult execStartActivity(Context who, IBinder contextThread, ...) {
    // ...
    // 这里会通过 Binder 调用到 AMS 相关的代码
    int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(),
            intent, intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
    // ...
}

// system_server进程
// AMS
public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
    String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    // ...
}
  • caller: AMS 在完成相关任务后会通过它来 Binder 调用到客户端 APP 进程来实例化 Activity 对象并回调其生命周期方法,caller 的 Binder 服务端位于 APP 进程。
  • callingPackage: 这个参数标识调用者包名。
  • …

这里可以尝试 Hook 一些系统的东西,具体怎么 Hook 的代码先不给出了,经过测试在 Android 9 的小米设备上可以成功,有兴趣可以自行研究谈论哈,暂时不公开了,有需要的同学可以留言告诉我。或者反编译小米 ROM 源码,可以从里面发现一些东西。

Android Q后台启动权限

在上面介绍过 Android Q 版本开始原生系统也加入了后台启动的限制,通过通知设置 fullScreenIntent 可以在原生 Android 10 系统上从后台启动 Activity。查看 AOSP 源码,可以在 AMS 找到这部分后台权限限制的代码,上面讲到 startActivity 的流程,在 APP 进程发起请求后,会通过 Binder 跨进程调用到 system_server 进程中的 AMS,然后调用到 ActivityStarter.startActivity 方法,关于后台启动的限制就这这里:

// 好家伙,整整二十多个参数,嘿嘿,嘿嘿
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        SafeActivityOptions options,
        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
    // ...
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
        requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
        inTask != null, callerApp, resultRecord, resultStack);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);
    abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
            callingPackage);

    boolean restrictedBgActivity = false;
    if (!abort) {
        restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                originatingPendingIntent, allowBackgroundActivityStart, intent);
    }
    // ...
}

这里的 shouldAbortBackgroundActivityStart 调用是在 Android Q 中新增的,看方法名就能菜刀这是针对后台启动的:

boolean shouldAbortBackgroundActivityStart(...) {
    final int callingAppId = UserHandle.getAppId(callingUid);
    if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
            || callingAppId == Process.NFC_UID) {
        return false;
    }
    if (callingUidHasAnyVisibleWindow || isCallingUidPersistentSystemProcess) {
        return false;
    }
    // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
    if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
            == PERMISSION_GRANTED) {
        return false;
    }
    // don't abort if the caller has the same uid as the recents component
    if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
        return false;
    }
    // don't abort if the callingUid is the device owner
    if (mService.isDeviceOwner(callingUid)) {
        return false;
    }
    // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
    if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
        Slog.w(TAG, "Background activity start for " + callingPackage
                + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
        return false;
    }
    // ...
}

从这个方法可以看到后台启动的限制和官方文档 中的说明是可以对应上的,这里面都是针对 uid 去做权限判断的,且是在系统进程 system_server 中完成,单纯更改包名已经没用了。。。

在一些没有针对后台启动单独做限制的 ROM 上通过 全屏通知 可以成功弹出后台 Activity 页面,比如说小米 A3,另外还有一台 vivo 和一台三星手机,具体机型忘记了;在做了限制的设备上则弹不出来,比如说红米 Note 8 Pro。

对于红米 Note 8 Pro 这块硬骨头,不停尝试了好多方法,但其实都是碰运气的,因为拿不到 MIUI 的源码,后来想转变思路,是否可以尝试从这台手机上 pull 出相关的 framework.jar 包然后反编译呢?说不定就有收获!不过需要 Root 手机,这个好办,小米自己是有提供可以 Root 的开发版系统的,于是就去 MIUI 官网找了一下,发现这台红米 Note 8 Pro 机型没有提供开发版系统(笑哭),想起来好像之前是说过低端机小米不再提供开发版了。。。好吧,手里头没有其它可以尝试的手机了。

再转念一想,是否可以直接下载稳定版的 ROM 包,解压后有没有工具能够得到一些源码相关的痕迹呢?于是下载了一个 ROM.zip 后,解压看到里面只有一些系统映像 img 文件和 .dat.br 文件,这一块我还不太懂,猜想就算能得到我想要的东西,整套流程花费的时间成本估计也超出预期了,所以暂时只能先放下这个想法了。后续有足够的时间再深入研究研究吧。

总结

原生Android ROM

Android 原生 ROM 都能正常地从后台启动 Activity 界面,无论是 Android 9(直接启动) 还是 10 版本(借助全屏通知)。

定制化ROM

检测后台弹出界面权限:

  • 通过反射 AppOpsManager 相关方法检测对应 opCode 的权限;
  • opCode = 10021(小米机型);
  • 其它机型可以尝试遍历得到 opCode;

Android P版本的小米:

  • 通过Hook相关参数来后台启动Activity,代码由于某些原因不能给出了,有需要的同学可以留言告诉我哈;
  • 只测试过小米机型,其它机型不一定可用;
  • 理论上 P 版本以下的小米应该也支持;

Android P版本的机型:

  • 通过 moveTaskToFront 方法将应用切换到前台;
  • 这种方法毕竟是官方 API,因此兼容性可能更好一些;
  • 如果切换失败的话可以多尝试几次调用 moveTaskToFront 方法;
  • 理论上 P 版本以下的机型应该也支持;

Android Q版本的机型:

  • 通过系统全屏通知的方式调起后台 Activity;
  • 在一些另作了限制的 ROM 上可能调起失败;

至于反编译 MIUI 代码的方式只是一个猜想,时间原因未能付诸行动。看样子产品哥哥的需求暂时不能完全实现了,不知道有没有做过相关研究(或者知道内情)的小伙伴能不能提供一些参考思路,虽然是一个比较流氓的功能,但是代码是无罪的嘿嘿,朝着一个需求目标,为此思考解决方法,并从各个方向去调研,我觉得本身是一件有意思也有提升的事情!欢迎有过相关研究的同学在评论区提出建议,做好需求奥里给。

实战|Android后台启动Activity实践之路续 家人们!Android 原生 ROM 都能正常地从后台启动 Activity 界面,无论是 Android 9(直接启动) 还是 10 版本(借助全屏通知)。Android P版本的机型:通过 moveTaskToFront 方法将应用切换到前台,如果切换失败的话可以多尝试几次调用 moveTaskToFront 方法;小米机型可以通过Hook相关参数来后台启动Activity;Android Q版本的机型:通过系统全屏通知的方式调起后台 Activity; 阅读详情

相关推荐

[android q] 从后台启动 Activity 的限制

https://developer.android.com/guide/components/activities/background-starts https://developer.android.com/training/notify-user/time-sensitive 从AndroidQ开始android进一步限制了从后台(组件)启动Activity的行为,前台的不受限制。说白...

xlnaan的博客 2400

Android Permission 大全

Android Permission大全出自1.0 SDK中记录着新改变的访问权限许可。程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求,Android开发网已经翻译并使用中英文对照,完整列表如下:   android.permission.ACCESS_CHECKIN_PROPERTIES允许读写访问"properties"表在checkin数据库...

wongstar的专栏 343

Android 10.0以后高版本后台启动Activity的方法

在Android 10.0以后在后台直接启动Activity已经不行了 查看官方文档 发现这种方式为了安全起见已经受限了 给出了一些不受限制的例外情况,此外官方的推荐是对于后台启动的需求,先向用户展示一个 Notification 而不是直接启动 Activity,然后在用户点击 Notification 后才处理对应的逻辑。还可以在设置 Notification 时通过 setFullScreenIntent 添加一个全屏 Intent 对象,该方法经过测试 下面就来实现这种方式启动Activity 1.

安卓兼职framework和app工程师的博客 7777

android_基础_权限大全

转载自: https://www.cnblogs.com/shiwei-bai/p/4916794.html 1 android.permission.EXPAND_STATUS_BAR 允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序 android.permission.FACTORY_TEST 作为一个工厂测试程序,运行在root用户 android.permission.FLASHLIGHT 访问闪光灯,android开发网提示HTC .

写bug的蚊子的博客 3191

Android 后台无法启动 Activity 的解决方法

通过这些解决方案,我们可以在后台任务完成时向用户发送通知,并在用户点击通知时启动相应的 Activity,让用户方便地查看任务结果。当后台任务完成时,我们可以通过发送一个通知来提示用户,并在用户点击通知时启动相应的 Activity。通过将后台任务转换为前台服务,我们可以在系统状态栏显示一个通知,提醒用户任务正在运行,并在用户点击通知时启动相应的 Activity。通过这种方式,我们可以在后台任务完成时,通过通知来启动对应的 Activity,让用户方便地查看任务结果。解决方案二:使用前台服务。

CodeJolt的博客 1352

Moodle平台题库建设技术

Moodle平台题库建设技术简述1新的改变1功能快捷键1合理的创建标题,有助于目录的生成1如何改变文本的样式1插入链接与图片1如何插入一段漂亮的代码片1生成一个适合你的列表1创建一个表格1设定内容居中、居左、居右1SmartyPants1创建一个自定义列表1如何创建一个注脚注释也是必不可少的1KaTeX数学公式1新的甘特图功能,丰富你的文章1UML 图表1FLowchart流程图1导出与导入导出1...

lxf78的博客 4534

2024年安卓最新实战|Android后台启动Activity实践之路续,2024年最新零基础学习android开发

!最后放上一个大概的Android学习方向及思路(详细的内容太多了~),提供给大家:对于程序员来说,要学习的知识内容、技术有太多太多,这里就先放上一部分,其他的内容有机会在后面的文章向大家呈现出来,不过我自己所有的学习资料都整理成了一个文档,一直在不断学习,希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!Android架构师之路很漫长,一起共勉吧!如果你觉得文章写得不错就给个赞呗?获取ROM源码=======adb pull========

2401_84562041的博客 1000

PID控制器(位置式和增量式)

PID控制算法

zhinian_hao的博客 4512

最全实战_Android后台启动Activity实践之路,春招的面试时间

原生Android ROMAndroid 原生 ROM 都能正常地从后台启动 Activity 界面,无论是 Android 9(直接启动) 还是 10 版本(借助全屏通知)。定制化ROM通过反射 AppOpsManager 相关方法检测对应 opCode 的权限;opCode = 10021(小米机型);其它机型可以尝试遍历得到 opCode;通过Hook相关参数来后台启动Activity,代码由于某些原因不能给出了,有需要的同学可以留言告诉我哈;只测试过小米机型,其它机型不一定可用;

2401_84556528的博客 1309

如何区分Info与CoWoS封装?

这篇文章主要从Info、CoWoS封装的定义、Interposer的种类以及Info、CoWoS封装的种类三方面进行了介绍,希望读者能够有所收获

wangyubo1的博客 7938

jaka+realsense+aruco+手眼标定(python)

第二次重建了项目的手眼标定部分……有很多第一次记录遗漏的地方,在此补充。

drivenzyw的博客 2122

实战_Android后台启动Activity实践之路,android工程师面试题目和答案

} fun noteOpNoThrow(context: Context, op: Int): Int { val ops = context.getSystemService(Context.APP_OPS_SERVICE) as AppOp sManager try { val method: Method = ops.javaClass.getMethod( “noteOpNoThrow”, Int::class.javaPrimitiveType, Int::class.javaPrimitiveT

m0_65322636的博客 944

SigmaStar(星宸科技)SSC33X系列

目前,SSC33X系列已经量产了接近两年,SDK成熟稳定,功耗表现良好,图像效果出色,广泛应用在AI枪机、AI球机、AI云台机、多目摄像机、停车场闸机、人脸门禁、人脸锁、门铃猫眼等产品上。

Comake Online的博客 1万+

2024年最全实战|Android后台启动Activity实践之路续(1),测试面试宝典

那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!北京 Android 工程师「工资收入水平 」今天重点内容是怎么去学,怎么提高自己的技术。1.合理安排时间2.找对好的系统的学习资料3.有老师带,可以随时解决问题。

2301_82244718的博客 1214

基于Slim-Neck架构的YOLOv11轻量化特征融合方案(实现超轻量级与高精度的双重突破)

购买即可解锁800+YOLO优化文章,并且还有海量深度学习复现项目,价格仅需两杯奶茶的钱,每日更新。

m0_64661770的博客 250

【2024遥感应用组一等奖】基于时空融合和水量平衡法的若尔盖高原水源涵养功能评价

考虑到水源涵养的概念和尺度特征、数据的可获得性、模型的模拟精度等,构建了一种基于遥感、气象和水量平衡原理的草原湿地水源涵养评价方法,估算若尔盖湿地近23年(2000-2022)来的水源涵养量。若尔盖湿地是我国黄河源区的重要水源地,所以本研究以若尔盖湿地的水源涵养功能评估为科学问题,基于遥感数据、GIS数据等,利用水量平衡原理,发展计算简单、便捷、数据易获取的“水源涵养估算方法”,科学估算若尔盖湿地水源涵养服务量,探究其时空动态变化趋势及其影响因素;公式中,Z1和Z2为两个不同高度面的高度,u为摩擦速率;

JData_Engineer的博客 239

最全实战|Android后台启动Activity实践之路续(1),2024年最新字节跳动面试官

给大家送上我成功跳槽复习中所整理的资料,由于文章篇幅有限,所以只是把题目列出来了网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化学习资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

2401_84556528的博客 1295

零基础学习simulink-- 四旋翼和六旋翼无人机的建模与动力学分析

通过上述代码实现,您可以逐步创建和搭建一个多旋翼无人机(如四旋翼、六旋翼)的动力学模型,并结合自适应控制器进行仿真。该模型不仅考虑了无人机的基本动力学行为,还引入了空气阻力、螺旋桨之间的相互作用以及气流干扰等复杂效应,使得仿真结果更加接近实际情况。Simulink 提供了强大的建模和仿真工具,使得控制系统工程师能够快速构建复杂的控制算法,并将其应用于实际工程中。多旋翼无人机动力学建模:建立四旋翼和六旋翼无人机的动力学模型,包括平移运动和旋转运动方程。升力和扭矩模型。

amy_mhd的博客 388

移动开发最新实战_Android后台启动Activity实践之路(2),2024年最新腾讯面试官工资

原生Android ROMAndroid 原生 ROM 都能正常地从后台启动 Activity 界面,无论是 Android 9(直接启动) 还是 10 版本(借助全屏通知)。定制化ROM通过反射 AppOpsManager 相关方法检测对应 opCode 的权限;opCode = 10021(小米机型);其它机型可以尝试遍历得到 opCode;通过Hook相关参数来后台启动Activity,代码由于某些原因不能给出了,有需要的同学可以留言告诉我哈;只测试过小米机型,其它机型不一定可用;

2401_84538063的博客 758

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

android 10+从后台启动 Activity 的限制

Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity 的时间施加限制。这些限制有助于最大限度地减少对用户造成的中断,并且可以让用户更好地控制其屏幕上显示的内容。 在 Android 10 或更高版本上运行的应用只有在满足以下一项或多项条件时,才能启动 Activity:

xiaoyantan的博客 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android 在后台无法启动Activity

前言 前几天接触的一个闹钟APP项目,闹钟触发从后台启动一个activity,执行之后的响铃操作,但是却失效了,闹钟并没有按时响铃。最后发现是系统拦截了从后台启动的Activity。 具体原因 一、AndroidQ从后台启动Activity的限制 Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity进行限制。Android10中, 当App的Activit...

屈佳俊的博客 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Android 后台启动Activity适配

先判断是否是特殊机型,如果是则需要申请后台弹出界面权限如果不是特殊机型,则有两种方案,一是全屏通知,二是申请在其他应用上层绘制权限。

极致的专注 无限的热情 5202

Android Q 限制后台启动Activity

描述 Android Q限制在没有用户交互的情况下加载Activity。这一变化可以最大限度的减少对用户的打扰,保持用户对屏幕上所显示内容的可控性。 运行在Android Q上的APP仅在以下一种或多种情况下可运行Activity: APP存在一个可视的窗口,例如一个处于前台的Activity 另外一个处于前台的APP发送一个属于当前APP的PendingIntent。例如Custom Tabs...

iPeak的专栏 1万+

如何解决Android 后台进程启动 activity 限制?

这仅适用于在调用 finish() 时,应用在前台中具有一项 activity,或在前台任务的返回栈中具有一项 activity 的情况。不过也可以看出这些代码中的额外一些条件,其实都不是普通第三方app可以的达到的条件,所以文档中也没有列出这些,文档主要还是列出第三方应用可以达到条件。那么这个问题应该如何解决呢?所以对于系统应用而言,如果想要后台启动,只需要在自己的apk中添加权限既可以,注意同时要有系统签名或其他条件。3、应用在“最近使用的应用”屏幕上现有任务的返回堆栈中具有 activity。

learnframework的博客 2037

Android 10 后台启动Activity

从官方文档得知,在一些情况下,可以允许从后台启动Activity,具体如下: 在 Android 10 或更高版本上运行的应用只有在满足以下一项或多项条件时,才能启动 Activity: 应用具有可见窗口,例如前台 Activity。 应用在前台任务的返回栈中拥有 Activity。 应用在 Recents 屏幕上现有任务的返回栈中拥有 Activity。 注意:当此类应用尝试启动新的 Activity 时,系统会将该 Activity 放置到应用现有任务的顶部,但不会离开当前可见的任务。当用户稍后返

xiaowang_lj的博客 5987
上一篇: 继上篇,关于Rxjava,让你知道什么叫“大海无量”
下一篇: Android面试笔试总结(Android篇)
懂你的大海
博客等级 码龄6年 9049粉丝 1381原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值