当前位置: 代码迷 >> Android >> android 源码有关问题解答(错误处理)
  详细解决方案

android 源码有关问题解答(错误处理)

热度:668   发布时间:2016-04-28 02:20:05.0
android 源码问题解答(异常处理)

case1:如何做到按back键不退出应用后台继续运行?

在基类activity会调用onBackPressed这个方法,这个方法会finish当前这个activity,使得当前activity走到onDestory,如果想要按back键不走到onDestory,需要复写onBackPressed方法
    @Override
public void onBackPressed() {
// TODO Auto-generated method stub
// super.onBackPressed();
     moveTaskToBack(true);
}
调用moveTaskToBack(true),让任务在后台执行,与按home键的效果一样
case2:android调试如何获得时间差
1,引用如下命名空间:
import java.util.Date;
import android.text.format.DateFormat;
2,设置时间格式:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
3,获取时间:
Date   curDate   =   new   Date(System.currentTimeMillis());
     //PROCESSING
Date   endDate   =   new   Date(System.currentTimeMillis());
long diff = endDate.getTime() - curDate.getTime();
这样获取的就是时间间隔了,并且是ms级别的,通过log就可以打印出来

case3:listview如何在显示的时候默认跳转到最后一条记录开始的地方而不是结尾?

系统中listview显示很多条数据时,或者一条数据过长时,比如超过整个屏幕的高度,那么显示的时候就会自动跳转到最后一条数据的结尾,这是由属性transcriptMode来控制的

属性所用到值及意义为:

disabled 0 Disables transcript mode. This is the default value. 

normal 1 The list will automatically scroll to the bottom when a data set change notification is received and only if the last item is already visible on screen. 

alwaysScroll 2 The list will automatically scroll to the bottom, no matter what items are currently visible. 


但是我们如果想要滚动,又不想让它跳转到最后一条记录开始的地方就要在代码中设置如下:

mListView.setSelection(listviewAdapter.getCount())

另外用transcriptMode属性的默认值即disabled

case4:在浏览器中反复测试同一问题有时会出现"浏览器停止运行"?比如说不断的添加书签,不断的点播视频等等

1.问题分析

出现这种问题一般会在main.log中打印如下trace:

11-19 06:00:46.570   880  1870 E CursorWindow: Could not allocate CursorWindow '/data/data/com.android.browser/databases/browser2.db' of size 2097152 due to error -24


这代表是FD超标了,android中fd的数量上限为1024,超过此数目,就会报上述异常。


也可以用下述命令进一步确认是否是fd超标及哪些文件句柄超标:

adb shell
ps | busybox grep com.android.browser得到 pid
lsof | busybox grep pid

用busybox命令必须保证是在userdebug版本而非user版本

如果发现用上述命令得到fd的数量很大,而且有不断递增的趋势,一般超过300就认为是异常了,最高不会超过1024


2.问题定位

首先是排查自己添加的代码有无fd泄漏,比如cusros没有关闭或者关闭异常,thread执行关闭没有释放,这些是最常见的fd超标。

确认自己的代码没问题,怀疑是平台的问题,就可以把log及browser代码提交给展讯来分析了。

caes5:在android中,常见的任务延迟怎么实现呢?

1.最常见的就是用thread了,一般为:

new Thread(new Runnable(){ 
    public void run(){ 
        Thread.sleep(n); 
        handler.sendMessage();//去告诉主线程可以开始工作了
    } 
}).start 

2.用handler来实现

 new Handler().postDelayed(new Runnable(){
     public void run(){
            //做你想做的事
      }
 }, delay);

3.用timer来实现

timer = new Timer(true);
timerTask = new TimerTask() {
      public void run() {
         //做你想做的事
        }
};
timer.schedule(timerTask, delay);

这三种方式是我们经常用到的。

4.用定时器AlarmManager来实现,我们经常用到的日历和闹钟就是主要用到了这个服务;主要功能就是在特定的时刻为广播一个指定的Intent;简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent


case6:如何衡量代码性能?

Java和Android提供了以下的API,让应用可以测量时间及性能:

    System.currentTimeMillis

    System.nanoTime

    Debug.threadCpuTimeNanos

    SystemClock.currentThreadTimeMills

    SystemClock.elapsedRealtime

    SystemClock.uptimeMillis

以上函数即使有些方法返回时间用纳秒表示,并不意味着精度是纳秒级的。实际精度取决于平台。毫秒精度的一样的道理。

测试时间的典型代码:

long startTime = System.nanoTime();

//待测代码

long duration = System.nanoTime() - startTime;

这段代码全引用的java类,因此可以用在Android以外的平台。而Debug和SystemClock类是Android独有的。

 

尽管System.currentTimeMillis()可以作为测量时间的手段,但不建议使用这种方法,原因如下:

1)其精度和准确度不够

2)更改系统时间会影响其结果

建议使用System.nanoTime(),因为它提供了更好的精度和准确度。System.nanoTime()没有定义参考时间,只能用来测量时间间隔。而System.currentTimeMilis()返回值是UTC时间1970年1月1日00:00:00到现在的毫秒数。

 System.nanoTime()本身的执行时间在750纳秒的数量级上。

 

注意进行测量的操作可能因为多线程而被中断几次,来让出CPU时间给别的线程。因此,测量结果可能包括一些执行其他代码的时间,这可能会得出不正确的时间测量结果,产生误导。可以使用Android的Debug.threadCpuTimeNano()方法测量代码的执行时间,这个方法更好些。因为Debug.threadCpuTimeNanos()只测量在当前线程中所花费的时间,所以它的结果更准确。不过,如果要测量的部分运行在多个线程上,只调用一次Debug.threadCpuTimeNanos()不会给出准确的估值,必须在所有涉及的线程调用此方法并把结果相加。

