Android异常之Service启动Activity

Buck电源设计常见的一些问题(一)半桥栅极驱动芯片共性失效问题 半桥驱动芯片主要用在器件可应用于电信,数据通信,便携式存储或更低电压系统中的电源转换器,半桥、全桥、推挽、同步降压,正激变换器和同步整流器等方面。当然难免会遇到不少问题。基本上我们在产品开发的过程中都遇到过栅极驱动芯片坏掉的情况,所以找了一些资料,学习学习。也查找查找原因。 阅读详情

在Activity中其中startActivity这个大家应该是非常熟悉的;那么从service里面调用startActivity话,会怎么样呢?
会出现下面的异常:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

也就是在service里面启动Activity的话,必须添加FLAG_ACTIVITY_NEW_TASK flag。
那么下面的话,我们将从下面几个方面分析这个问题。
1. 这个异常怎么产生的?
2. 解决这个异常后会出现问题?
3. 为什么Activity.startActivity()不会出现这个问题?
4. Android 为什么要这么设计?
下面,一一分析

一. Context的继承关系图

首先来看一张图, 这张图表示了Context里面的基本继承关系。

这里写图片描述

  1. 最上面的是Context.java,它其实是一个抽象类,它有两个重要的子类ContextImpl和ContextWrapper
  2. ContextImpl,是Context功能实现的主要类,
  3. ContextWrapper,顾名思义,它只是一个包装而已。主要功能实现都是通过调用ContextImpl去实现的。
  4. ContextThemeWrapper,包括一些主题的包装,由于Service没有主题,所以直接继承ContextWrapper;但是Activity就需要继承ContextThemeWrapper

二. 异常如何产生

1. 找到报错的代码

文件:
frameworks\base\core\java\android\app\ContextImpl.java
代码:

public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity)null, intent, -1, options);
}

在下面的if条件判断,如果不包含FLAG_ACTIVITY_NEW_TASK就会报这个错误

那么service.startActivity(Intent intent)怎么会调用这里来的呢?

要回答这个问题,我们分析下service.startActivity()做了什么,其实,service.startActivity调用的是ContextWrapper.startActivity(),因为service继承自ContextWrapper

2. 代码文件

frameworks\base\core\java\android\content\ContextWrapper.java
代码:

public void startActivity(Intent intent, Bundle options) {
    mBase.startActivity(intent, options);
}

ContextWrapper.startActivity的话,是直接调用的
mBase.startActivity(intent, options);
那么这个mBase是什么呢?又是什么时候赋值的呢?其实mBase是在ContextWrapper的attachBaseContext的时候初始化的。如下:

protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

那又是谁调用attachBaseContext的呢?
是在service创建的时候,在ActivityThread里面调用,如下:

3. 代码文件

frameworks\base\core\java\android\app\ActivityThread.java

private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            ....
        }
        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            service.onCreate();
            mServices.put(data.token, service);
            ....
        } catch (Exception e) {
            ...
        }
    }

抽出主要代码分析ActivityThread. handleCreateService()方法里面主要做这几件事
3.1 通过pms找到要启动的Service配置信息,然后通过反射生成Service对象
3.2 创建ContextImpl对象,然后调用service.attach方法设置到ContextWrapper.java的mBaseContext变量里面。

那现在就明白了,service.startActivity()->ContextWrapper.startActivity()->ContextImpl.startActivity()
然后再ContextImpl.startActivity里面会检查Intent的参数是否包含FLAG_ACTIVITY_NEW_TASK,从而出现这个异常。


三. 解决这个异常后会出现问题?

有些同学就会说了,在Service里面启动Activity必须要有FLAG_ACTIVITY_NEW_TASK参数,那么我们添加上不就可以了?
如下:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
那么这样会带来什么问题呢?
这样带来的问题就是在最近任务列表里面会出现两个相同的应用程序,比如你是在电话本里面启动的,那么最近任务列表就会出现两个电话本;因为有两个Task嘛!

那怎么解决呢?
其实也非常好解决,只要在新的Task里面的Activity里面配置android:excludeFromRecents=”true”就可以了。表示这个Activity不会显示在最近列表里面。


四. Activity.startActivity()为什么不出现这个异常呢?

要回答这个问题,需要看下Activity.startActivity()调用到哪里去了
代码文件:
frameworks\base\core\java\android\app\Activity.java
代码:

public void startActivity(Intent intent) {
   this.startActivity(intent, null);
}

接下来会调用startActivityForResult()->然后一路调用到Ams去启动Activity;
原来如此,Activity重写了startActivity()方法…


五. Android 为什么要这么设计?

那现在来回答这个问题,为什么Android在Service 里面启动Activity要强制规定使用参数FLAG_ACTIVITY_NEW_TASK呢?

