APM之Android应用的启动次数(2)

怎么防止sdk反复启动呢?---->一次启动对于应用来说算一次启动次数

  private static boolean started = false;

  public void start(Context context)  //sdk初始化执行的逻辑
  {
    if (started) {         //用一个变量防止重复初始化.
      log.debug("NewRelic is already running.");
      return;
    }
    try {
      AgentLogManager.setAgentLog(new NullAgentLog());
      log.setLevel(this.logLevel);

      if (isInstrumented()) {                               //如果使能成功才改变started的值.
        AndroidAgentImpl.init(context, agentConfiguration);
        started = true;
      } else {
        log.error("Failed to detect New Relic instrumentation.  Something likely went wrong during your build process and you should contact support@newrelic.com.");
        return;
      }
    } catch (Throwable e) {
      log.error("Error occurred while starting the New Relic agent!", e);
    }
  } 
  private boolean isInstrumented()  
  {
    return false;   //是不是感觉很奇怪?为什么直接返回false?那么sdk怎么改变started的值?
  }

虽然在sdk中 isInstrumented()返回的是false,编译成功以后这个值就变成true了

原因是在Apk编译的时候,在java文件生成class文件,进而生成dex文件的时候, rewriter.jar包会起作用,会把这个值修改为true. 这里的原理以后再说.

(表明rewriter在用户apk中嵌码的流程已经生效了,而不仅仅是添加了agent的jar包版本, 这个过程俗称使能.)

为了防止sdk反复初始化.要求上面的初始化方法必须嵌入在Activity的onCreate()方法中. 

 

注意点:

1.初始化代码不要嵌在Appliation的onCreate()方法中. 有可能出现多进程多次初始化的问题.

  不同的进程是不同的dalvik虚拟机,所以会有多个agent初始化.上面的变量started每个进程都会有一个.所以会多次初始化.

2.Asm是通过对java的字节码进行操作嵌码的. 字节码中只有类的父类信息.没有其父类以上的继承信息. 所以如果ActivityA extends BaseActivity; BaseActivity extends Activity.

  那么ActivityA因为其父类BaseActivity无法确认是否是Activity的子类,所以不会被嵌码. BaseActivity会正常嵌码. 

  型号的是在运行的时候. ActivityA生命周期的onStart() onStop()调用的时候.其父类BaseActivity的onStart(),onStop()也会正常执行.前面的ApplicationStateMonitor.activityStart()和activityStop()也会正常执行一次.

3.低端版本的Android可能存在按电源键锁屏 不会走Activity生命周期的onStop()方法.------->一个apk minsdkVersion=4的时候出现过.

 

posted @ 2015-04-24 21:04  laiqurufeng  阅读(588)  评论(0编辑  收藏  举报