case7:如何确认手机SIM卡是否掉卡以及出现掉卡该如何处理
可以通过分析android radio log 中“AT+CPIN?”命令的查询结果来确认SIM卡当前的状态。  

  04:03:56.470   164   855 D use-Rlog/RLOG-AT: [w] Channel1: AT> AT+CPIN?
  04:03:56.470   164   190 D use-Rlog/RLOG-AT: [w] Channel1: AT< +CME ERROR: 10

  正常的情况下,通常会返回 +CPIN:xxxx 或者 是直接返回OK。
  当返回+CME ERROR并且error cause为‘10’,即说明是手机是发生了SIM掉卡的现象。
  

  发生SIM掉卡后,请优先提供modem log供分析是否软件异常导致,

  另外,需要硬件同步确认是否有射频干扰以及卡槽松动的情况。

caes8:如何定位modem复位重启的问题

modem发生复位重启的时候,会出现掉网/掉卡/掉话等通信相关功能的异常,
  如何定位当前是否发生modem复位,可以查询android 的main log中是否有类似如下关键信息(modem assert happen)
  02-25 10:08:02.041 137 393 D MODEMD : buf=TD Modem Assert in file dspintisr.c at line 460 exp=(FALSE) info=[dsp assert 0x1002,0x1,0xa,0x5565]
  02-25 10:08:02.041 137 393 D MODEMD : modem assert happen
  

  如上log信息中

  第一行表示modem部分哪个文件的哪一行发生执行异常,

  第二行表示modem assert异常发生。


case9:如何分析通话异常的相关问题

室内或者外场测试中,经常会发生电话呼叫失败,电话无法接听以及通话过程中掉话等问题,可以通过android radio log中"AT^DSCI"初步分析通话的流程是否正常以及通话状态的切换。
 
  DSCI的相关参数的说明如下,具体的每个返回值表示的意义可以参考展讯官方发布的AT手册:
  ^DSCI: <id>,<idr>,<stat>,<type>,<mpty>,<number>,<num_type>,[<bs_type>][,cause]
  <id> : call id,取值为1-7
  <idr>: 区分主叫和被叫
  <stat>:说明当前电话的状态,比如拨号中,振铃中,接通中,挂断等
  <type>:voice call or data call,通常都是语音通话(0)
  <mpty>: 是否多方通话
  <number>:对端的电话号码
  <num_type>:号码的类型,参考TS 24.008,通常不需关注
  [<bs_type>]:适用与data call的情况下,通常不需关注
  [,cause]:通话挂断的原因

  

案例log分析:

 //拨打10086的号码

  02-19 11:10:26.210 161 825 D AT : [w] Channel2: AT> ATD10086;
  
  //主叫,拨打过程中,语音电话,非多方通话,对端号码10086
  02-19 11:10:26.280 161 365 D AT : [w] Channel0: AT< ^DSCI: 1,0,2,0,0,10086,129
  
  //主叫,接通中,语音电话,非多方通话,对端号码10086
  02-19 11:10:31.460 161 365 D AT : [w] Channel0: AT< ^DSCI: 1,0,0,0,0,10086,129
  
  //主叫,挂断,语音电话,非多方通话,对端号码10086,挂断原因34(底层链路异常)

  02-19 11:10:56.520 161 365 D AT : [w] Channel0: AT< ^DSCI: 1,0,6,0,0,10086,129,,34


case10:截屏功能的10秒保护机制

截屏功能的10秒保护机制

1. 截屏功能的10秒保护机制:
文件:PhoneWindowManager.java (frameworks\base\policy\src\com\android\internal\policy\impl)
PhoneWindowManager.takeScreenshot()函数中有如下代码:
            if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
                mScreenshotConnection = conn;
                mHandler.postDelayed(mScreenshotTimeout, 10000);
            }
该段代码的主要功能是bind上 TakeScreenshotService 后,定时10秒,如果10秒内没有完成截屏,PhoneWindowManager会主动关闭TakeScreenshotService。

2. 系统很忙时可能可能出现的问题
  A。截屏功能没有完成,并且不报错。
  B。可能报类似如下的错误,并且导致systemui(系统用户界面)退出。
  如果系统非常忙,10秒内没有完成截屏,PhoneWindowManager主动关闭了TakeScreenshotService。
  TakeScreenshotService正在走destroy流程,准备退出的时候,很多状态已经不正确。这时GlobalScreenshot去显示截屏图片等操作,就可能出错。
    AndroidRuntime: FATAL EXCEPTION: main
    java.lang.IllegalStateException: This view must be attached to a window first
     at android.view.View.buildLayer(View.java:12119)
     at com.android.systemui.screenshot.GlobalScreenshot$3.run(GlobalScreenshot.java:471)
     at android.os.Handler.handleCallback(Handler.java:615)
     at android.os.Handler.dispatchMessage(Handler.java:92)
     at android.os.Looper.loop(Looper.java:137)
     at android.app.ActivityThread.main(ActivityThread.java:4973)

3. 影响和对策。
  不影响下次进行的截屏操作。
  SystemUI退出后,能立即重启,不会影响后面的操作。
  为了减少报错几率,可以加长定时的时间。 例如15秒。
  mHandler.postDelayed(mScreenshotTimeout, 15000);


case11:如何简单快速的得知代码的调用顺序?

有时候程序单步调试比较麻烦无法进行时,同时又需要了解具体的代码调用顺序,可以在具体代码处添加下列代码,打印调用堆栈信息

    RuntimeException e = new RuntimeException("string");
    e.fillInStackTrace();
    Slog.e(TAG, "string ", e);



  相关解决方案