我们可以来做这样一个假设,我们有这样一个需求:
我们在电话本里面启动一个Service,然后它执行5分钟后,启动一个Activity
那么很有可能用户在5分钟后已经不在电话本程序里面操作了,有可能去上网,打开浏览器程序了。
5分钟后,此时当前的Task是浏览器的task,那么弹出Activity,如果这个Activity在当前Task的话,也就是浏览器的Task;那么用户就会觉得莫名其妙;因为弹出的Activity和浏览器在一个Task,本来这个Activity应该属于电话本的。

所以,对于Service而言,干脆强制定义启动的Activity要创建一个新的Task.
这种设计,我觉得还是比较合理的。


六. 转载地址 :

http://bbs.51cto.com/thread-1133875-1.html

3. Matérn协方差模型与随机偏微分方程 对应的高斯马尔可夫随机场 (GMRF)可以通过使用某种随机偏微分方程(SPDE)明确构造,当由高斯白噪声驱动时,随机偏微分方程的解是具有 Matérn 协方差函数的高斯场(GF) 阅读详情

相关推荐

vue3+SuperMap iClient3D for Cesium实现可视域分析功能

基于Vue3框架及SuperMap iClient3D for Cesium提供的ViewShed3D类实现场景动态可视域分析

qq_43334519的博客 2248

Android中在service中启动activity

启动activity: Intent intent = new Intent(this,MainActivity.class); startActivity(intent); 报错:android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires...

aidou1314的博客 4483

ROS入门(一)——ROS安装(vmware16+ubuntu20.04+ROS-Noetic)

嵌套:ROS可以在Ubuntu上运行,Ubuntu在虚拟机Vmware中安装。 从 虚拟机vmware安装→ubuntu安装→ros安装,逐步介绍安装ROS环境的过程。整个过程是我一步步跟着各种博客安装实现的,亲测可行。 版本: Vmware :Vmware Workstation16 Ubuntu :20.04 ROS :Noetic 其中vmware直接载当前最新版本就好,而ubuntu的版本要注意一下。 在ROS官网(cn - ROS Wiki),我们进入到ROS安装的步骤界面,可以看..

Netceor的博客 9741

service启动activity_「 Android 10 四大组件 」系列—Service 的 " 启动流程 "

作者:DeepCoder核心源码关键类路径Service 的启动过程相对 Activity 的启动过程来说简单了很多,我们都知道怎么去创建和启动一个 Service, 那么你有没有从源码角度研究过 Service 启动后在系统层是如何运作的 ?第一次看我文章的小伙伴可以关注一下我,顺便关注一下我的专栏:Android高级开发架构技术专栏,每天更新各种技术干货,分享更多最热程序员圈内事。Androi...

weixin_39576133的博客 389

EMI辐射发射超标案例

EMI辐射发射超标案例

让你爱上电路设计 8503

1、硬件工程师笔面试真题汇总(2025版本)

答:按照使用习惯,电源指示灯用红色,信号指示灯用绿色这两种颜色的LED 灯技术最成熟,价格最便宜通孔是贯穿整个PCB 的过孔盲孔是从PCB 表层连接到内层的过孔埋孔是埋在PCB 内层的过孔。大多数PCB厂家的加工能力是这样的:大于等于8mil 的过孔可以做机械孔小于等于6mil 的过孔需要做激光孔对小于等于6mil 的微型孔,在钻孔空间不够时,允许一部分过打在PCB 焊盘上。

XU157303764的博客 2万+

Android-Service里面如何启动Activity?为什么要这么做?

目录1. 一个应用中有多少个Context,它们之间的区别是什么?2. Service/广播中是否可以启动Activity?为什么? 1. 一个应用中有多少个Context,它们之间的区别是什么? Context数量=Activity数量+Service数量+Application 从图中我们知道: Context其实是一个抽象类,它有两个子类:ContextImpl、ContextWrapper,ContextImpl是context的功能具体实现类,而ContextWrapper则是一个包装类,主要

吴唐人的博客 7443

OpenClaw(Clawdbot/Moltbot)如何正确的配置浏览器,实现对浏览器的自动化操作功能(浏览器状态为running:false怎么办)

OpenClaw(Clawdbot/Moltbot)浏览器自动化功能无效?🤖 本文详细介绍如何解决这个问题🔧,让你的OpenClaw(Clawdbot/Moltbot)真正具备"睁眼看世界"的能力,支持网页搜索、点击操作和截图等功能 ✅

XiaoqiangClub的博客 8110

Android 在Service里面启动Activity

Android 在Service里面启动Activity

qq_27494201的博客 706

RestFul API 详解

RESTful API 经常也被叫做 REST API,它是基于 REST 构建的 API。RESTful API 可以让你看到 URL+Http Method 就知道这个 URL 是干什么的,让你看到了 HTTP 状态码(status code)就知道请求结果如何。

wynn的博客 7584

【BlueDroid】蓝牙音乐协议分析之A2DP和AVRCP连接流程(超详细)

