精华内容
下载资源
问答
  • 我们以 startActivity(Intent) 这个最常用的 api 来讲。 1. 首先,Context 类有一个 abstract 方法 /** * Same as {@link #startActivity(Intent, Bundle)} with no options * specified. * * @param ...

    我们以 startActivity(Intent) 这个最常用的 api 来讲。

    1. 首先,Context 类有一个 abstract 方法

      /**
         * Same as {@link #startActivity(Intent, Bundle)} with no options
         * specified.
         *
         * @param intent The description of the activity to start.
         *
         * @throws ActivityNotFoundException  
         *`
         * @see #startActivity(Intent, Bundle)
         * @see PackageManager#resolveActivity
         */
        public abstract void startActivity(Intent intent);
    


    2. Context 的一个子类叫 ContextWrapper ,ContextWrapper 虽然实现了 startActivity (Intent) 方法,但是很简单,因为需要实例化,所以必须要实现父类中的 abstract 方法。

      @Override
        public void startActivity(Intent intent) {
            mBase.startActivity(intent);
        }


    3. ContextWrapper 有一个子类叫 ContextThemeWrapper ,这个类并没有实现startActivity(Intent) 方法。


    4. Activity 的定义如下:

    public class Activity extends ContextThemeWrapper
            implements LayoutInflater.Factory2,
            Window.Callback, KeyEvent.Callback,
            OnCreateContextMenuListener, ComponentCallbacks2,
            Window.OnWindowDismissedCallback {
    }
    

    其实现了 startActivity(Intent) 方法:

    /**
         * Same as {@link #startActivity(Intent, Bundle)} with no options
         * specified.
         *
         * @param intent The intent to start.
         *
         * @throws android.content.ActivityNotFoundException
         *
         * @see {@link #startActivity(Intent, Bundle)}
         * @see #startActivityForResult
         */
        @Override
        public void startActivity(Intent intent) {
            this.startActivity(intent, null);
        }
    
        @Override
        public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }


    所以结论就是,这两个货是一样的...你在调用的时候,其实最终调用的都是 Activity 类实现的 startActivity 方法。
    之所以会有这样的写法,是因为下面两个在 Activity 中是等价的

    this.startActivity(intent);
    context.startActivity(intent);



    另外 Context 的子类也有其他实现 startActivity 的,比如 ContextImpl.java, 这时候就需要一个 flag :FLAG_ACTIVITY_NEW_TASK ,否则就会抛出异常。

    @Override
        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);
        }
    


    至于为什么非 Activity 实现的 startActivity 方法需要加这个 flag , 是因为在 Activity 的 startActivity 的实现中,会判断如果没有这个 flag , 就会自动把这个新的 Activity 加到现有的 task 里面。
    而其他的 Context 或者其子类的实现中, 是没有这种判断的, 所以需要使用者指定这个 flag ,以便 AMS 将其加入到其自己的 task 中。






    展开全文
  • 先看下 Context.java 中...public abstract void startActivity(@RequiresPermission Intent intent); /** * Launch a new activity. You will not receive any information about when * the activity exits. ...

    先看下 Context.java 中的函数定义:

    public abstract void startActivity(@RequiresPermission Intent intent);
    
    /**
     * Launch a new activity.  You will not receive any information about when
     * the activity exits.
     *
     * <p>Note that if this method is being called from outside of an
     * {@link android.app.Activity} Context, then the Intent must include
     * the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag.  This is because,
     * without being started from an existing Activity, there is no existing
     * task in which to place the new activity and thus it needs to be placed
     * in its own separate task.
     *
     * <p>This method throws {@link ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param intent The description of the activity to start.
     * @param options Additional options for how the Activity should be started.
     * May be null if there are no options.  See {@link android.app.ActivityOptions}
     * for how to build the Bundle supplied here; there are no supported definitions
     * for building it manually.
     *
     * @throws ActivityNotFoundException &nbsp;
     *
     * @see #startActivity(Intent)
     * @see PackageManager#resolveActivity
     */
    public abstract void startActivity(@RequiresPermission Intent intent,
            @Nullable Bundle options);
    
    

    从注释中可以很清楚的看到,如果 Context is not an Activity,则通过 Context.startActivity() 的时候,必须加上一个 Intent.FLAG_ACTIVITY_NEW_TASK 标志。因为非 Activity环境启动Activity 的时候没有 Activity 栈,所以需要加上这个标志位新建一个栈。

    ContextImpl.java -> Context.java

    找到实现类 ContextImpl.java 「Api Level 27」对这两个接口的实现:

    @Override
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }
    
    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
    
        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in.
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
            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 () 语句有三个判断条件。

    • (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
    • options != null
    • ActivityOptions.fromBundle(options).getLaunchTaskId() == -1

    当这三个条件都满足了才会 throw AndroidRuntimeException

    这里看到一个问题,当没有对 intent 设置 Intent.FLAG_ACTIVITY_NEW_TASK 这个 flag,然后 options 这个参数为 null 的时候,是不会进入 if () 的函数块的,而是直接执行到了 execStartActivity() .

    这不会有什么问题吗? 前面说到通过 Context.startActivity() 的时候需要设置NEW_TASK 标识,因为它是没有 activity 任务栈的,那通过上面的代码分析,发现这种启动方式并没有抛出异常。难道系统有 bug?

    特意找了一个 API Level27的手机写了一个 demo 跑了一下,发现确实没有抛出 AndroidRuntimeException,而是正常启动了 activity。

    这是为啥?????

    在这里插入图片描述

    仔细查看 logcat 发现一条关键的日志:

     W/ActivityManager: startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { cmp=com.jacksen.demo.view/.MainActivity }
    

    含义就是,通过非 Activity startActivity 的时候,会强制添加 Intent.FLAG_ACTIVITY_NEW_TASK 这个 flag。

    在这里插入图片描述

    谷歌闹着玩呢?!!

    如果都是通过 Context.startActivity(Intent) 这种方式来启动 activity 的话,岂不是每个 activity 都是一个任务栈,if() 里面的 「throw AndroidRuntimeException 」也没机会被执行到。

    废物代码吗?

    。。。。

    然后找了一个 API Level 28 的手机跑同一个 demo,发现直接 crash 了!

    从这里就能猜到不同Android 系统版本,对这种情况的处理不一致。

    找一下 API level 28 系统下 ContextImpl.startActivity() 的源码如下:

    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
    
        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
        // maintain this for backwards compatibility.
        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;
    
        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && (targetSdkVersion < Build.VERSION_CODES.N
                        || targetSdkVersion >= Build.VERSION_CODES.P)
                && (options == null
                        || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
            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 的条件变成了:

    • (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
    • (targetSdkVersion < Build.VERSION_CODES. N
      || targetSdkVersion >= Build.VERSION_CODES. P)
    • (options == null
      || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)

    A bug was existed between N and O-MR1 which allowed this to work. We maintain this for backwards compatibility.

    从这段注释很清楚的看到,从 N (API Level 24)O-MR1 (API Level 27) 的系统版本有一个 bug ?。

    谷歌官方的处理是保持向下兼容, 也就是 bug 依然存在  ̄□ ̄||。

    展开全文
  • Hook StartActivity Demo

    2016-11-17 22:41:47
    Hook StartActivity Demo
  • java.lang.RuntimeException: Unable to start activity ComponentInfo---getSupportActionBar()为null。

    报错信息:

    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.example.edm, PID: 16919
        java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.edm/com.example.edm.StudentActivity.TimeTable.ui.editcourse.EditActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.appcompat.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3773)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3952)
            at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
            at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
            at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
            at android.os.Handler.dispatchMessage(Handler.java:107)
            at android.os.Looper.loop(Looper.java:213)
            at android.app.ActivityThread.main(ActivityThread.java:8169)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
         Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.appcompat.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference
            at com.example.edm.StudentActivity.TimeTable.ui.editcourse.EditActivity.setActionBar(EditActivity.java:248)
            at com.example.edm.StudentActivity.TimeTable.ui.editcourse.EditActivity.onCreate(EditActivity.java:75)
            at android.app.Activity.performCreate(Activity.java:8086)
            at android.app.Activity.performCreate(Activity.java:8074)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1313)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3746)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3952) 
            at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91) 
            at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149) 
            at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103) 
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386) 
            at android.os.Handler.dispatchMessage(Handler.java:107) 
            at android.os.Looper.loop(Looper.java:213) 
            at android.app.ActivityThread.main(ActivityThread.java:8169) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101) 
    

    错误原因:

    private void setActionBar() {
            ActionBar actionBar = getSupportActionBar();
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setTitle(R.string.course_edit);
        }
    

    代码中actionBar为空指针。

    解决方案:检查AndroidManifest.xml文件中相关Activity的theme是否为:

    android:theme="@style/Theme.AppCompat.Light.NoActionBar"
    

    将其改为:

    android:theme="@style/Theme.AppCompat"
    
    展开全文
  • 原文链接:... 1. 首先,Context 类有一个 abstract 方法 /** * Same as {@link #startActivity(Intent, Bundle)} with no options * specified. * ...

    原文链接:https://blog.csdn.net/u011694328/article/details/53355361

    1. 首先,Context 类有一个 abstract 方法

    /**
         * Same as {@link #startActivity(Intent, Bundle)} with no options
         * specified.
         *
         * @param intent The description of the activity to start.
         *
         * @throws ActivityNotFoundException  
         *`
         * @see #startActivity(Intent, Bundle)
         * @see PackageManager#resolveActivity
         */
        public abstract void startActivity(@RequiresPermission Intent intent);

    2. Context 的一个子类叫 ContextWrapper ,ContextWrapper 虽然实现了 startActivity (Intent) 方法,但是很简单,因为需要实例化,所以必须要实现父类中的 abstract 方法。

    @Override
     public void startActivity(Intent intent) {
         mBase.startActivity(intent);
     }

    3. ContextWrapper 有一个子类叫 ContextThemeWrapper ,这个类并没有实现startActivity(Intent)方法。

    4. Activity 的定义如下:

    public class Activity extends ContextThemeWrapper
         implements LayoutInflater.Factory2,
         Window.Callback, KeyEvent.Callback,
         OnCreateContextMenuListener, ComponentCallbacks2,
         Window.OnWindowDismissedCallback {
    }

    其实现了 startActivity(Intent) 方法:

    /**
     * Same as {@link #startActivity(Intent, Bundle)} with no options
     * specified.
     *
     * @param intent The intent to start.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see {@link #startActivity(Intent, Bundle)}
     * @see #startActivityForResult
     */
     @Override
     public void startActivity(Intent intent) {
         this.startActivity(intent, null);
     }
     @Override
     public void startActivity(Intent intent, @Nullable Bundle options) {
         if (options != null) {
             startActivityForResult(intent, -1, options);
         } else {
             // Note we want to go through this call for compatibility with
             // applications that may have overridden the method.
             startActivityForResult(intent, -1);
         }
     }

    所以结论就是,这两个货是一样的...你在调用的时候,其实最终调用的都是 Activity 类实现的startActivity 方法。之所以会有这样的写法,是因为下面两个在 Activity 中是等价的。

    this.startActivity(intent);
    context.startActivity(intent);

    另外Context 的子类也有其他实现startActivity的,比如ContextImpl.java,这时候就需要一个flag:FLAG_ACTIVITY_NEW_TASK ,否则就会抛出异常。

    @Override
     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);
     }

    至于为什么非 Activity 实现的 startActivity 方法需要加这个 flag , 是因为在 Activity 的 startActivity的实现中,会判断如果没有这个 flag , 就会自动把这个新的 Activity 加到现有的 task 里面。而其他的 Context 或者其子类的实现中, 是没有这种判断的, 所以需要使用者指定这个 flag ,以便AMS 将其加入到其自己的 task 中。

    展开全文
  • Android Activity startActivity流程简介

    千次阅读 2018-11-14 10:35:30
    Android Activity startActivity流程简介
  • 在非Activity中使用startActivity:Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag 问题描述 在APP 1中启动APP 2中的Activity。 Intent intent = new ...
  • Kotlin activity跳转-startActivity

    千次阅读 2017-11-18 10:21:38
    startActivity(Intent(MainActivity@this, SecondActivity::class.java)) 或者 startActivity(Intent(this@MainActivity, SecondActivity::class.java)) 或者 startActivity(Intent(this, SecondAct
  • StartActivity的2种用法

    万次阅读 2019-03-12 15:50:24
    startActivity有2种用法 1.显示调用。通过指明ComponentName,显示调用Activity,若 Intent intent = newIntent(CustomerService.this, DetailInfo.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ...
  • startActivity()详解

    万次阅读 2018-08-02 11:43:51
    startActivity()详解 class ReceiverRestrictedContext extends ContextWrapper { ReceiverRestrictedContext(Context base) { super(base); } } final Context getReceiverRestrictedContext...
  • appium startActivity使用方法

    千次阅读 2019-11-20 14:21:49
    appium startActivity使用方法1.构造方法2.要开启的Activity 1.构造方法 说明:构造方法的二个参数,请使用aapt dump badging a.apk获取到的参数,如果指定其它Activity会报Permission Denial: starting Intent { ...
  • 非Activity环境startActivity的正确姿势

    千次阅读 2019-05-28 22:07:49
    对于Android7.0~8.1系统,调用`startActivity(Intent intent)`可以不用加标记,调用startActivity(Intent intent, Bundle options)时,options有值则需注意加标记或为options添加上指定的LaunchTaskId。
  • android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
  • 两个Activity在调用StartActivity的时候传递序列化信息
  • Kotlin实现Activity跳转(startActivity)

    千次阅读 2018-11-28 16:49:54
    方式一 val intent = Intent(context, ...startActivity(intent) 方式二 val intent = Intent(context, SecondActivity::class.java) startActivity(intent) 安卓开发技术分享: https://blog.csdn.net/...
  • StartActivity的流程

    千次阅读 2012-11-21 21:08:50
    1. Activity.startActivity(Intent intent)  public void startActivity(Intent intent) { startActivity(intent, null); } 调用内部重载函数startActivity @Override public void start
  • Window window = am.startActivity(id, intent); View view = window.getDecorView(); container.addView(view); } 调试发现在am.startActivity中出错,在mainfest中已经注册了MySchedule.class,不知道...
  • 一、startActivity( ) 与startActivityForResult( )的区别 1、startActivity( )  startActivity( ) 仅仅是启动另一个Activity,他不会自定回转到原来的Activity,若是想跳回原来的页面,则必须再使用一次start...
  • 使用Kotlin如何startActivity

    万次阅读 2017-06-16 10:39:27
    转载注明出处:简书-十个雨点没错,就是这么简单的一个功能,不过由于初学kotlin,所以找了很久才找到如何写,所以还是贴出来给需要的人吧,上代码:startActivity(Intent(MainActivity@this, SecondActivity::class...
  • 报错: Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? 从我上一篇转...
  • Android中调用startActivity结果导致:上网查了一下,总结如下: 第一种情况:java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}: java.lang.NullPointerException 错误代码: private...
  • 本文基于api 24,Activity的启动过程之startActivity源码解析
  • Activity的启动过程--startActivity()

    千次阅读 2016-04-26 17:40:50
    当我们调用startActivity()启动一个Activity的时候,首先他会调到startActivityForResult()方法: @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { ...
  • android startActivity 过慢

    2015-09-15 02:23:19
    在service的startActivity(intent)之前也打了log Log.i("1234", "realstart"+System.currentTimeMillis()); startActivity(it); 结果俩个log中间耗时超过3-4s,仅当回到桌面后按home键 或者进入别...
  • 今天遇到一个问题就是,如何在非activity里面使用startActivity(); 解决办法如下、 需要我们有context intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent);
  • 跳转Activity报错:Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? at android.app.ContextImpl.startActivity...
  • BroadcastReceiver中使用startActivity报错

    千次阅读 2017-07-12 09:55:50
    在写开机启动activity的时候, 在BroadcastReceiver中使用context.startActivity 报错,错误如下: Caused by: Android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity ...
  • startActivity(intent);然后finish(); activity的切换效果是缩放的那种 finish();然后startActivity(intent);
  • Unable to start activity ComponentInfo

    千次阅读 2018-01-04 14:02:00
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.zhy.sample.folderlayout/com.all.activity.BleLightControlActivity}: android.view.InflateException: Binary XML file line #10: Binar

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 340,727
精华内容 136,290
关键字:

startactivity