AVCTP协议描述了蓝牙设备间Audio/Video的控制信号交换的格式和机制,他是一个总体的协议,具体的控制信息由其指定的协议(AVRCP)实现,AVCTP协议本身只指定控制Command和Response的总体的格式;这个过程中对应了Event中的btavrcp_play_status_changed_callback和btavrcp_play_position_changed_callback;上述为AVCTP-Control建立L2CAP连接的Command,对应H4的Sent (0x00);

风云说通信 7316

Android Activity 的启动流程

当我们启动Actitivity 或者关闭Activity 时,我们经常说这个活动入栈或者出栈了,那到底是什么入栈出栈了呢?这里有一点要注意的是这里我们调用了一个startPausingLocked ()方法, 如果当前获取焦点的Activity不为null, 我们还要暂停它,最终调用了当前活动的onPause() 方法,也就是说在开启新的Activity之前要先暂停当前Activity,所以为了使新启动的Activity 更快的启动,我们不要在onPause() 方法中做过多的操作。

JeffTang2020的博客 1397

链路状态路由协议 OSPF (一)

本章将会学习链路状态路由协议OSPF,理解OSPF的基本概念,工作原理,掌握OSPF配置基本命令。本章重点,OSPF的基本概念,OSPF配置。

yj11290301的博客 3475

Android Service中如何启动Activity(发生异常的原因,如何解决)

在Activity中其中startActivity这个大家应该是非常熟悉的;那么从service里面调用startActivity话,会怎么样呢? 会出现下面的异常: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires th

庭前梧桐树 1679

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

在android的service中启动一个通知,点击通知无法启动activity,报一个SecurityException异常

10-15 17:21:38.992: W/ActivityManager(1663): Permission Denial: starting Intent { cmp=com.dawning.gridview/.activity.MessageDetailActivity bnds=[35,-1733][1047,-1541] (has extras) } from null (pid=-1,

huanchengdao的博客 857

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

android开发:activity上下文之外启动activity注意的地方

有过一点android经验的同学应该知道,在activity之外去启动一个activity一般会报这么一个异常。 解决办法是需要我们设置:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); android.util.AndroidRuntimeException: Calling startActivity() from outside of an...

一个程序员-二白的博客 672

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

android 从service启动/打开activity

后面这个thread位于一个service类的内部,也算是从service启动activity了。

310

android flag_activity_new_task结束,非activity环境启动activity还需要FLAG_ACTIVITY_NEW_TASK吗?...

2018-11-7更新更新先说结果原理上按照设计,service,application,broadcast不能直接startActivity,除非加上FLAG_NEW_TASK但是api 23 ,也就6.0以下的遵循了该设计原则api 24,25,26,27官方出现了bug,不加flag也能正常启动,bug就是 &&option!=nullapi 28 解决了该笔bug背景之前...

weixin_39930748的博客 349

android service java_Android 在Service中启动Activity的大坑

在Activity中其中startActivity这个大家应该是非常熟悉的;那么从service里面调用startActivity话,会怎么样呢?会出现下面的异常:android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_A...

weixin_31951365的博客 610

Android 在Service中启动Activity的大坑

一    Context的继承关系图 二    异常如何产生 三    解决这个异常后会出现问题 四    ActivitystartActivity为什么不出现这个异常呢 五    Android 为什么要这么设计 六 样例代码 Service 启动 Dialog 使用 WindowManager 实现 使用 Activity 实现 在Activity中其中startActivity这个大家应该是

姚佳伟 2万+

android service 启动和关闭不在同一个Activity的问题

在android2.3版本上可以在一个的activity中直接stopService()关闭同一应用另外一个activity启动的service,但是把sdk换成4.0.3以上的版本,就会抛出异常,这是我问题的来源。

出头天 2729

Service里启动Activity

我想我们一般在Service里想启动Activity一定会这样写: Java代码   Intent intentv = new Intent(Intent.ACTION_VIEW);              intentv.setData(uri);              intentv.putExtra("keepTitle", true);            

RuiMan的博客 649

【Android】Activity、Fragment和Service初始化顺序

通过运行时报错,分析了Activity、Fragment和Service在初始化时的各函数执行顺序。

m0_60964043的博客 391

android 自定义通知崩溃,Android自定义处理崩溃异常

用过安卓手机的用户以及安卓开发者们会时长碰到程序异常退出的情况,普通用户遇到这种情况,肯定非常恼火,甚至会骂一生垃圾软件,然后卸载掉。那么开发者们在开发过程中遇到这种情况给怎么办呢,当然,你不可能世界上的每个安卓手机你都要试试你的程序有没有异常,这是无法办到的事情,所以最好的办法就是,当普通用户遇到这种情况时,让应用自动把错误信息发送到你的服务器,然后你去分析异常原因,这是不是一件很有意义的事情啊...

weixin_33378570的博客 269
上一篇: android button 字母自动变大写原因以及属性总结
下一篇: java 线程 --- Thread,Runnable,Callable 基础学习
android_小路
博客等级 码龄12年 53粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值