??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲精品VA片在线播放,午夜影视日本亚洲欧洲精品一区,亚洲一级黄色大片http://www.tkk7.com/lihao336/category/41508.html成于坚忍Q毁于Qw?/description>zh-cnFri, 03 Feb 2012 02:13:07 GMTFri, 03 Feb 2012 02:13:07 GMT60[转]不同格式证书导入keystoreҎ(gu) http://www.tkk7.com/lihao336/archive/2012/02/03/369303.htmlcalvincalvinFri, 03 Feb 2012 02:06:00 GMThttp://www.tkk7.com/lihao336/archive/2012/02/03/369303.htmlhttp://www.tkk7.com/lihao336/comments/369303.htmlhttp://www.tkk7.com/lihao336/archive/2012/02/03/369303.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/369303.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/369303.html阅读全文

calvin 2012-02-03 10:06 发表评论
]]>
Android exchange 账户讄http://www.tkk7.com/lihao336/archive/2012/01/30/369036.htmlcalvincalvinMon, 30 Jan 2012 09:13:00 GMThttp://www.tkk7.com/lihao336/archive/2012/01/30/369036.htmlhttp://www.tkk7.com/lihao336/comments/369036.htmlhttp://www.tkk7.com/lihao336/archive/2012/01/30/369036.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/369036.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/369036.html关键点: “服务器”一栏,默认为gmail.comQ应该改为?font color="#FF0000">m.google.com”,然后l箋卛_?img src ="http://www.tkk7.com/lihao336/aggbug/369036.html" width = "1" height = "1" />

calvin 2012-01-30 17:13 发表评论
]]>
setComponentEnabledSetting doesn't work on widgethttp://www.tkk7.com/lihao336/archive/2011/12/27/367332.htmlcalvincalvinTue, 27 Dec 2011 06:14:00 GMThttp://www.tkk7.com/lihao336/archive/2011/12/27/367332.htmlhttp://www.tkk7.com/lihao336/comments/367332.htmlhttp://www.tkk7.com/lihao336/archive/2011/12/27/367332.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/367332.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/367332.html
<package name="com.android.setupwizard" codePath="/system/app/SetupWizard.apk" nativeLibraryPath="/data/data/com.android.setupwizard/lib" flags="1" ft="13349457a90" it="13349457a90" ut="13349457a90" version="130" userId="10016">
<sigs count="1">
<cert index="0" />
</sigs>
<disabled-components>
<item name="com.android.setupwizard.SetupWizardActivity" />
</disabled-components>
</package>

现在需要在q行时禁用某个widgetQ同时有一个system property用来标识是否需要禁用?br />因ؓwidget实际上就是个reveiverQ它接收android.appwidget.action.APPWIDGET_UPDATE的actionQ所以开始的思\是:
创徏一个BroadcastReceiverQ接收Intent.ACTION_BOOT_COMPLETEDq个动作Q从而在启动完成后调用SystemProperties.get("disable_widget")Q如果需要禁用这个widgetQ那么调用:
PackageManager.setComponentEnabledSetting(widgetComponentNameQPackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);

但是问题是,调用q个Ҏ(gu)disable掉这个widget后,发现必须把设备重启之后才能生?..
l过googleQ发现问题出在com.android.server.AppWidgetService.java?br />原来开机后QSystemServer会调用AppWidgetService的systemReady()Ҏ(gu)Q这个方法通过PackageManager查询所有的widget receiverlgQ保存到mInstalledProviders变量列表中,q持久化widget信息?data/system/appwidgets.xml中?br />而在Launcher上长按添加widget时的那个widget列表信息也是通过AppWidgetService取得mInstalledProviders列表?br />问题在于我们通过PackageManager.setComponentEnabledSettingQ)用掉某个widget后,packagemanager实这个组件disable了,但是AppWidgetService却没有去从packagemanager reload widget信息Q这导致了mInstalledProviders中保存的widget信息q是开机时loadq来的那些信息,q没有与pmq行同步。直C一ơ开用systemReady重新加蝲widget信息才会hq个列表?br />
参考:
Dynamically enabling or disabling a widget with PackageManager.setComponentEnabledSetting does not work
http://code.google.com/p/android/issues/detail?id=6533

http://blog.csdn.net/yinlijun2004/article/details/6136108



calvin 2011-12-27 14:14 发表评论
]]>
Activity的onSaveInstanceState调用时机http://www.tkk7.com/lihao336/archive/2011/11/22/364585.htmlcalvincalvinTue, 22 Nov 2011 09:56:00 GMThttp://www.tkk7.com/lihao336/archive/2011/11/22/364585.htmlhttp://www.tkk7.com/lihao336/comments/364585.htmlhttp://www.tkk7.com/lihao336/archive/2011/11/22/364585.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/364585.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/364585.html
Activity的生命周期里q没有提到onSaveInstanceState的触发,q个函数提供了ؓ我们在某些情况下保存Activity信息的机会,但需要注意的是这个函C是什么时候都会被调用的,官方文档解释的比较清楚,Ҏ(gu)
译一下?
原文出处Qandroid-sdk-windows-1.5_r3/docs/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
protected void onSaveInstanceState (Bundle outState)
       Called to retrieve per-instance state from an activity before being killed so that the state can be restored in onCreate(Bundle) or onRestoreInstanceState(Bundle) (the Bundle populated by this method will be passed to both). This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via onCreate(Bundle) or onRestoreInstanceState(Bundle).

    在activity被杀掉之前调用保存每个实例的状?以保证该状态可以在onCreate(Bundle)或? onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState装好的)中恢复。这个方法在一个activity被杀d调用Q当? activity在将来某个时d来时可以恢复其先前状态。例如,如果activity B启用后位于activity A的前端,在某个时刻activity A因ؓpȝ回收资源的问题要被杀掉,A通过onSaveInstanceState有Z保存其用L(fng)面状态,使得来用户q回到activity A时能通过onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢复界面的状态?

    Do not confuse this method with activity lifecycle callbacks such as onPause(), which is always called when an activity is being placed in the background or on its way to destruction, or onStop() which is called before destruction. One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact.
  
    不要这个方法和activity生命周期回调如onPause()或onStop()搞؜淆了QonPause()在activtiy被放|到背景或? 自行销毁时M被调用,onStop()在activity被销毁时被调用。一个会调用onPause()和onStop()Q但不触? onSaveInstanceState的例子是当用户从activity Bq回到activity AӞ没有必要调用B的onSaveInstanceState(Bundle)Q此时的B实例永远不会被恢复,因此pȝ会避免调用它。一个调? onPause()但不调用onSaveInstanceState的例子是当activity B启动q处在activity A的前端:如果在B的整个生命周期里A的用L(fng)面状态都没有被破坏的话,pȝ是不会调用activity A的onSaveInstanceState(Bundle)的?

    The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle)). If you override this method to save additional information not captured by each individual view, you will likely want to call through to the default implementation, otherwise be prepared to save all of the state of each view yourself. If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().

      默认的实现负责了大部分UI实例状?的保?Q采用的方式是调用UI层上每个拥有id的view的onSaveInstanceState() Qƈ且保存当前获得焦点的view的id(所有保存的状态信息都会在默认的onRestoreInstanceState(Bundle)实现中恢?? 如果你覆写这个方法来保存额外的没有被各个view保存的信息,你可能想要在默认实现q程中调用或者自׃存每个视囄所有状态。如果被调用Q这个方法会 在onStop()前被触发Q但pȝq不保证是否在onPause()之前或者之后触发?

很多不明白ActivitycM包含的onSaveInstanceState和onRestoreInstanceState有什么用Q首先声 明下使用q两个方法时一定要注意情况和了解Activity的生命周期,否则有的时候? onSaveInstanceState和onRestoreInstanceState 可能不会被触发,虽然他们都是Activity的重写方法。(?Android开发网Q?

他们比较常用到的地方? Sensor、Land和Port布局的自动切换,q去Android开发网曄说过解决横屏和竖屏切换带来的数据被置I或者说onCreate被重复调 用问题,其实Android提供的onSaveInstanceStateҎ(gu)可以保存当前的窗口状态在卛_布局切换前或当前Activity被推入历? 栈,其实布局切换也调用过onPause所以被推入Activity的history stackQ如果我们的Activity在后台没有因行内存吃紧被清理Q则切换回时会触发onRestoreInstanceStateҎ(gu)?

q两个方法中参数均ؓBundleQ可以存攄?SharedPreferences 的数据,所以用它们作为当前窗口的状态保存是比较合适的。实际用代?
@Override
  protected void onSaveInstanceState(Bundle outState){
            outState.putString("lastPath", "/sdcard/android123/cwj/test");
  }


@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);

String cwjString = savedInstanceState.getString("lastPath");
}

onSaveInstanceState和onRestoreInstanceState触发的时?
已有 199 ơ阅?2011-3-10 10:32 |个h分类:Android|关键?onSaveInstanceState onRestoreInstanceState
先看Application Fundamentals上的一D话Q?
Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)
从这句话可以知道Q当某个activity变得“容易”被pȝ销毁时Q该activity的onSaveInstanceState׃被执行,除非该activity是被用户d销毁的Q例如当用户按BACK键的时候?
注意上面的双引号Q何为“容易”?a下之意就是该activityq没有被销毁,而仅仅是一U可能性。这U可能性有哪些Q通过重写一? activity的所有生命周期的onXXXҎ(gu)Q包括onSaveInstanceState和onRestoreInstanceStateҎ(gu)Q我 们可以清楚地知道当某个activityQ假定ؓactivity AQ显C在当前task的最上层Ӟ其onSaveInstanceStateҎ(gu)会在什么时候被执行Q有q么几种情况Q?
1、当用户按下HOME键时。这是显而易见的Q系l不知道你按下HOME后要q行多少其他的程序,自然也不知道activity A是否会被销毁,故系l会调用onSaveInstanceStateQ让用户有机会保存某些非怹性的数据。以下几U情늚分析都遵循该原则
2、长按HOME键,选择q行其他的程序时?
3、按下电(sh)源按键(关闭屏幕昄Q时?
4、从activity A中启动一个新的activity时?
5、屏q方向切换时Q例如从竖屏切换到横屏时。在屏幕切换之前Q系l会销毁activity AQ在屏幕切换之后pȝ又会自动地创建activity AQ所以onSaveInstanceState一定会被执?
总而言之,onSaveInstanceState的调用遵循一个重要原则,卛_pȝ“未l你许可”时销毁了你的activityQ则 onSaveInstanceState会被pȝ调用Q这是系l的责QQ因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了Q?
至于onRestoreInstanceStateҎ(gu)Q需要注意的是,onSaveInstanceStateҎ(gu)? onRestoreInstanceStateҎ(gu)“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提 是,activity A“确实”被pȝ销毁了Q而如果仅仅是停留在有q种可能性的情况下,则该Ҏ(gu)不会被调用,例如Q当正在昄activity A的时候,用户按下HOME键回C界面Q然后用L(fng)接着又返回到activity AQ这U情况下activity A一般不会因为内存的原因被系l销毁,故activity A的onRestoreInstanceStateҎ(gu)不会被执?
另外QonRestoreInstanceState的bundle参数也会传递到onCreateҎ(gu)中,你也可以选择在onCreateҎ(gu)中做数据q原

calvin 2011-11-22 17:56 发表评论
]]>
利用javap生成Ҏ(gu){֐http://www.tkk7.com/lihao336/archive/2011/10/24/361901.htmlcalvincalvinMon, 24 Oct 2011 08:04:00 GMThttp://www.tkk7.com/lihao336/archive/2011/10/24/361901.htmlhttp://www.tkk7.com/lihao336/comments/361901.htmlhttp://www.tkk7.com/lihao336/archive/2011/10/24/361901.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/361901.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/361901.html如:
 1 package com.demo;
 2 
 3 public class SigTest {
 4 
 5     public static final String name = null;
 6 
 7     public int getName(int[] data,long index) {
 8         return 0;
 9     }
10 }
11 

[calvin@calvin-desktop /tmp 15:59:50 ]
$ javac SigTest.java
[calvin@calvin-desktop /tmp 15:59:57 ]
$ javap -s -p -classpath . SigTest
Compiled from "SigTest.java"
public class com.demo.SigTest extends java.lang.Object{
public static final java.lang.String name;
  Signature: Ljava/lang/String;
public com.demo.SigTest();
  Signature: ()V
public int getName(int[], long);
  Signature: ([IJ)I
static {};
  Signature: ()V
}


-s表示打印{֐信息
-p表示打印所有函数和成员的签名信息,默认只打印public的签名信息?br />
注意Q?br />_体部分?class文g的文件名Q不?class后缀Q否则提C?br />ERROR:Could not find SigTest.class.



calvin 2011-10-24 16:04 发表评论
]]>
[转]The Android boot process from power onhttp://www.tkk7.com/lihao336/archive/2011/09/07/358158.htmlcalvincalvinWed, 07 Sep 2011 02:53:00 GMThttp://www.tkk7.com/lihao336/archive/2011/09/07/358158.htmlhttp://www.tkk7.com/lihao336/comments/358158.htmlhttp://www.tkk7.com/lihao336/archive/2011/09/07/358158.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/358158.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/358158.html

init is the first process after kernel started. The corresponding source code lies in: device/system/init. It does the following tasks step by step:

1.       Initialize log system.

2.       Parse /init.rc and /init.%hardware%.rc.

3.       Execute early-init action in the two files parsed in step 2.

4.       Device specific initialize. For example, make all device node in /dev and download firmwares.

5.       Initialize property system. Actually the property system is working as a share memory. Logically it looks like a registry under Windows system.

6.       Execute init action in the two files parsed in step 2.

7.       Start property service.

8.       Execute early-boot and boot actions in the two files parsed in step 2.

9.       Execute property action in the two files parsed in step 2.

10.   Enter into an indefinite loop to wait for device/property set/child process exit events. For example, if an SD card is plugined, init will receive a device add event, so it can make node for the device. Most of the important process is forked in init, so if any of them crashed, init will receive a SIGCHLD then translate it into a child process exit event, so in the loop init can handle the process exit event and execute the commands defined in *.rc(it will run command onrestart).

 

The .rc file is a script file defined by Android. The default is device/system/rootdir/init.rc. We can take a loot at the file format(device/system/init/readme.txt is a good overall introduction of the script). Basically the script file contains actions and services.

 

Actions

-------

Actions are named sequences of commands. Actions have a trigger which is used to determine when the action should occur.  When an event occurs which matches an action's trigger, that action is added to the tail of a to-be-executed queue (unless it is already on the queue).

Each action in the queue is dequeued in sequence and each command in that action is executed in sequence.  Init handles other activities (device creation/destruction, property setting, process restarting) "between" the execution of the commands in activities.

Actions take the form of:

on <trigger>

   <command>

   <command>

   <command>

...

 

Services

--------

Services are programs which init launches and (optionally) restarts when they exit.  Services take the form of:

service <name> <pathname> [ <argument> ]*

   <option>

   <option>

   ...

 

Options

-------

Options are modifiers to services.  They affect how and when init runs the service.

 

Triggers

--------

Triggers are strings which can be used to match certain kinds of events and used to cause an action to occur.

 

The builtin supported commands are defined in device/system/init/keywords.h. Commands are implementd in device/system/init/bultins.c.

 

The init program only executes five kinds of triggers: “early-init? “init? “early-boot? “boot? “property:*? Take a look at the following line in default init.rc.

class_start default

This line is a command for the action corresponding to “boot?trigger. It will start all services whose class name equals to “default? By default, if no class option is defined for a service, the service’s class name is “default? So this line will start all the services in the order of position in the file by default. (BTW, you can start any service using start commands, if you like.) Any service is run as a forked process of init, take a look at the source code of service_start in device/system/init.c.

 

So according to the default init.rc, the following services will be executed step by step:

console: star a shell. The source is in device/system/bin/ash.

adbd: start adb daemon. The source is in device/tools/adbd. By default is disabled.

servicemanager: start binder system. The source is in device/commands/binder.

mountd: mount all fs defined in /system/etc/mountd.conf if started, receive commands through local socket to mount any fs. The source is in device/system/bin/mountd.

debuggerd: start debug system. The source is in device/system/bin/debuggerd.

rild: start radio interface layer daemon. The source is in device/commands/rind.

zygote: start Android Java Runtime and start system server. It’s the most important service. The source is in device/servers/app.

media: start AudioFlinger, MediaPlayerService and CameraService. The source is in device/commands/mediaserver.

bootsound: play the default boot sound /system/media/audio/ui/boot.mp3. The source is in device/commands/playmp3.

dbus: start dbus daemon, it’s only used by BlueZ. The source is in device/system/Bluetooth/dbus-daemon.

hcid: redirect hcid’s stdout and stderr to the Android logging system. The source is in device/system/bin/logwrapper. By default is disabled.

hfag: start Bluetooth handsfree audio gateway, it’s only used by BlueZ. The source is in device/system/Bluetooth/bluez-utils. By default is disabled.

hsag: start Bluetooth headset audio gateway, it’s only used by BlueZ. The source is in device/system/Bluetooth/bluez-utils. By default is disabled.

installd: start install package daemon. The source is in device/servers/installd.

flash_recovery: load /system/recovery.img. The source is in device/commands/recovery/mtdutils.

 

Zygote service does the following tasks step by step:

1.       Create JAVA VM.

2.       Register android native function for JAVA VM.

3.       Call the main function in the JAVA class named com.android.internal.os.ZygoteInit whose source is device/java/android/com/android/internal/os/ZygoteInit.java.

a)         Load ZygoteInit class

b)        Register zygote socket

c)        Load preload classes(the default file is device/java/android/preloaded-classes)

d)        Load preload resources

e)         Call Zygote::forkSystemServer (implemented in device/dalvik/vm/InternalNative.c) to fork a new process. In the new process, call the main function in the JAVA class named com.android.server.SystemServer, whose source is in device/java/services/com/android/server.

                         i.              Load libandroid_servers.so

                       ii.              Call JNI native init1 function implemented in device/libs/android_servers/com_android_server_SystemServers. It only calls system_init implemented in device/servers/system/library/system_init.cpp.

l         If running on simulator, instantiate AudioFlinger, MediaPlayerService and CameraService here.

l         Call init2 function in JAVA class named com.android.server.SystemServer, whose source is in device/java/services/com/android/server. This function is very critical for Android because it start all of Android JAVA services.

l         If not running on simulator, call IPCThreadState::self()->joinThreadPool() to enter into service dispatcher.

 

SystemServer::init2 will start a new thread to start all JAVA services as follows:

Core Services:

1.       Starting Power Manager

2.       Creating Activity Manager

3.       Starting Telephony Registry

4.       Starting Package Manager

5.       Set Activity Manager Service as System Process

6.       Starting Context Manager

7.       Starting System Context Providers

8.       Starting Battery Service

9.       Starting Alarm Manager

10.   Starting Sensor Service

11.   Starting Window Manager

12.   Starting Bluetooth Service

13.   Starting Mount Service

Other services

1.       Starting Status Bar Service

2.       Starting Hardware Service

3.       Starting NetStat Service

4.       Starting Connectivity Service

5.       Starting Notification Manager

6.       Starting DeviceStorageMonitor Service

7.       Starting Location Manager

8.       Starting Search Service

9.       Starting Clipboard Service

10.   Starting Checkin Service

11.   Starting Wallpaper Service

12.   Starting Audio Service

13.   Starting HeadsetObserver

14.   Starting AdbSettingsObserver

Finally SystemServer::init2 will call ActivityManagerService.systemReady to launch the first activity by senting Intent.CATEGORY_HOME intent.

 

There is another way to start system server, which is through a program named system_server whose source is device/servers/system/system_main.cpp. It also calls system_init to start system services. So there is a question: why does Android have two methods to start system services? My guess is that directly start system_server may have synchronous problem with zygote because system_server will call JNI to start SystemServer::init2, while at that time zygote may not start JAVA VM yet. So Android uses another method. After zynote is initialized, fork a new process to start system services.


calvin 2011-09-07 10:53 发表评论
]]>
Compile CyanogenMod (Linux) for HTC Desirehttp://www.tkk7.com/lihao336/archive/2011/09/06/358137.htmlcalvincalvinTue, 06 Sep 2011 10:12:00 GMThttp://www.tkk7.com/lihao336/archive/2011/09/06/358137.htmlhttp://www.tkk7.com/lihao336/comments/358137.htmlhttp://www.tkk7.com/lihao336/archive/2011/09/06/358137.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/358137.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/358137.html参照guideQ?br />http://wiki.cyanogenmod.com/wiki/HTC_Desire_(GSM):_Compile_CyanogenMod_(Linux)

出现如下问题Q?br />
1.repo init时报错:
......
object 30d452905f166b316152f236422f85c8aa75a2d0
type commit
tag v1.7.5
tagger Shawn O. Pearce <sop@google.com> 1307663540 -0700

repo 1.7.5

gpg: Signature made Fri 10 Jun 2011 07:52:20 AM CST using DSA key ID 920F5C65
gpg: Can't check signature: public key not found
error: could not verify the tag 'v1.7.5'

出错原因是曾使用repo sync从其它库syncq代码,删掉~/.repoconfig卛_Q?br />$ rm -rf ~/.repoconfig
$ ./repo init -u git://github.com/CyanogenMod/android.git -b gingerbread
gpg: keyring `/home/calvin/.repoconfig/gnupg/secring.gpg' created
gpg: keyring `/home/calvin/.repoconfig/gnupg/pubring.gpg' created
gpg: /home/calvin/.repoconfig/gnupg/trustdb.gpg: trustdb created
gpg: key 920F5C65: public key "Repo Maintainer <repo@android.kernel.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Getting repo ...
   from http://android.git.kernel.org/tools/repo.git
。。。?br />

2.repo sync时报错:
。。。。?br />Fetching projects:   1% (3/285) 
Initializing project platform/bootable/bootloader/legacy ...
android.git.kernel.org[0: 130.239.17.13]: errno=Connection refused
android.git.kernel.org[0: 149.20.4.77]: errno=Connection timed out
android.git.kernel.org[0: 199.6.1.173]: errno=Connection refused
android.git.kernel.org[0: 2001:4f8:8:10:1972:112:1:0]: errno=Network is unreachable
android.git.kernel.org[0: 2001:500:60:10:1972:112:1:0]: errno=Network is unreachable
android.git.kernel.org[0: 2001:6b0:e:4017:1972:112:1:0]: errno=Network is unreachable
android.git.kernel.org[0: 2001:4f8:1:10:1972:112:1:0]: errno=Network is unreachable
fatal: unable to connect a socket (Network is unreachable)
error: Cannot fetch platform/bootable/bootloader/legacy

q接服务器时的问题,解决Q?br />修改.repo/manifest.xml?br />  <remote  name="korg"
           fetch="git://android.git.kernel.org/"
           review="review.source.android.com" />
?br />  <remote  name="korg"
           fetch="http://android.git.kernel.org/"
           review="review.source.android.com" />



calvin 2011-09-06 18:12 发表评论
]]>
android.uid.system没有dsdcard的权?/title><link>http://www.tkk7.com/lihao336/archive/2011/08/29/357497.html</link><dc:creator>calvin</dc:creator><author>calvin</author><pubDate>Mon, 29 Aug 2011 06:16:00 GMT</pubDate><guid>http://www.tkk7.com/lihao336/archive/2011/08/29/357497.html</guid><wfw:comment>http://www.tkk7.com/lihao336/comments/357497.html</wfw:comment><comments>http://www.tkk7.com/lihao336/archive/2011/08/29/357497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/lihao336/comments/commentRss/357497.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/lihao336/services/trackbacks/357497.html</trackback:ping><description><![CDATA[在AndroidManifest.xml中声?br />android:sharedUserId="android.uid.system"<br />后,该应用程序将没有权限dSD卡?br /><br />Processes that continue holding open fds on the sdcard a little after it is <br />requested to be unmounted will be killed so that it can unmount. <br /><br />We don't want the system process to  be able to access the sdcard to avoid <br />these kinds of issues (and just general security cleanliness), so that it <br />does not have permission to access it. <br /><br /><a >http://groups.google.com/group/android-porting/browse_thread/thread/c6af65d7ddd5eff3</a><br /><a >http://stackoverflow.com/questions/5617797/android-shared-user-id-and-reading-writing-a-file</a><br /><a >http://stackoverflow.com/questions/6679011/it-cant-access-the-sdcard-after-setting-android-uid-system-in-my-application</a><br /><a >http://www.eoeandroid.com/forum.php?mod=viewthread&tid=63314&page=1#pid636737</a><br /><img src ="http://www.tkk7.com/lihao336/aggbug/357497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/lihao336/" target="_blank">calvin</a> 2011-08-29 14:16 <a href="http://www.tkk7.com/lihao336/archive/2011/08/29/357497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android monkey & jni相关http://www.tkk7.com/lihao336/archive/2011/05/27/351178.htmlcalvincalvinFri, 27 May 2011 07:08:00 GMThttp://www.tkk7.com/lihao336/archive/2011/05/27/351178.htmlhttp://www.tkk7.com/lihao336/comments/351178.htmlhttp://www.tkk7.com/lihao336/archive/2011/05/27/351178.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/351178.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/351178.htmlApp层:
Force close crash
ANR crash
Native层:
Tombstone crash
Kernel层:
Kernel panic
比较隑֮位,可以查看/proc/last_kmsg来辅助定位?br />
最q需要通过monkey工具试Tombstonecd的crashQ抓取logq分析。通过monkey试Q如果要抓取nativecd的crashQ需要加?-monitor-native-crash参数Q?br />
seed=$(date +%Y%m%d%H%m%S)
monkey -s $seed --pkg-whitelist-file ${your-package-list} --monitor-native-crashes --kill-process-after-error -v -v -v 2000000000

q样Qmonkey在跑出crash后,?data/system/dropbox ?/data/tombstones目录下会生成相关日志Qmoneky会停止发送事件流q出测?值得注意的是Q?data/tombstones文g夹下只会保存10个日志,过10个后Q最早创建的会被替换。而monkey是通过监视q个文g夹下的文件数量变化来判断是否有tombtonecd的crash产生的。因此,?data/tombstones文g夹下过10个文件后Q如果再有tombstone crash产生的话Qmonkey是不能检到的,它会l箋发送事件流。ؓ了避免这个问题,可以在每ơ运行monkey之前先清IZ下这个文件夹?br />
另外Q在settings.db中的secure表中有三个字D:dropbox:data_app_wtf,dropbox:data_app_anr,dropbox:data_app_crash。如果设|ؓenabledQ每当有app crash之后Q在/data/system/dropboxq个文g夹下都会产生相关的日志信息,q对于分析调试问题都是第一手的信息?br />
如何刉tombstonecd的crashQ?br />q需要通过jni调用一个native的so文gQ在本地代码中抛出异常即可?br />可以~写如下代码tombstone_gen.cpp:
int main(int argc, char **argv) {
  int *p=0;
  *p=1;    //will seg fault
  return 0;
}
参照development/samples/SimpleJNI的示例,q行build出的apk卛_?br />
关于jni调用Q也有几个问题:
1.FindClass,RegisterNatives{找不到Q?br />target thumb C: libtombstonec <= development/samples/AndroidDemos/jni/tombstone_gen.c
development/samples/AndroidDemos/jni/tombstone_gen.c: In function 'registerNativeMethods':
development/samples/AndroidDemos/jni/tombstone_gen.c:48: error: request for member 'FindClass' in something not a structure or union
development/samples/AndroidDemos/jni/tombstone_gen.c:53: error: request for member 'RegisterNatives' in something not a structure or union
development/samples/AndroidDemos/jni/tombstone_gen.c: In function 'JNI_OnLoad':
development/samples/AndroidDemos/jni/tombstone_gen.c:97: error: request for member 'GetEnv' in something not a structure or union
make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libtombstonec_intermediates/tombstone_gen.o] Error 1

问题原因在于Q?br />如果是CE序Q要?(*env)->
如果是C++要用 env->
因此有两U解x法:
1、将 (*env)-> 改ؓ env->
2、将c文g改ؓcpp文gQ改为c++的方式编译?br />
2、运行时异常java.lang.UnsatisfiedLinkError
tombstone_gen.cpp?br />static const char *classPathName = "com/android/demo/AndroidDemos";
cd有误Q导致类链接错误?br />
最后,关于jni中JNINativeMethod相关解释Q?br />http://hi.baidu.com/zhlg_hzh/blog/item/f0d782081f2f45d963d986f5.html



calvin 2011-05-27 15:08 发表评论
]]>
在android工程中导入layoutlib.jar使用internal apihttp://www.tkk7.com/lihao336/archive/2011/04/28/349172.htmlcalvincalvinThu, 28 Apr 2011 03:39:00 GMThttp://www.tkk7.com/lihao336/archive/2011/04/28/349172.htmlhttp://www.tkk7.com/lihao336/comments/349172.htmlhttp://www.tkk7.com/lihao336/archive/2011/04/28/349172.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/349172.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/349172.html 导入Ҏ(gu)Q?br /> 1. Right-click the project in Eclipse and select "Build Path -> Add Libraries...".
2. Select User Library from the list and click Next.
3. Click the "User Libraries..." button.
4. Click "New..." in the User Libraries dialog.
5. Give the user library a name and select the System library checkbox and click OK.
6. Highlight the newly added user library in the list and click the "Add JARs..." button and add the desired jar files.
7. Click OK on the User Libraries dialog.
8. Make sure the new user library is checked in the Add Library dialog and

不以q种方式d会出现DEX errorQ切?br />


calvin 2011-04-28 11:39 发表评论
]]>
Eclipse 导入gingerbread源代码build path错误http://www.tkk7.com/lihao336/archive/2011/04/21/348715.htmlcalvincalvinThu, 21 Apr 2011 08:29:00 GMThttp://www.tkk7.com/lihao336/archive/2011/04/21/348715.htmlhttp://www.tkk7.com/lihao336/comments/348715.htmlhttp://www.tkk7.com/lihao336/archive/2011/04/21/348715.html#Feedback1http://www.tkk7.com/lihao336/comments/commentRss/348715.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/348715.html 在eclipse中导入gingerbread源代码后出现如下build path错误Q?br />
Project 'gingerbread' is missing required library: 'out/target/common/obj/JAVA_LIBRARIES/google-common_intermediates/javalib.jar'
Project 'gingerbread' is missing required library: 'out/target/common/obj/JAVA_LIBRARIES/gsf-client_intermediates/javalib.jar'

解决Q?br /> 删除.classpath中的q两行\?br /> <classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/google-common_intermediates/javalib.jar"/>
<classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/gsf-client_intermediates/javalib.jar"/>
d
<classpathentry kind="lib" path="out/target/common/obj/JAVA_LIBRARIES/android-common_intermediates/javalib.jar"/>


或?br /> https://groups.google.com/group/android-platform/browse_thread/thread/5c86d1f1929eed3c?pli=1
http://topic.csdn.net/u/20110406/19/5cc32204-b45e-4427-a3ea-eacd83fede13.html



calvin 2011-04-21 16:29 发表评论
]]>
使用git下蝲android源码http://www.tkk7.com/lihao336/archive/2011/03/03/345551.htmlcalvincalvinWed, 02 Mar 2011 17:39:00 GMThttp://www.tkk7.com/lihao336/archive/2011/03/03/345551.htmlhttp://www.tkk7.com/lihao336/comments/345551.htmlhttp://www.tkk7.com/lihao336/archive/2011/03/03/345551.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/345551.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/345551.html

1、Git的安?/strong> 
  
sudo apt-get install git-core 

2、安装Repo 
2.1首先保在当前用L(fng)ȝ录下创徏一个~/bin目录Q如果没有的话)Q?/p>

2.2然后把它(~/bin)加到PATH环境变量?

echo “export PATH=$PATH:~/bin” > ~/.bashrc

source ~/.bashrc
2.3下蝲repo

打开http://android.git.kernel.org/repoQ把该网保存ؓ ~/bin/repo

lrepo可执行权?br style="line-height: 22px;" /> chmod a+x ~/bin/repo

3Q设|git代理参考,见我的一文?/strong>

http://blog.chinaunix.net/u3/93670/showart_2084139.html

4、初始化版本?/strong>

4.1修改repo内容

?#8220;git:”Ҏ(gu)“http:” 

4.2新徏~/android目录Q进M后用repo init命o卛_。只初始?.0版(eclairQ?/p>

repo init -u http: //android.git.kernel.org/platform/manifest.git -b eclair

最后会看到 repo initialized in /androidq样的提C,p明本地的版本库已l初始化完毕Qƈ且包含了当前最新的sourcecode?/p>

通常情况下会出现error提示Q如果是以前没有创徏qrepo账户的话Q,q个不要紧,忽略掉它好了?br style="line-height: 22px;" />
配置repo账户
git config --global user.email "[email=xxxxx@xxxxxxx]xxxxx@xxxxxxx[/email]"
git config --global user.name "xxxxxx"

5、同步版本库 
5.1修改.repo/manifest.xml

  ?#8220;git:”Ҏ(gu)“http:”

5.2同步Q其实是正式下蝲Q前面init只是下蝲了具体的路径和依赖文Ӟ

repo sync


另一U情冉| Q?span style="line-height: 21px; font-weight: bold;">只下载某一个项?/span> ?/p>

我们只需要某一个project的代码,比如kernel/commonQ就不需要repo了,直接用Git卛_?br style="line-height: 22px;" /> git clone git://android.git.kernel.org/kernel/common.git 
q也需要不的旉Q因为它会把整个Linux Kernel的代码复制下来?/p>

如果需要某个branch的代码,用git checkout卛_。比如我们刚刚拿了kernel/common.get的代码,那就先进入到common目录Q然后用下面的命令:
git checkout origin/android-goldfish-2.6.27 -b goldfish 
q样我们在本地建立了一个名为goldfish的android-goldfish-2.6.27分支Q代码则已经与android-goldgish-2.6.27同步。我们可以通过git branch来列出本地的所有分支?/p>



calvin 2011-03-03 01:39 发表评论
]]>
SurfaceView与Viewhttp://www.tkk7.com/lihao336/archive/2010/12/08/340050.htmlcalvincalvinWed, 08 Dec 2010 03:20:00 GMThttp://www.tkk7.com/lihao336/archive/2010/12/08/340050.htmlhttp://www.tkk7.com/lihao336/comments/340050.htmlhttp://www.tkk7.com/lihao336/archive/2010/12/08/340050.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/340050.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/340050.html 如果你的游戏不吃CPUQ用View比较好Q符合标准Android操作方式Q由pȝ军_hsurface的时机?br /> 但如果很不幸的,你做不到不让你的E序吃CPUQ你只好用SurfaceView来强制刷新surface了,不然pȝ的UIq程很可能抢不过你那些吃CPU的线E?br />
当然其实不止q两U方法来hSurface的,q两U只是纯java应用比较常见的方法?br />


SurfaceView和View最本质的区别在于,surfaceView是在一个新L(fng)单独U程中可以重新绘制画面而View必须在UI的主U程中更新画面?br /> 那么在UI的主U程中更新画?可能会引发问题,比如你更新画面的旉q长Q那么你的主UIU程会被你正在画的函数阻塞。那么将无法响应按键Q触屏等消息?br />
当用surfaceView ׃是在新的U程中更新画面所以不会阻塞你的UIȝE。但q也带来了另外一个问题,是事g同步。比如你触屏了一下,你需要surfaceView中thread处理Q一般就需要有一个event queue的设计来保存touch eventQ这会稍E复杂一点,因ؓ涉及到线E同步?br />
所以基于以上,Ҏ(gu)游戏特点Q一般分成两cR?br />
1 被动更新画面的。比如棋c,q种用view好了。因为画面的更新是依赖于 onTouch 来更斎ͼ可以直接使用 invalidate?因ؓq种情况下,q一ơTouch和下一ơ的Touch需要的旉比较长些Q不会生媄响?br />
2 d更新。比如一个h在一直跑动。这需要一个单独的thread不停的重lh的状态,避免dmain UI thread。所以显然view不合适,需要surfaceView来控制?br />

calvin 2010-12-08 11:20 发表评论
]]>
android bluetoothhttp://www.tkk7.com/lihao336/archive/2010/12/06/339897.htmlcalvincalvinMon, 06 Dec 2010 06:48:00 GMThttp://www.tkk7.com/lihao336/archive/2010/12/06/339897.htmlhttp://www.tkk7.com/lihao336/comments/339897.htmlhttp://www.tkk7.com/lihao336/archive/2010/12/06/339897.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/339897.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/339897.htmlhttp://blog.csdn.net/dyufei/archive/2010/08/16/5815719.aspx

http://blog.csdn.net/dyufei/archive/2010/08/27/5844353.aspx

http://www.tkk7.com/Files/lihao336/android/android-Bluetooth.pdf


calvin 2010-12-06 14:48 发表评论
]]>
Talking about Android processhttp://www.tkk7.com/lihao336/archive/2010/11/29/339327.htmlcalvincalvinMon, 29 Nov 2010 08:14:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/29/339327.htmlhttp://www.tkk7.com/lihao336/comments/339327.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/29/339327.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/339327.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/339327.html

[First written by Steve Guo, please keep the mark if forwarding.]

In this topic you will learn some information about Android process management. First let’s take a look at the launched processes during Android booting.

USER PID PPID VSIZE RSS WCHAN PC NAME

root 1 0 264 176 c00acc6c 0000c36c S /init

root 28 1 724 308 c0051354 afe0c4cc S /system/bin/sh

system 30 1 796 248 c026516c afe0b74c S /system/bin/servicemanager

root 31 1 1824 316 ffffffff afe0b50c S /system/bin/mountd

root 32 1 652 248 c02976e0 afe0c0bc S /system/bin/debuggerd

radio 33 1 5344 664 ffffffff afe0bdbc S /system/bin/rild

root 34 1 71028 18828 c00ad308 afe0b874 S zygote

media 37 1 16812 3456 ffffffff afe0b74c S /system/bin/mediaserver

root 39 1 788 288 c02f9ae4 afe0b50c S /system/bin/installd

system 86 34 187756 21836 ffffffff afe0b74c S system_server

radio 118 34 103476 13896 ffffffff afe0c824 S com.android.phone

app_4 124 34 117848 19248 ffffffff afe0c824 S android.process.acore

app_5 139 34 98672 11516 ffffffff afe0c824 S com.android.mms

app_3 151 34 92096 10976 ffffffff afe0c824 S com.android.alarmclock

app_6 161 34 94436 12616 ffffffff afe0c824 S com.android.calendar

app_9 173 34 93248 11728 ffffffff afe0c824 S android.process.media

app_15 182 34 91848 9764 ffffffff afe0c824 S com.android.voicedialer

app_16 190 34 94524 10812 ffffffff afe0c824 S android.process.im

They can be divided into three kinds.

Root Process

init is the first process after kernel booting. The major task it performs:

l Parser and execute init.rc and init.%hardware%.rc

l Automatically generate device node under /dev

l Start log and property service

l Monitor for device, property set and child process exit events

Native Application Process

According to init.rc, init will fork the following native application process.

console: star a shell.

servicemanager: start binder IPC service manager.

mountd: mount all fs defined in /system/etc/mountd.conf if started, receive commands through local socket to mount any fs.

debuggerd: start debug system.

rild: start radio interface layer daemon.

zygote: start Android Java VM Runtime and start system server. It’s the most important process.

mediaserver: start AudioFlinger, MediaPlayerService and CameraService.

installd: start install package daemon.

JAVA Application Process

Every JAVA application process is forked from zygote process. system_server is a special JAVA process, which is directly forked from zygote.. Other JAVA process is created from ActivityManagerService(run in system_server process) like this.

int pid = Process.start("android.app.ActivityThread",

mSimpleProcessManagement ? app.processName : null, uid, uid,

gids, ((app.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0), null);

While Process.java use UNIX domain socket to communicate with zygote. So the overall picture is shown as following.

clip_image002

System Server

It’s the first JAVA application launched by zygote. It starts the core Android services, e.g. ActivityManager, WindowManager, PackageManager etc. It’s the Android core engine.

Persistent Application

During booting, ActivityManagerService.systemReady will start all persistent applications.

List apps = ActivityThread.getPackageManager().

getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);

if (apps != null) {

int N = apps.size();

int i;

for (i=0; i<N; i++) {

ApplicationInfo info

= (ApplicationInfo)apps.get(i);

if (info != null &&

!info.packageName.equals("android")) {

addAppLocked(info);

}

}

}

Currently only Phone application is registered as a persistent app in AndroidManifest.xml like this.

<application android:name="PhoneApp"

android:persistent="true"

android:label="@string/dialerIconLabel"

android:icon="@drawable/ic_launcher_phone">

So during booting, only phone application is automatically launched. It’s the “com.android.phone” process.

The First Activity

The first activity is launched by senting Intent.CATEGORY_HOME intent from ActivityManagerService.

Intent intent = new Intent(

mTopAction,

mTopData != null ? Uri.parse(mTopData) : null);

intent.setComponent(mTopComponent);

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

intent.addCategory(Intent.CATEGORY_HOME);

}

ActivityInfo aInfo =

intent.resolveActivityInfo(mContext.getPackageManager(),

PackageManager.GET_SHARED_LIBRARY_FILES);

if (aInfo != null) {

intent.setComponent(new ComponentName(

aInfo.applicationInfo.packageName, aInfo.name));

// Don't do this if the home app is currently being

// instrumented.

ProcessRecord app = getProcessRecordLocked(aInfo.processName,

aInfo.applicationInfo.uid);

if (app == null || app.instrumentationClass == null) {

intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);

startActivityLocked(null, intent, null, null, 0, aInfo,

null, null, 0, 0, 0, false);

}

}

It’s the “android.process.acore” process. (The process name is defined in AndroidManifest.xml)

Auto-launched Application After Booting

When activity idle is detected in ActivityManagerService, it will broadcast ACTION_BOOT_COMPLETED intent at the first time.

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

// Tell anyone interested that we are done booting!

synchronized (this) {

broadcastIntentLocked(null, null,

new Intent(Intent.ACTION_BOOT_COMPLETED, null),

null, null, 0, null, null,

android.Manifest.permission.RECEIVE_BOOT_COMPLETED,

false, false, MY_PID, Process.SYSTEM_UID);

}

}

Currently, MMS, AlarmClock, Calendar, MediaProvider, VoiceDialer and IM have registered as a receiver for ACTION_BOOT_COMPLETED intent in their AndroidManifest.xml. So they will be automatically launched. (This explains the remained JAVA process.)

Email also registers as a receiver for ACTION_BOOT_COMPLETED intent in its AndroidManifest.xml, but it defines android:enable=”false”. So it won’t be launched.

<receiver android:name=".service.BootReceiver"

android:enabled="false"

>

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.DEVICE_STORAGE_OK" />

</intent-filter>

</receiver>

DownloadProvider also registers as a receiver for ACTION_BOOT_COMPLETED intent in its AndroidManifest.xml, but it defines android:exported=”false”. So it won’t be launched.

<receiver android:name=".DownloadReceiver" android:exported="false">

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

</intent-filter>

</receiver>

Behind the JAVA process

system_server is a special case. It calls ActivityThread.java’s systemMain static function, which creates an instance of ActivityThread. ActivityThread then creates an instance of ApplicationThread, Application and ApplicationContext.

Every other JAVA process works in a different way. It’s controlled by system_server while forked by zygote. When any JAVA process other than system_server is forked from zygote, it automatically calls ActivityThread.java’s main static function(See Process.java and the following code snippet).

try {

ZygoteInit.invokeStaticMain(cloader, className, mainArgs);

} catch (RuntimeException ex) {

logAndPrintError (newStderr, "Error starting. ", ex);

}

The ActivityThread.java’s main function creates an instance of ActivityThread. ActivityThread then creates an instance of ApplicationThread. The ApplicationThread will work as an IBinder object to interact with ActivityManagerService in system_server. The new process does nothting at this time other than waiting IPC call from system_server. The Application and ApplicationContext object won’t be created at this time. Actually it’s deferred to when the process really works, eg. start an activity, receive intent or start a service.

For example, when start an activity, ActivityManagerService know which process the to-be-launched activity should run in, so it will RPC call ApplicationThread’s scheduleLaunchActivity to launch a new activity in that process. ApplicationThread then post a message to let ActivityThread know it needs to start an activity. ActivityThread then creates Application and ApplicationContext object. After that, it calls Instrumentation, then Instrumentation finally calls JAVA dalvik VM to really create an activity JAVA object.

 原文地址 http://letsgoustc.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=cat%3DGoogle%2









calvin 2010-11-29 16:14 发表评论
]]>
handler与多U程消息处理http://www.tkk7.com/lihao336/archive/2010/11/29/339316.htmlcalvincalvinMon, 29 Nov 2010 06:55:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/29/339316.htmlhttp://www.tkk7.com/lihao336/comments/339316.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/29/339316.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/339316.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/339316.html
在Android下面也有多线E的概念Q在C/C++中,子线E可以是一个函敎ͼ一般都是一个带有@环的函数Q来处理某些数据Q优先线E只是一个复杂的q算q程Q所以可能不需要while循环Q运完成,函数l束Q线E就销毁。对于那些需要控制的U程Q一般我们都是和互斥锁相互关联,从而来控制U程 的进度,一般我们创建子U程Q一U线E是很常见的Q那是带有消息循环的线E?br />
消息循环是一个很有用的线E方式,曄自己用C在Linux下面实现一个消息@环的机制Q往消息队列里添加数据,然后异步的等待消息的q回。当消息队列为空的时候就会挂L(fng)E,{待新的消息的加入。这是一个很通用的机制?br />
在AndroidQ这里的U程分ؓ有消息@环的U程和没有消息@环的U程Q有消息循环的线E一般都会有一个LooperQ这个是android的新概念。我们的ȝE(UIU程Q就是一个消息@环的U程。针对这U消息@环的机制Q我们引入一个新的机制HandlerQ我们有消息循环Q就要往消息循环里面发送相应的消息Q自定义消息一般都会有自己对应的处理,消息的发送和清除Q消息的的处理,把这些都装在Handle里面Q注意Handle只是针对?些有Looper的线E,不管是UIU程q是子线E,只要你有LooperQ我可以往你的消息队列里面d东西Qƈ做相应的处理?br />
但是q里q有一点,是只要是关于UI相关的东西,׃能放在子U程中,因ؓ子线E是不能操作UI的,只能q行数据、系l等其他非UI的操作?br />
那么什么情况下面我们的子线E才能看做是一个有Looper的线E呢Q?strong>我们如何得到它Looper的句柄呢Q?/strong>

Looper.myLooper();获得当前的Looper

Looper.getMainLooper () 获得UIU程的Lopper

我们看看Handle的初始化函数Q如果没有参敎ͼ那么他就默认使用的是当前的LooperQ如果有Looper参数Q就是用对应的线E的Looper?br />
如果一个线E中调用Looper.prepare()Q那么系l就会自动的U程建立一个消息队列,然后调用 Looper.loop();之后p入了消息循环Q这个之后就可以发消息、取消息、和处理消息。这个如何发送消息和如何处理消息可以在其他的U程中通过 Handle来做Q但前提是我们的Handle知道q个子线E的LooperQ但是你如果不是在子U程q行 Looper.myLooper()Q一般是得不到子U程的looper的?br />
public void run() {
            synchronized (mLock) {
                Looper.prepare();
               //do something
            }
            Looper.loop();
        }

所以很多h都是q样做的Q我直接在子U程中新建handleQ然后在子线E中发送消息,q样的话失M我们多线E的意义了?br />
 1 class myThread extends Thread{
 2 
 3              private EHandler mHandler ;
 4 
 5              public void run() {
 6 
 7                  Looper myLooper, mainLooper;
 8 
 9                  myLooper = Looper.myLooper ();
10 
11                 mainLooper = Looper.getMainLooper ();
12 
13                 String obj;
14 
15                 if (myLooper == null ){
16 
17                          mHandler = new EHandler(mainLooper);
18 
19                          obj = "current thread has no looper!" ;
20 
21                 }
22 
23                 else {
24 
25                      mHandler = new EHandler(myLooper);
26 
27                      obj = "This is from current thread." ;
28 
29                 }
30 
31                 mHandler .removeMessages(0);
32 
33                 Message m = mHandler .obtainMessage(111, obj);
34 
35                 mHandler .sendMessage(m);
36 
37              }
38 
39   }

可以让其他的U程来控制我们的handleQ可以把 private EHandler mHandler ;攑֜外面Q这h们的发消息和处理消息都可以在外面来定义,q样增加E序代码的美观,l构更加清晰?br />
对如M的HandleQ里面必要重蝲一个函?br />
public void handleMessage(Message msg)

q个函数是我们的消息处理,如何处理Q这里完全取决于你,然后通过 obtainMessage?sendMessage{来生成和发送消息, removeMessages(0)来清除消息队列。Google真是太智慧了Q这U框架的产生Q我们写代码更加L了?br />
有的时候,我们的子U程惛_改变UI了,q个时候千万不要再子线E中M改,获得UIU程的LooperQ然后发送消息即可?br />
我们来看看高焕堂的代码:

// class ac01 extends Activity {

          // ………

              public void onClick(View v) {

                     switch (v.getId()){

                     case 101:

                                  t = new myThread();

                            t .start();

                          break ;

                     case 102:

                  finish();

                                break ;

                     }

           }

//------------------------------------------------------            

class EHandler extends Handler {

                   public EHandler(Looper looper) {

                       super (looper);

                   }

                   @Override

                   public void handleMessage(Message msg) {

                      tv .setText((String)msg. obj );

               }

           }

//------------------------------------------------------            

class myThread extends Thread{

             private EHandler mHandler ;

             public void run() {

                Looper myLooper, mainLooper;

                myLooper = Looper.myLooper ();

                mainLooper = Looper.getMainLooper ();

                String obj;

                if (myLooper == null ){

                        mHandler = new EHandler(mainLooper);

                        obj = "current thread has no looper!" ;

                }

                else {

                     mHandler = new EHandler(myLooper);

                     obj = "This is from current thread." ;

                }

                mHandler .removeMessages(0);

                Message m = mHandler .obtainMessage(1, 1, 1, obj);

                mHandler .sendMessage(m);

             }

  }

}

完全是不知所云,一坨狗屎。我们来看,在上面的run里面

Looper myLooper, mainLooper;

myLooper = Looper.myLooper (); //很明显这个会q回I,因ؓ你还没有 prepareQ不会返回Looper?br />
mainLooper = Looper.getMainLooper ();

大家在看Looper的时候不要看高焕堂的书,感觉他也不是很懂Q倒还把我搞糊涂了。讲了那么多Q完全是他自q理解Q他自己的理解很是复杂,关键的是把简单的问题复杂化,q且复杂之后的东西还是错的。我们看看Goole Music App的源代码?br />
在MediaPlaybackActivity.java中,我们可以看一下再OnCreate中的有这L(fng)两句Q?br />
        mAlbumArtWorker = new Worker("album art worker");
        mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());

很明显这两句Q是构徏了一个子U程。ƈ且这个子U程q是Looper的子U程Q这里很牛逼的使用?mAlbumArtWorker.getLooper()q个函数Q因为我们知道,我们能够得到子线E的Looper的途径只有一个:是在子U程中调?Looper.myLooper ()Qƈ且这个函数还要在我们perpare之后调用才能得到正确的LooperQ但是他q里用了一个这L(fng)什么东?getLooperQ不知道它是如何实现的?

q里有一个大概的思\Q我们在子线E的的prepare之后调用 myLooper ()q个Ҏ(gu)Q然后保存在一个成员变量中Q这个getLooperp回这个东西,但是q里会碰到多U程的一个很H出的问题,同步。我们在父线E中调用 mAlbumArtWorker.getLooper()Q但是想要这个返回正的looper必要求我们的子线E运行了prepareQ但是这个东 西实在子U程q行的,我们如何保证呢?
 
我们看Google是如何实现的Q?br />
 
  private class Worker implements Runnable {
        
private final Object mLock = new Object();
        
private Looper mLooper;
       
        
/**
         * Creates a worker thread with the given name. The thread
         * then runs a {
@link android.os.Looper}.
         * 
@param name A name for the new thread

         
*/
        Worker(String name) {
            Thread t 
= new Thread(nullthis, name);
            t.setPriority(Thread.MIN_PRIORITY);
            t.start();
            
synchronized (mLock) {
                
while (mLooper == null) {
                    
try {
                        mLock.wait();
                    } 
catch (InterruptedException ex) {
                    }
                }
            }
        }
       
        
public Looper getLooper() {
            
return mLooper;
        }
       
        
public void run() {
            
synchronized (mLock) {
                Looper.prepare();
                mLooper 
= Looper.myLooper();
                mLock.notifyAll();
            }
            Looper.loop();
        }
       
        
public void quit() {
            mLooper.quit();
        }
    }

我们知道Q一个线E类的构造函数是在主U程中完成的Q所以在我们?Worker的构造函C我们创佳一个线E,然后让这个线E运行,q一q个U程的创建是指定一?RunnablQ这里就是我们的Worker本nQ在ȝE调?t.start();Q这后,我们子线E已l创建,q且开始执行work的runҎ(gu)。然后下面的代码很艺术:

synchronized (mLock) {
                while (mLooper == null) {
                    try {
                        mLock.wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }

我们开始等待我们的子线E给mLooper赋|如果不赋值我们就l箋{,然后我们的子U程在运行runҎ(gu)之后Q在l?mLooper赋g后,通知worker够着函数中的waitQ然后我们的构造函数才能完成,所以我们说Q?br />
mAlbumArtWorker = new Worker("album art worker");

q句本n是d的,它创Z一个子U程Q开启了子线E,q且{待子线E给mLooper赋|赋值完成之后,q个函数才返回,q样才能保证我们的子U程的Looper的获取绝Ҏ(gu)正确的,q个构思很有创意。值得借鉴?br />
PSQ?br /> 1、发送消息ƈ不会dU程Q而处理消息时会阻塞线E,q是因ؓHandler 处理完一?Message 对象才会接着d下面一个消息进行处理?br /> Handler对于Message的处理不是ƈ发的。一个Looper 只有处理完一条Message才会d下一条,所以消息的处理是阻塞Ş式的Q如果在handler里做耗时的操作,则调用者线E会d。但是如?strong>用不同的Looper则能辑ֈq发的目?/strong>。(http://windywindy.javaeye.com/blog/464185Q?br />
2、Android提供了一个HandlerThread来实现ƈ发处理message的目的,HandlerThread在实C与Music应用的Workercȝ伹{?br />
参考:


calvin 2010-11-29 14:55 发表评论
]]>
Android H口理http://www.tkk7.com/lihao336/archive/2010/11/24/338962.htmlcalvincalvinWed, 24 Nov 2010 10:28:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/24/338962.htmlhttp://www.tkk7.com/lihao336/comments/338962.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/24/338962.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/338962.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/338962.html 在整个控件树(wi)的最端Q是一个逻辑的树(wi)ӞViewParentQ在源码中的实现是ViewRootQViewRoot extends Handler implements ViewParentQ。它是整个控件树(wi)和W(xu)indowManager之间的事件信息的译者。WindowManager是Android中一个重要的服务。它?yu)用L(fng)操作Q翻译成为指令,发送给呈现在界面上的各个Window。Activity会将的控件注册到WindowManager中,当用L(fng)是触屏q或键盘的时候,W(xu)indowManager׃通知刎ͼ而当控g有一些请求生,也会l由ViewParent送回到WindowManager中。从而完成整个通信程?br />
事g分发程
用户在触发一个时间后产生一个消息,消息先被window manager采集刎ͼ然后分发lclient?br /> window manager通过IWindow分发lclientQ我们知道ViewRoot使用IWindowSession与server通讯Q用IWindow接收消息Q所以第一步消息到了ViewRootq里来了
也就是window manager->IWindow->ViewRoot
CViewRoot后它把消息{发给LooperQ楼d以看ViewRoot.java看它是怎么获取当前U程的Looper?
Looper->ViewRoot$RootHandler().dispatch()Q有转发会给ViewRootQ然后就通过decor view形成的树(wi)状结构依ơ分发下厅R?br />
window manager proxy中维护了view, ViewRoot, layout param三元l?br /> 每次调用window manager proxy的addView都会新增一个三元组。一般程序中都是调用addView(decor,...)Q也是只对decor view调用addView

*****************\
在Activity在performLaunchActivityӞ会用Activity.attachQ)建立一个PhoneWindowȝ口。这个主H口的徏立ƈ不是一个重炏VhandleResumeActivity真正要启动一个Activity时候,主H口加入到WindowManagerQ当然ƈ不是主H口本nQ而是主H口的DecorView加入到WindowManager中?br />
• performLaunchActivity@ActivityThread.java
attach()@Activity.javaSession.java
addWindow()@WindowManager

mWindow = PolicyManager.makeNewWindow(this); --实例化一个activity或者dialog或者widget的地Ҏ(gu)会make new window
• handleResumeActivity()@ActivityThread.java
addView()@WindowManagerImpl.java --dDecorView到WindowManager?br /> setView()@ViewRoot.java
add()@IwindowSession.java
| --q里通过AIDL调用
add()@WindowManagerService$Service.java

关于PhoneWindowQ?br /> 而PhoneWindow只是做了一个具体跟手机功能相关的公用事件的处理Q所以在Android中PhoneWindowq不是一个抽象的U正概念Q而是一个跟手机pȝ相关的一个特别窗口概念,例如按键的默认动作处理,按键音的发出{等?br />
一个View对应一个ViewRoot

问题Q?strong style="background-color: yellow">WindowMangerService如果通过AIDL事件派发到客户端的Q?/strong>

calvin 2010-11-24 18:28 发表评论
]]>
[原]Activity启动q程分析http://www.tkk7.com/lihao336/archive/2010/11/23/338802.htmlcalvincalvinTue, 23 Nov 2010 06:59:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/23/338802.htmlhttp://www.tkk7.com/lihao336/comments/338802.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/23/338802.html#Feedback1http://www.tkk7.com/lihao336/comments/commentRss/338802.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/338802.html **android.process.acoreq程
1.Acticity.startActivityForResult()
2.Instrumention.execStartActivity();
3.ActivityManagerNative.getDefault()
                .startActivity()
  3.1 ActivityManagerNative.getDefault()q回的是ActivityManagerProxy的实例,
  它只是一个代理类Q这个代理类实际上代理的是IBinder b = ServiceManager.getService("activity");
  q个Service?br />   3.2 q个Service是什么时候添加进来的呢?
  在SystemServer.java的run()中有调用
  ActivityManagerService.setSystemProcess();
      ServiceManager.addService("activity", m);
      q里q会d许多pȝ关键服务?br />       QTODOQ查看在SystemServer的Log输出Q?br />      
**system_processq程
4 ActivityManagerNative
    |--ActivityManagerService
   
    在ActivityManagerNative的onTransactҎ(gu)中最l提供了服务Q?br />     case START_ACTIVITY_TRANSACTIONQ?br />       ActivityManagerService.startActivityQ);
        --startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType,
            Uri[] grantedUriPermissions,
            int grantedMode, ActivityInfo aInfo, IBinder resultTo,
            String resultWho, int requestCode,
            int callingPid, int callingUid, boolean onlyIfNeeded,
            boolean componentSpecified)
          --startActivityUncheckedLocked(r, sourceRecord,
                grantedUriPermissions, grantedMode, onlyIfNeeded, true)
          在这个方法里面检查权限,解析intent中的Flag。。?br />           --startActivityLocked(HistoryRecord r, boolean newTask)
            --resumeTopActivityLocked(HistoryRecord prev)
              --startSpecificActivityLocked(HistoryRecord r,boolean andResume, boolean checkConfig)
                --startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName)
                  --startProcessLocked(ProcessRecord app,String hostingType, String hostingNameStr)
                    在这里启动一个进E用来hostq个应用
                    int pid = Process.start("android.app.ActivityThread",
                    mSimpleProcessManagement ? app.processName : null, uid, uid,
                    gids, debugFlags, null);
                   
ActivityManagerService.java
--startSpecificActivityLocked(HistoryRecord r,boolean andResume, boolean checkConfig)
  --realStartActivityLocked(HistoryRecord r,ProcessRecord app, boolean andResume, boolean checkConfig)
    --app.thread.scheduleLaunchActivity                                   //scheduleLaunchActivity()@IApplicationThread.java
      --scheduleLaunchActivity()@ActivityThread.java                      //q里实际是ApplicationThreadNative提供的服?br />         --handleMessage()@H$ActivityThread.java
          --handleLaunchActivity()@ActivityThread.java
            --Activity performLaunchActivity(ActivityRecord r, Intent customIntent)@ActivityThread.java  //q时真正的Activity对象被构造出?br />               --mInstrumentation.newActivityQ)                            //通过反射构造出Activity对象
              --activity.attachQ)                                         //初始化ActivityQ生成一个window对象Q设|各U状态等{?br />               --mInstrumentation.callActivityOnCreate(activity, r.state);  //调用Activity的onCreate()Ҏ(gu)
           
              到这里,我们自己写的activity的onCreate()Ҏ(gu)已经被系l调用了Q接下来依次回调生命周期Ҏ(gu)Q?br />               --activity.performStart();
                --mInstrumentation.callActivityOnStart(this);
              --mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
              --mInstrumentation.callActivityOnPostCreate(activity, r.state);
              --mActivities.put(r.token, r);                               //这个activity入栈
             
            然后p调用onResume()Ҏ(gu)了:
            --handleResumeActivity(IBinder token, boolean clearHide, boolean isForward)
              --performResumeActivity(token, clearHide);
                --r.activity.performResume();
                  --performRestart()@Activity.java;
                    --mInstrumentation.callActivityOnRestart(this);
                    --mInstrumentation.callActivityOnStart(this);
                --mInstrumentation.callActivityOnResume(this);
                onResume()已经调用完毕Q一个activity的逻辑处理l束了,但是q时候屏q上q不会显CZQ何东西,因ؓViewq没有添加进?br />                
               
              --r.window.getDecorView();                                   //开始把DecorViewdqWindow
              --wm.addView(decor, l);
           
            x一个Activity启动l束?br />

calvin 2010-11-23 14:59 发表评论
]]>
PDP context相关http://www.tkk7.com/lihao336/archive/2010/11/23/338799.htmlcalvincalvinTue, 23 Nov 2010 06:50:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/23/338799.htmlhttp://www.tkk7.com/lihao336/comments/338799.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/23/338799.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/338799.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/338799.html
GPRS-PDP上下文的Ȁz过E?(摘?

about PDP context


calvin 2010-11-23 14:50 发表评论
]]>
Apn切换后数据连接过E?/title><link>http://www.tkk7.com/lihao336/archive/2010/11/23/338789.html</link><dc:creator>calvin</dc:creator><author>calvin</author><pubDate>Tue, 23 Nov 2010 06:12:00 GMT</pubDate><guid>http://www.tkk7.com/lihao336/archive/2010/11/23/338789.html</guid><wfw:comment>http://www.tkk7.com/lihao336/comments/338789.html</wfw:comment><comments>http://www.tkk7.com/lihao336/archive/2010/11/23/338789.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/lihao336/comments/commentRss/338789.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/lihao336/services/trackbacks/338789.html</trackback:ping><description><![CDATA[<br /> GsmDataConnectionTracker在实例化Ӟ会注册一个观察者,监视apn数据库的变化?br /> p.getContext().getContentResolver().registerContentObserver(<br />                 Telephony.Carriers.CONTENT_URI, true, apnObserver);<br />                 <br /> 当改变apn后,Settings应用更新apn数据库,ApnChangeObserver的onChange被调用,发送EVENT_APN_CHANGED消息Q?br /> sendMessage(obtainMessage(EVENT_APN_CHANGED));<br /> <br /> 接着onApnChanged()@GsmDataConnectionTracker.java被调?br />       -trySetupData(Phone.REASON_APN_CHANGED)@GsmDataConnectionTracker.java<br />         --setupData(String reason)@GsmDataConnectionTracker.java<br />         <br />         private boolean setupData(String reason) {<br />         ApnSetting apn;<br />         GsmDataConnection pdp;<br /> <br />         apn = getNextApn();<br />         if (apn == null) return false;<br />         <br />         //获取一个状态ؓinactive的pdpq接对象<br />         pdp = findFreePdp();<br />         if (pdp == null) {<br />             if (DBG) log("setupData: No free GsmDataConnection found!");<br />             return false;<br />         }<br />         mActiveApn = apn;<br />         mActivePdp = pdp;<br /> <br />         Message msg = obtainMessage();<br />         msg.what = EVENT_DATA_SETUP_COMPLETE;<br />         msg.obj = reason;<br />         <br />         //开始激z这个pdp<br />         //在android2.0.1版本Ӟ有一个PdpConnection.java来进行连接,2.2时这个类被删掉了Qconnect的功能合q到GsmDataConnection里面<br />         pdp.connect(msg, apn);<br />         <br />         //讄q个pdpq接状态ؓINITING<br />         setState(State.INITING);<br />         if (DBG) log("setupData for reason: "+reason);<br />         <br />         //通知上层应用数据q接状态改?br />         phone.notifyDataConnection(reason);<br />         return true;<br />     }<br />     <br />     其中Q在q一层,数据q接׃个状态:<br />         IDLE,<br />         INITING,<br />         CONNECTING,<br />         SCANNING,<br />         CONNECTED,<br />         DISCONNECTING,<br />         FAILED<br />         <br />         对上层应用来_q七个状态划分ؓ四种状态(getDataConnectionState()@GSMPhone.javaQ:<br />         CONNECTED, CONNECTING, DISCONNECTED, SUSPENDED;<br />         分别对应TelephonyManager的四U连接状态?br />         <br />         开始激zPDPq接Ӟ讄状态ؓState.INITINGQ调用phone.notifyDataConnection(reason)发出通知Q后l调用过EؓQ?br />         notifyDataConnection(String reason)@PhoneBase.java<br />           --notifyDataConnection(Phone sender, String reason)@DefaultPhoneNotifier.java<br />             .<br />             .   <strong>q里需要经qIPC调用</strong><br />             .<br />             notifyDataConnection()@TelephonyRegistry.java<br />               --onDataConnectionStateChanged()<br />               <br /> 当连接成功后QonDataSetupCompleteQ)@GsmDataConnectionTracker.java被调?br /> 通过phone.notifyDataConnection(reason);回调应用层的onDataConnectionStateChanged()Ҏ(gu)?br /> <br /> ps:可以通过adb logcat -b radio查看ȀzL据连接时Qradio层的log输出?br /> <img src ="http://www.tkk7.com/lihao336/aggbug/338789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/lihao336/" target="_blank">calvin</a> 2010-11-23 14:12 <a href="http://www.tkk7.com/lihao336/archive/2010/11/23/338789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用onUserLeaveHint发送后台运行通知http://www.tkk7.com/lihao336/archive/2010/11/22/338677.htmlcalvincalvinMon, 22 Nov 2010 05:26:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/22/338677.htmlhttp://www.tkk7.com/lihao336/comments/338677.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/22/338677.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/338677.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/338677.html 用户按下Home键将E序|于后台q行或者应用启动其他activityQ比如系l浏览器Q短信等Q需要向pȝ发送通知Q用户做完别的操作后Q点击通知栏,回到应用?br />
问题一
在什么时机发送通知Q?br /> 用户按下Home的事件在应用层时捕捉不到的,因此只能从activity生命周期Ҏ(gu)着手?br />
Ҏ(gu)一Q?br /> pȝ所有activityl承一个BaseActivityQ在BaseActivity中维护一个当前可见的activity数组Q?br /> protected static ArrayList sVisibleActivities = new ArrayList();

在onResume中,当前activity保存Q同时清除所有通知Q?br /> protected void onResume()
{
if (!sVisibleActivities.contains(this))
{
sVisibleActivities.add(this);
}

// 清除pȝ消息
mNotificationManager.cancel(R.id.notify);
}

在onStop中,清除保存的当前activityQ?br /> protected void onStop()
{
if (sVisibleActivities.contains(this))
{
sVisibleActivities.remove(this);
}

// 如果当前没有可见的activityQ则发送系l通知
if (sVisibleActivities.isEmpty())
{
sendBackgroundNotify();
}

super.onStop();
}

q种方式在大多数情况下工作良好,可以辑ֈ需求,但是问题Ӟ当前台的activity被至于后台时QonStop()Ҏ(gu)不一定会被调用,因此通知有可能不会被发出Q?br />
Ҏ(gu)二:
几经周折Q发现activity有一个生命周期方法可以达到目的:

protected void onUserLeaveHint ()

Since: API Level 
3
Called as part of the activity lifecycle when an activity is about to go into the background as the result of user choice.
For example, when the user presses the Home key, onUserLeaveHint() will be called, but when an incoming phone call causes the in
-call Activity to be automatically brought to the foreground,
 onUserLeaveHint() will not be called on the activity being interrupted. In cases when it is invoked, 
this method is called right before the activity's onPause() callback.
This callback and onUserInteraction() are intended to help activities manage status bar notifications intelligently; specifically, for helping activities determine the proper time to cancel a notfication.

从文档来看,q个Ҏ(gu)g是Z按下Home键时q样的场景设计的?br /> q样Q在onUserLeaveHint里发出系l通知卛_?br /> 但是问题又来了,如果启动应用Q从一个activity依次调用startActivityQfinish关闭自己Q启动一个新的activityӞonUserLeaveHint也会被调?...

再次阅文档Q发现Intent中的一个FlagQ?br />
public static final int FLAG_ACTIVITY_NO_USER_ACTION

Since: API Level 
3
If set, 
this flag will prevent the normal onUserLeaveHint() callback from occurring on the current frontmost activity before it is paused as the newly-started activity is brought to the front.

Typically, an activity can rely on that callback to indicate that an explicit user action has caused their activity to be moved out of the foreground.
The callback marks an appropriate point in the activity
's lifecycle for it to dismiss any notifications that it intends to display "until the user has seen them," such as a blinking LED.
If an activity is ever started via any non-user-driven events such as phone-call receipt or an alarm handler, this flag should be passed to Context.startActivity, ensuring that the pausing activity does not think the user has acknowledged its notification.

q正是我惌的,q样Q在启动activityӞ往intent中加上这个flagQonUserLeaveHint׃会再被调用了Qhoory...


calvin 2010-11-22 13:26 发表评论
]]>
android1.6启动pppd的方?/title><link>http://www.tkk7.com/lihao336/archive/2010/11/19/338480.html</link><dc:creator>calvin</dc:creator><author>calvin</author><pubDate>Fri, 19 Nov 2010 07:25:00 GMT</pubDate><guid>http://www.tkk7.com/lihao336/archive/2010/11/19/338480.html</guid><wfw:comment>http://www.tkk7.com/lihao336/comments/338480.html</wfw:comment><comments>http://www.tkk7.com/lihao336/archive/2010/11/19/338480.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/lihao336/comments/commentRss/338480.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/lihao336/services/trackbacks/338480.html</trackback:ping><description><![CDATA[?.5中,有个PppLink.java文gQ封装了启动pppdq程的接口,但是?.6版本的时候这个文件被删除了,与之相关的代码也全删了,不知其解Q网上搜得解{如下:<br /> <br /> 因ؓ高通的Ҏ(gu)Q采用共享内存的Ҏ(gu)Q不需要pppd拨号了。googleq帮人就认ؓ不需要pppd了,也就把PppLink.java删除了。所?.6之后Q还需要pppd拨号的,需要把1.5拨号q块UL回来.<br /> <br /> 参见Q?br /> <a >http://topic.csdn.net/u/20091022/16/6e5b6a99-3af6-421a-b6f1-e0752e239077.html</a><br /> <br /> <img src ="http://www.tkk7.com/lihao336/aggbug/338480.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/lihao336/" target="_blank">calvin</a> 2010-11-19 15:25 <a href="http://www.tkk7.com/lihao336/archive/2010/11/19/338480.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Task和Activity相关http://www.tkk7.com/lihao336/archive/2010/11/19/338478.htmlcalvincalvinFri, 19 Nov 2010 06:32:00 GMThttp://www.tkk7.com/lihao336/archive/2010/11/19/338478.htmlhttp://www.tkk7.com/lihao336/comments/338478.htmlhttp://www.tkk7.com/lihao336/archive/2010/11/19/338478.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/338478.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/338478.html
q段旉在做一个项目,发现对Task和Activity掌握的还是不牢固。把相关知识整理在这里,方便查阅Q有几个Flag没看明白啥意思,也没试出来效果如何。。?br />
android:allowTaskReparenting
用来标记Activity能否从启动的TaskUd到有着affinity的TaskQ当q个Taskq入到前台时Q—?#8220;true”Q表CUdQ?#8220;false”Q表C它必须呆在启动时呆在的那个Task里?br /> 如果q个Ҏ(gu)没有被讑֮Q设定到元素上的allowTaskReparentingҎ(gu)的g应用到Activity上。默认gؓ“false”?br /> 一般来_当Activity启动后,它就与启动它的Task兌Qƈ且在那里耗尽它的整个生命周期。当当前的Task不再昄Ӟ你可以用这个特性来强制ActivityUd到有着affinity的Task中。典型用法是Q把一个应用程序的ActivityUd另一个应用程序的主Task中?br /> 例如Q如果eQmail中包含一个web늚链接Q点d?yu)׃启动一个Activity来显C个页面。这个Activity是由Browser应用E序定义的,但是Q现在它作ؓeQmail Task的一部分。如果它重新宿主到Browser Task里,当Browser下一ơ进入到前台Ӟ它就能被看见Qƈ且,当eQmail Task再次q入前台Ӟq不到它了?br /> Actvity的affinity是由taskAffinityҎ(gu)定义的。Task的affinity是通过d根Activity的affinity军_。因此,Ҏ(gu)定义Q根ActivityL位于相同affinity的Task里。由于启动模式ؓ“singleTask”?#8220;singleInstance”的Activity只能位于Task的底部,因此Q重新宿d能限?#8220;standard”?#8220;singleTop”模式?br />
android:alwaysRetainTaskState
用来标记Activity所在的Task的状态是否Lql来保持—?#8220;true”Q表CLQ?#8220;false”Q表C在某种情Ş下允许系l恢复Task到它的初始化状态。默认值是“false”。这个特性只针对Task的根Activity有意义;对其它Activity来说Q忽略之?br /> 一般来_特定的情形如当用户从ȝ面重新选择q个TaskӞpȝ会对q个Taskq行清理Q从stack中删除位于根Activity之上的所有ActivivityQ。典型的情况Q当用户有一D|间没有访问这个Task时也会这么做Q例?0分钟?br /> 然而,当这个特性设?#8220;true”Ӟ用户L能回到这个Task的最新状态,无论他们是如何启动的。这非常有用Q例如,像Browser应用E序Q这里有很多的状态(例如多个打开的TabQ,用户不想丢失q些状态?br />
android:clearTaskOnLaunch
用来标记是否从Task中清除所有的ActivityQ除了根Activity外(每当从主画面重新启动Ӟ—?#8220;true”Q表CL清除臛_的根ActivityQ?#8220;false”表示不。默认值是“false”。这个特性只对启动一个新的Task的ActivityQ根ActivityQ有意义Q对Task中其它的Activity忽略?br /> 当这个gؓ“true”Q每ơ用户重新启动这个TaskӞ都会q入到它的根Activity中,不管q个Task最后在做些什么,也不用h使用BACKq是HOMEd的。当q个gؓ“false”Ӟ可能会在一些情形下Q参考alwaysRetainTaskStateҎ(gu))清除Task的ActivityQ但不L?br /> 假设Q某Zȝ面启动了Activity PQƈ从那里迁U至Activity Q。接下来用户按下HOMEQ然后返回Activity P。一般,用户可能见到的是Activity QQ因为它是P的Task中最后工作的内容。然而,如果P讑֮q个Ҏ(gu)ؓ“true”Q当用户按下HOMEqɘq个Task再次q入前台Ӟ其上的所有的Activity(在这里是Q)都将被清除。因此,当返回到q个TaskӞ用户只能看到P?br /> 如果q个Ҏ(gu)和allowTaskReparenting都设定ؓ“true”Q那些能重新宿主的Activity会移动到׃naffinity的Task中;剩下的Activity都将被抛弃,如上所q?br />
android:finishOnTaskLaunch
用来标记当用户再ơ启动它的TaskQ在ȝ面选择q个TaskQ时已经存在的Activity实例是否要关闭(l束Q—?#8220;true”Q表C应该关闭,“false”表示不关闭。默认值是“false”?br /> 如果q个Ҏ(gu)和allowTaskReparenting都设定ؓ“true”Q这个特性胜出。Activity的affinity忽略。这个Activity不会重新宿主Q但是会销毁?br />
android:launchMode
用于指示Activity如何启动。这里有四种模式Q与Intent对象中的Activity FlagsQFLAG_ACTIVITY_*变量Q共同作用,来决定Activity如何启动来处理Intent。它们是Q?br />
"standard"
"singleTop"
"singleTask"
"singleInstance"

默认模式?#8220;standard”?br />
q些模式可以分成两大l别Q?#8220;standard”?#8220;singleTop”一l,“singleTask”?#8220;singleInstance”一l。具?#8220;standard”?#8220;singleTop”启动模式的Activity可以实例化很多次。这些实例可以属于Q何Taskq且可以位于Activity stack的Q何位|。典型的情况是,它们会进入调用startActivity()的TaskQ除非Intent对象包含FLAG_ACTIVITY_NEW_TASK标志Q在q种情况下会选择一个不同的Task——参考taskAffinityҎ(gu))?br /> 相反的,“singleTask”?#8220;singleInstance”只能启动一个Task。它们L位于Activity stack的底部。甚臻I讑֤一ơ只能拥有一个Activity的实例——只有一个这L(fng)Task?br /> “standard”?#8220;singleTop”模式只在一U情况下有差别:每次有一个新的启?#8220;standard”Activity的IntentQ就会创Z个新的实例来响应q个Intent。每个实例处理一个Intent。相似的Q一?#8220;singleTop”的Activity实例也有可能被创建来处理新的Intent。然而,如果目标Task已经有一个存在的实例q且位于stack的顶部,那么Q这个实例就会接收到q个新的IntentQ调用onNewIntent()Q;不会创徏新的实例。在其他情况下——例如,如果存在?#8220;singleTop”的Activity实例在目标Task中,但不是在stack的顶部,或者它在一个stack的顶部,但不是在目标Task中——新的实例都会被创徏q压入stack中?br /> “singleTask”?#8220;singleInstance”模式也只在一U情况下有差别:“singleTask”Activity允许其它Activity成ؓ它的Task的部分。它位于Activity stack的底部,其它ActivityQ必L“standard”?#8220;singleTop”ActivityQ可以启动加入到相同的Task中?#8220;singleInstance”ActivityQ换句话_不允许其它Activity成ؓ它的Task的部分。它是Task中的唯一Activity。如果它启动其它的ActivityQ这个Activity会被攄到另一个task中——好像Intent中包含了FLAG_ACTIVITY_NEW_TASK标志?br />
android:noHistory
用于标记当用户从Activity上离开q且它在屏幕上不再可见时Activity是否从Activity stack中清除ƈl束Q调用finish()Ҏ(gu)Q—?#8220;true”Q表C它应该关闭Q?#8220;false”Q表CZ需要。默认值是“false”?br /> “true”值意味着Activity不会留下历史痕迹。因为它不会在Activity stack的Task中保留,因此Q用户不能返回它?br />
android:taskAffinity
Activity为Task拥有的一个affinity。拥有相同的affinity的Activity理论上属于相同的TaskQ在用户的角度是相同?#8220;应用E序”Q。Task的affinity是由它的根Activity军_的?
affinity军_两g事情——Activity重新宿主的TaskQ参考allowTaskReparentingҎ(gu))和用FLAG_ACTIVITY_NEW_TASK标志启动的Activity宿主的Task?br /> 默认情况Q一个应用程序中的所有Activity都拥有相同的affinity。捏可以讑֮q个Ҏ(gu)来重组它们Q甚臛_以把不同应用E序中定义的Activity攄到相同的Task中。ؓ了明Activity不宿ȝ定的TaskQ设定该Ҏ(gu)ؓI的字符丌Ӏ?br /> 如果q个Ҏ(gu)没有设|,Activity从应用E序的设定那里承下来(参?application>元素的taskAffinityҎ(gu))。应用程序默认的affinity的名字是元素中设定的package名?br />
FLAG_ACTIVITY_BROUGHT_TO_FRONT
q个标志一般不是由E序代码讄的,如在launchMode中设|singleTask模式时系l帮你设定?br />
FLAG_ACTIVITY_CLEAR_TOP
如果讄Qƈ且这个Activity已经在当前的Task中运行,因此Q不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭Q然后这个Intent会作Z个新的Intent投递到老的ActivityQ现在位于顶端)中?br /> 例如Q假设一个Task中包含这些ActivityQAQBQCQD。如果D调用了startActivity()Qƈ且包含一个指向Activity B的IntentQ那么,C和D都将l束Q然后B接收到这个IntentQ因此,目前stack的状冉|QAQB?br /> 上例中正在运行的Activity B既可以在onNewIntent()中接收到q个新的IntentQ也可以把自己关闭然后重新启动来接收q个Intent。如果它的启动模式声明ؓ“multiple”(默认?Qƈ且你没有在这个Intent中设|FLAG_ACTIVITY_SINGLE_TOP标志Q那么它?yu)关闭然后重新创建;对于其它的启动模式,或者在q个Intent中设|FLAG_ACTIVITY_SINGLE_TOP标志Q都把q个Intent投递到当前q个实例的onNewIntent()中?br /> q个启动模式q可以与FLAG_ACTIVITY_NEW_TASKl合h使用Q用于启动一个Task中的根ActivityQ它会把那个Task中Q何运行的实例带入前台Q然后清除它直到根Activity。这非常有用Q例如,当从Notification Manager处启动一个Activity?br />
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
如果讄Q这在Task的Activity stack中设|一个还原点Q当Task恢复Ӟ需要清理Activity。也是_下一ơTask带着FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记q入前台Ӟ典型的操作是用户在主画面重启它)Q这个Activity和它之上的都关闭,以至于用户不能再q回到它们,但是可以回到之前的Activity?br /> q在你的E序有分割点的时候很有用。例如,一个e-mail应用E序可能有一个操作是查看一个附Ӟ需要启动图片浏览Activity来显C。这个Activity应该作ؓe-mail应用E序Task的一部分Q因是用户在q个Task中触发的操作。然而,当用L(fng)开q个TaskQ然后从ȝ面选择e-mail appQ我们可能希望回到查看的会话中,但不是查看图片附Ӟ因ؓq让人困惑。通过在启动图片浏览时讑֮q个标志Q浏览及其它启动的Activity在下ơ用戯回到mailE序旉全部清除?br />
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果讄Q新的Activity不会在最q启动的Activity的列表中保存?br />
FLAG_ACTIVITY_FORWARD_RESULT
如果讄Qƈ且这个Intent用于从一个存在的Activity启动一个新的ActivityQ那么,q个作ؓ{复目标的Activity会传到q个新的Activity中。这U方式下Q新的Activity可以调用setResult(int)Qƈ且这个结果值将发送给那个作ؓ{复目标的Activity?br />
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
q个标志一般不由应用程序代码设|,如果q个Activity是从历史记录里启动的Q常按HOME键)Q那么,pȝ会帮你设定?br />
FLAG_ACTIVITY_MULTIPLE_TASK
不要使用q个标志Q除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASKl合h使用Q可以禁用把已存的Task送入前台的行为。当讄Ӟ新的TaskL会启动来处理IntentQ而不这是是否已l有一个Task可以处理相同的事情?br /> ׃默认的系l不包含囑ŞTask理功能Q因此,你不应该使用q个标志Q除非你提供l用户一U方式可以返回到已经启动的Task?br /> 如果FLAG_ACTIVITY_NEW_TASK标志没有讄Q这个标志被忽略?br />
FLAG_ACTIVITY_NEW_TASK
如果讄Q这个Activity会成为历史stack中一个新Task的开始。一个TaskQ从启动它的ActivityC一个Task中的ActivityQ定义了用户可以q移的Activity原子l。Task可以Ud到前台和后台Q在某个特定Task中的所有ActivityL保持相同的次序?br /> q个标志一般用于呈?#8220;启动”cd的行为:它们提供用户一pd可以单独完成的事情,与启动它们的Activity完全无关?br /> 使用q个标志Q如果正在启动的Activity的Task已经在运行的话,那么Q新的Activity不会启动;代替的,当前Task会简单的Ud前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志Q可以禁用这一行ؓ?br /> q个标志不能用于调用方对已经启动的Activityhl果?br />
FLAG_ACTIVITY_NO_ANIMATION
如果在Intent中设|,q传递给Context.startActivity()的话Q这个标志将Lpȝq入下一个Activity时应用Acitivityq移动画。这q不意味着动画永不运行——如果另一个Activity在启动显CZ前,没有指定q个标志Q那么,动画被应用。这个标志可以很好的用于执行一q串的操作,而动画被看作是更高一U的事g的驱动?br />
FLAG_ACTIVITY_NO_HISTORY
如果讄Q新的Activity不再历史stack中保留。用户一d它,q个Activity关闭了。这也可以通过讄noHistoryҎ(gu)?br />
FLAG_ACTIVITY_NO_USER_ACTION
如果讄Q作为新启动的Activityq入前台Ӟq个标志在Activity暂停之前L从最前方的Activity回调的onUserLeaveHint()?br /> 典型的,一个Activity可以依赖q个回调指明昑ּ的用户动作引L(fng)ActivityUd后台。这个回调在Activity的生命周期中标记一个合适的点,q关闭一些Notification?br /> 如果一个Activity通过非用户驱动的事gQ如来电(sh)或闹钟,启动的,q个标志也应该传递给Context.startActivityQ保证暂停的Activity不认为用户已l知晓其Notification?br />
FLAG_ACTIVITY_PREVIOUS_IS_TOP
If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.

FLAG_ACTIVITY_REORDER_TO_FRONT
如果在Intent中设|,q传递给Context.startActivity()Q这个标志将引发已经q行的ActivityUd到历史stack的顶端?br /> 例如Q假设一个Task由四个Activityl成QA,B,C,D。如果D调用startActivity()来启动Activity BQ那么,B会移动到历史stack的顶端,现在的次序变成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP标志也设|的话,那么q个标志被忽略?br />
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.

FLAG_ACTIVITY_SINGLE_TOP
如果讄Q当q个Activity位于历史stack的顶端运行时Q不再启动一个新的?


Activity和Task

之前提到的,一个Activity可以启动另一个,即便是定义在不同应用E序中的Activity。例如,假设你想让用hCZ些地方的街景。而这里已l有一个Activity可以做到q一点,因此Q你的Activity所需要做的只是在Intent对象中添加必要的信息Qƈ传递给startActivity()。地图浏览将会显CZ的地图。当用户按下BACK键,你的Activity会再ơ出现在屏幕上?br />
对于用户来说Q看h好像是地图浏览与你的Activity一P属于相同的应用程序,即便是它定义在其它的应用E序里,q运行在那个应用E序的进E里。Android通过这两个Activity保存在同一个Task里来体现q一用户体验。简单来_一个Task是用户体验上的一?#8220;应用”。它?yu)相关的Activityl合在一P以stack的方式管理。stack中根Activity启动Task——典型的Q它?yu)是用户在应用程序启动栏中选择的Activity。位于stack端的Activity是当前正在运行的——能够聚焦用L(fng)动作。当一个Activity启动另一个,新的Activityq入stackQ它成ؓ正在q行的Activity。之前的Activity仍保留在stack中。当用户按下BACK键,当前的Activity从stack中退出,之前的那个成为正在运行的Activity?br />
stack包含对象Q因此,如果一个Task中有多个同一个Activity的实例时——多个地图浏览,例如——stack为每个实例拥有一个独立的入口。位于stack中的Activity不会重新调整Q只是进入和退出?br />
一个Task是一lActivityQ不是一个类或者在manifest中定义的一个元素。因此,没有办法为Task讄独立于它的Activity的属性倹{Task的g为整体在根Activity中设|。例如,下一个章节会讨论Task?#8220;affinity”Q那个值就是从Task中的根Activity中读取的?br />
Task中的所有Activity作ؓ一个单元一L(fng)动。整个TaskQ整个Activity stackQ可以进入前台或者退到后台。例如,假设当前Task中的stack中有4个Activity—?个位于当前Activity下方。用h下HOME键,q入到应用程序启动栏Q然后选择一个新的应用程序(实际上,一个新的TaskQ。当前Task退到后収ͼq且新Task中的根Activity会显C出来。然后,l过一D|间后Q用户回到Home画面Q然后再ơ选择前一个应用程序(前一个TaskQ。那个拥?个Activity的Task会进入前台。当用户按下BACK键,屏幕不会昄用户刚刚d的ActivityQ前一个Task的根ActivityQ。而是Q这个stack中的端ActivityU除Q相同Task中的前一个Activity会显C出来?br />
刚才描述的行为是Activity和Task的默认行为。但有方法来完全改变它。Task之间的关联,和一个Task中的一个Activity行ؓQ受启动Activity的Intent对象中设|的Flag和manifest文g中Activity?activity>元素的特性g互控制。调用者和响应者都有权军_如何发生?br />
核心的Intent Flag有:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP

核心?activity>Ҏ(gu)有Q?br /> taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch

接下来的章节描qC些Flag和特性的用法Q如何相互媄响,以及在用时的徏议?br />
Affinity和新Task
默认情况下,一个应用程序中的所有Activity都有affinity——也是_属于同一个Task中所有Activity有一个设定。然而,每个Activity都可以在元素的taskAffinityҎ(gu)上讄单独的倹{定义在不同应用E序中的Activity可以׃n同一个affinityQ或者定义在同一个应用程序中的Activity讄不同的affinity。Affinity在两U环境下工作QIntent对象包含FLAG_ACTIVITY_NEW_TASK标志Q和Activity的allowTaskReparentingҎ(gu)设|ؓ“true”?br /> FLAG_ACTIVITY_NEW_TASK:
之前描述的,一个Activity一般通过调用startActivity()启动q加入到Task中。它同调用者一Pq入同一个Task。然而,如果传递给startActivity()的Intent对象中包含FLAG_ACTIVITY_NEW_TASKӞpȝ会搜索一个新的Task来容Ux的Activity。通常Q如标志的名字所C,是一个新的Task。然而,q不是必L。如果已l存在一个Task与新Activity的affinity相同Q这个Activity׃加入到那个Task中。如果不是,启动一个新的Task?br /> allowTaskReparentingQ?br /> 如果一个Activity的allowTaskReparentingҎ(gu)设|ؓ“true”Q它?yu)p从启动的Task中移到有着相同affinity的TaskQ这个Taskq入到前台的时候)。例如,在一个旅游的E序中定义了一个可以报告选择城市的天气情늚Activity。它和同一个应用程序的其它Activity一P有着相同的AffinityQ默认的AffinityQ,q且它允?dng)R新宿丅R你的Activity中的一个启动了天气预报Q因此,它初始化到和你Activity相同的Task中。然而,当旅游应用程序下一ơ进入到前台Ӟ天气预报那个Activity会重新~排q在那个Task中显C?br />
如果从用L(fng)角度出发Q一?apk文g包含多个“应用”的话Q你可能希望为关联的Activity讄不同的affinity?br />
Launch Mode

q里4U不同的启动模式可以讄?activity>元素的launchModeҎ(gu)上Q?br /> standardQ默认模式)
singleTop
singleTask
singleInstance

q些模式有以下四点区别:
l 哪个Task容U_应Intent的Activity。对?#8220;standard”?#8220;singleTop”来说Q是产生Intent的那个TaskQƈ调用startActivity()Q——除非Intent对象包含FLAG_ACTIVITY_NEW_TASK。在那种情况下,不同的Task被选择Q如“Affinity和新Task”中描q的那样。对比而言Q?#8220;singleTask”?#8220;singleInstance”指示ActivityL一个Task的根。它们定义一个TaskQ它们不会加入到另一个Task中?br /> l 是否有多个Activity的实例?#8220;standard”?#8220;singleTop”可以实例化多ơ。它们可以属于多个TaskQ一个特定的Task可以有相同Activity的多个实例。对比而言Q?#8220;singleTask”?#8220;singleInstance”只能有一个实例。因些Activity只能位于Task的底部,q一限制意味着在设备的某个旉Q不会出现这样Task的多个实例?br /> l 是否可以在同一个Task中拥有其它的Activity?#8220;singleInstance”Activity保持单nQ在它的Task中它是仅有的Activity。如果它启动另一个ActivityQ那个Activity会攑օC同的Task中,而不它的启动模式——好像FLAG_ACTIVITY_NEW_TASK在Intent中一栗对于其它方面,Q?#8220;singleInstance”{同?#8220;singleTask”。其它三个模式允许多个Activity加入到这个Task中?#8220;singleTask”ActivityL位于Task的底部,但它可以启动其它的Activityq放入到它的Task中?#8220;standard”?#8220;singleTop”的Activity可以出现在stack的Q何地斏V?br /> l 是否一个新的实例启动来处理新的Intent。对于默认的“standard”来说Q都是创Z个新的实例来响应新的Intent。每个实例处理一个Intent。对?#8220;singleTop”来说Q如果它位于目标Task的顶端,那么Q已l存在的实例可以重复用来处理q个新的Intent。如果它不在端Q那么它?yu)׃能重复用。替代的Q新的实例将创徏来响应新的IntentQƈq入到stack中?br /> 例如Q假设一个Task的Activity stack中包含根Activity A和其它Activity BQCQDQƈ且D位于端Q因此,stack是A-B-C-D。有一个Intent来了Q它要启动Dcd的Activity。如果D有默认的“standard”启动模式Q那么,一个新的实例将被启动ƈ且stack变成A-B-C-D-D。然而,如果D的启动模?#8220;singleTop”Q已l存在的实例去处理新来的IntentQ因为它正好处在stack的顶端)Qƈ且stack依旧是A-B-C-D?br /> 换句话说Q如果来临的Intent是冲着Bcd的,那么QBcd的实例将被创建启动而不B的模式是“standard”?#8220;singleTop”Q因为B不处在stack的顶端)Q因此,stack会是A-B-C-D-B?br /> 之前提到的,讑֤上不会出现超q一个实例的“singleTask”?#8220;singleInstance”ActivityQ因此,那个实例都将d理所有新来的Intent?#8220;singleInstance”ActivityL位于stack的顶端(因ؓ它是task中唯一的ActivityQ,因此Q它L处于能处理Intent的位|。然而,“singleTask”Activity可能有或没有其它Activity处于它的上方。如果有Q它?yu)׃处于能处理Intent的位|,那么Q这个Intent被丢弃。(即Intent被丢弃了Q它的到来会引发那个Taskq入到前収ͼ在那里,它会l箋保留。)

当一个存在的Activityhd理一个新的IntentӞIntent对象传到该Activity的onNewIntent()的方法中。(原来启动Activity的Intent对象可以通过调用getIntent()得到。)

注意Q当一个新的实例创建来处理新的IntentӞ用户可以按下BACK键返回到之前的状态(前一个ActivityQ。但一个存在的实例来处理新的IntentӞ用户不能按下BACK键返回到新Intent到来之前的状态?br />
清除stack
如果用户dTask很长一D|_pȝ会清除Task中的所有ActivityQ除根Activity外。当用户再次q回到这个TaskӞ和用L(fng)开时一P仅仅只是初始化Activity呈现。这样做的意图是Q经q一些时间后Q用户可能已l忘C前正在做的事情,q且打算回到Task开始些新的时期?br />
q是默认情况。这里有一些ActivityҎ(gu)可以用于控制这一行ؓq且修改它:
alwaysRetainTaskStateQ?br /> 如果Task的根Activity的这个特性设|ؓ“true”Ӟ上面描述的默认行Z会发生。Task保留所有的ActivityQ即便是l过很长一D|间?br /> clearTaskOnLaunchQ?br /> 如果Task的根Activity的这个特性设|ؓ“true”Ӟ当用L(fng)开Taskq返回时Qstack会清除直到根Activity。换句话_它是alwaysRetainTaskState的另一个极端。用hL回到Task的初始化状态,即便是一个短暂的d?br /> finishOnTaskLaunchQ?br /> q个Ҏ(gu)和clearTaskOnLaunch怼Q但它针对单个ActivityQ不是整个Task。它能MActivity消失Q包括根Activity。当它设|ؓ“true”Ӟq个Activity仅在当前会话期间保持为Task的部分。如果用L(fng)开q再ơ返回到q个TaskQ它?yu)׃再显CZ?br />
q里q有其它的方式可以强制Activity从stack中移除。如果Intent对象中包含FLAG_ACTIVITY_CLEAR_TOP标志Qƈ且目标Task中已l有一个这个类型Activity的实例,而且q个实例应该处理q个IntentQ那么,位于其上的Activity都将U除Q这Pq个Activityp在stack的顶端ƈ响应q个Intent。如果这个Activity的启动模式设定ؓ“standard”Q它也会从stack中清除,然后新的实例启动来响应这个Intent。这是因为当启动模式讑֮?#8220;standard“ӞL会创Z个新的实例来响应新的Intent?br />
FLAG_ACTIVITY_CLEAR_TOPl常与FLAG_ACTIVITY_NEW_TASKl合h使用。当一起用时Q这些标志可以定位其它Task中已l存在的ActivityQƈ且把它置于可以响应Intent的位|?br />
启动Task
如果一个Activity的Intent Filter的action?#8220;android.intent.action.MAIN”、category?#8220;android.intent.category.LAUNCHER”Ӟ它就可以作ؓ一个Task的入口点。有q种cd的Filter会在Dq个Activity在应用程序启动栏昄一个图标和标签Q给用户提供一个方式可以启动这个Task和在M时候可以再ơ回到这个Task?br />
W二个能力很重要Q用户一定可以离开一个TaskQ然后可以再ơ回到它。基于这个原因,两个启动模式Q?#8220;singleTask”?#8220;singleInstance”应该只在有MAIN和LAUNCHER的Activity上用。例如,假设q个Filter没有的话Q一个Intent启动了一?#8220;singleTask”ActivityQ初始化一个新的TaskQ然后用戯费了一些时间在它上面。然后,用户按下HOME键。现在,q个Task处于后台q且被HOME画面遮盖。由于它不能在应用程序启动栏昄Q用户就没有办法可以q回它?br />
在面对FLAG_ACTIVITY_NEW_TASKӞ也有怼的困难。如果这个标志导致一个Activity启动了一个新的TaskQƈ且用h下HOME键离开它,q里必须有方法可以再ơ回到它。一些机能(如Notification ManagerQL在外部的Task中启动ActivityQ而不是作q一部分Q因此,它L把FLAG_ACTIVITY_NEW_TASK标志攑օIntentQ然后传递给startActivity()。如果你的Activity可能会被外部的机能(可能使用q个标志Q调用,注意用户可以额外的方式可以返回到启动的Task?br />
如果你不想用户回到某个ActivityQ可以把元素的finishOnTaskLaunch讄?#8220;true”?br />
http://www.cnblogs.com/xirihanlin/archive/2010/06/03/1750811.html


calvin 2010-11-19 14:32 发表评论
]]>
Handler与Androidq程理http://www.tkk7.com/lihao336/archive/2010/10/27/336309.htmlcalvincalvinWed, 27 Oct 2010 11:01:00 GMThttp://www.tkk7.com/lihao336/archive/2010/10/27/336309.htmlhttp://www.tkk7.com/lihao336/comments/336309.htmlhttp://www.tkk7.com/lihao336/archive/2010/10/27/336309.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/336309.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/336309.html阅读全文

calvin 2010-10-27 19:01 发表评论
]]>
调试跟踪Android源代?/title><link>http://www.tkk7.com/lihao336/archive/2010/10/25/336058.html</link><dc:creator>calvin</dc:creator><author>calvin</author><pubDate>Mon, 25 Oct 2010 02:09:00 GMT</pubDate><guid>http://www.tkk7.com/lihao336/archive/2010/10/25/336058.html</guid><wfw:comment>http://www.tkk7.com/lihao336/comments/336058.html</wfw:comment><comments>http://www.tkk7.com/lihao336/archive/2010/10/25/336058.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/lihao336/comments/commentRss/336058.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/lihao336/services/trackbacks/336058.html</trackback:ping><description><![CDATA[1、编译android 代码?wi),~译sdkQ?br /> ~译注意Q?br /> 1Qgcc的版本过高,׃android源码~译要求?.3Q如果你的gcc版本?.4Q那你的~译可能会失败的Q我的系l是ubuntu 10.04,默认的gcc版本?.4Qgcc-4.4太严|那么怎样从gcc-4.4降到gcc- 4.3呢?<br /> 1、安装gcc-4.3<br /> $ sudo apt-get install gcc-4.3 g++-4.3<br /> 2、修gcc相关链接<br /> $ cd /usr/bin<br /> $sudo ln -snf gcc-4.3 gcc<br /> $sudo ln -snf g++-4.3 g++<br /> $sudo ln -snf cpp-4.3 cpp<br /> <br /> gcc,g++链接?.3版本卛_?br /> <br /> 2QJDK 5.0, update 12 or higher.Java 6 is not supported, because of incompatibilities with @Override.<br /> <br /> 3Q? sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl sun-java5-jdk zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-dev<br /> 参见http://source.android.com/source/download.html<br /> <br /> 2、拷贝development/ide/eclipse/.classpath?classpath.<br /> <br /> 3、启?eclipse Q按照这个步?File->New->Java Project (不是 Android Project!) ->Create project from existing source 选到代码?wi)根目?.<br /> <br /> 4、在l过长时间等待之后, source code被导入projectQ正常情况下应该没有error?br /> <br /> 5启动模拟?br /> [calvin@calvin-desktop ~/android/source-code/android_1.5_Sourcecode 10:28:03 ] $ . build/envsetup.sh <br /> [calvin@calvin-desktop ~/android/source-code/android_1.5_Sourcecode 10:28:18 ] $ lunch 1<br /> [calvin@calvin-desktop ~/android/source-code/android_1.5_Sourcecode 10:30:31 ] $ ./out/host/linux-x86/bin/emulator<br /> <br /> 6?strong>在ddms中选中要调试的q程</strong><br /> <br /> 7、在source code中设|断?br /> <br /> 8、在eclipse? Run->Debug Configuration->Remote Java Application->New, 讄 Connection port to 8700 (DDMS’s 默认端口),卛_正常调试?br /> <span id="1166116" class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"></span> <img src ="http://www.tkk7.com/lihao336/aggbug/336058.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/lihao336/" target="_blank">calvin</a> 2010-10-25 10:09 <a href="http://www.tkk7.com/lihao336/archive/2010/10/25/336058.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>滚动时显Cscrollbarhttp://www.tkk7.com/lihao336/archive/2010/10/18/335455.htmlcalvincalvinMon, 18 Oct 2010 06:25:00 GMThttp://www.tkk7.com/lihao336/archive/2010/10/18/335455.htmlhttp://www.tkk7.com/lihao336/comments/335455.htmlhttp://www.tkk7.com/lihao336/archive/2010/10/18/335455.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/335455.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/335455.html阅读全文

calvin 2010-10-18 14:25 发表评论
]]>
Building, running, and debugging Android sourcehttp://www.tkk7.com/lihao336/archive/2010/10/17/335355.htmlcalvincalvinSun, 17 Oct 2010 06:05:00 GMThttp://www.tkk7.com/lihao336/archive/2010/10/17/335355.htmlhttp://www.tkk7.com/lihao336/comments/335355.htmlhttp://www.tkk7.com/lihao336/archive/2010/10/17/335355.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/335355.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/335355.html阅读全文

calvin 2010-10-17 14:05 发表评论
]]>
android调试工具?/title><link>http://www.tkk7.com/lihao336/archive/2010/10/02/333674.html</link><dc:creator>calvin</dc:creator><author>calvin</author><pubDate>Sat, 02 Oct 2010 14:44:00 GMT</pubDate><guid>http://www.tkk7.com/lihao336/archive/2010/10/02/333674.html</guid><wfw:comment>http://www.tkk7.com/lihao336/comments/333674.html</wfw:comment><comments>http://www.tkk7.com/lihao336/archive/2010/10/02/333674.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/lihao336/comments/commentRss/333674.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/lihao336/services/trackbacks/333674.html</trackback:ping><description><![CDATA[     摘要:   <a href='http://www.tkk7.com/lihao336/archive/2010/10/02/333674.html'>阅读全文</a><img src ="http://www.tkk7.com/lihao336/aggbug/333674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/lihao336/" target="_blank">calvin</a> 2010-10-02 22:44 <a href="http://www.tkk7.com/lihao336/archive/2010/10/02/333674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Androidx界面代码http://www.tkk7.com/lihao336/archive/2010/10/02/333671.htmlcalvincalvinSat, 02 Oct 2010 13:39:00 GMThttp://www.tkk7.com/lihao336/archive/2010/10/02/333671.htmlhttp://www.tkk7.com/lihao336/comments/333671.htmlhttp://www.tkk7.com/lihao336/archive/2010/10/02/333671.html#Feedback0http://www.tkk7.com/lihao336/comments/commentRss/333671.htmlhttp://www.tkk7.com/lihao336/services/trackbacks/333671.html阅读全文

calvin 2010-10-02 21:39 发表评论
]]>
HTTP/1.1 Cache-Control的理?/title><link>http://www.tkk7.com/lihao336/archive/2010/09/29/333429.html</link><dc:creator>calvin</dc:creator><author>calvin</author><pubDate>Wed, 29 Sep 2010 13:43:00 GMT</pubDate><guid>http://www.tkk7.com/lihao336/archive/2010/09/29/333429.html</guid><wfw:comment>http://www.tkk7.com/lihao336/comments/333429.html</wfw:comment><comments>http://www.tkk7.com/lihao336/archive/2010/09/29/333429.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/lihao336/comments/commentRss/333429.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/lihao336/services/trackbacks/333429.html</trackback:ping><description><![CDATA[     摘要:   <a href='http://www.tkk7.com/lihao336/archive/2010/09/29/333429.html'>阅读全文</a><img src ="http://www.tkk7.com/lihao336/aggbug/333429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/lihao336/" target="_blank">calvin</a> 2010-09-29 21:43 <a href="http://www.tkk7.com/lihao336/archive/2010/09/29/333429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://dstbxg.com" target="_blank">ҹ³˿ƬAV</a>| <a href="http://wwwv27.com" target="_blank">ҹ18ѿ</a>| <a href="http://sflhb.com" target="_blank">һһ߹ۿƵ</a>| <a href="http://www456788.com" target="_blank">Ʒ</a>| <a href="http://ranjihua.com" target="_blank">ۺϾþ</a>| <a href="http://szgyk.com" target="_blank">һƬaƵѹۿ</a>| <a href="http://kk600700.com" target="_blank">ɫ͵͵ۺAV </a>| <a href="http://hljjlhl.com" target="_blank">þþŷղa</a>| <a href="http://mmstom.com" target="_blank">Ƶȫ</a>| <a href="http://bd0574.com" target="_blank">Ʒ޾ƷþþƷ</a>| <a href="http://ivr69.com" target="_blank">Ƶһ</a>| <a href="http://sese3366.com" target="_blank">ŮػҹƵѿ</a>| <a href="http://57az.com" target="_blank">AVר</a>| <a href="http://sewuji.com" target="_blank">ƷһëƬ</a>| <a href="http://tttui.com" target="_blank">ֻˬƵ</a>| <a href="http://gayhh.com" target="_blank">޹˾Ʒ벥</a>| <a href="http://hzsprfm.com" target="_blank">޵һƵ߹ۿ</a>| <a href="http://fphs666.com" target="_blank">ŮëƬѹۿ97</a>| <a href="http://ai-xian.com" target="_blank">޵һվƵ</a>| <a href="http://jmdehong.com" target="_blank">91ƷѹƬ</a>| <a href="http://langya2255.com" target="_blank">޾ƷþþþAV鶹</a>| <a href="http://yakonet.com" target="_blank">ëƬѹۿ</a>| <a href="http://aqdav22.com" target="_blank">ձɫƵ</a>| <a href="http://dw168cn.com" target="_blank">vavaպ߹ۿ</a>| <a href="http://2002tw.com" target="_blank">AVһӰƬ</a>| <a href="http://pohezi.com" target="_blank">67194</a>| <a href="http://xj47777.com" target="_blank">޹˾þþƷӰ </a>| <a href="http://44od.com" target="_blank">һỵĺʹȫƵƵ߹ۿ </a>| <a href="http://xsdjiagu.com" target="_blank">ŮͬëƬ߲</a>| <a href="http://dddd20.com" target="_blank">ްv2017</a>| <a href="http://5kee.com" target="_blank">һƵ</a>| <a href="http://472849.com" target="_blank">ѵƵ</a>| <a href="http://8654123.com" target="_blank">ѾƵ߹ۿ</a>| <a href="http://woniuzn.com" target="_blank">99þ99ȾƷѹۿ</a>| <a href="http://2030188.com" target="_blank">ۺϼר</a>| <a href="http://da666f.com" target="_blank">պɫպƵվ</a>| <a href="http://tccqdy.com" target="_blank">ɫƵ</a>| <a href="http://theav25.com" target="_blank">aëƬ߲</a>| <a href="http://4eeyy.com" target="_blank">ۺɫһС˵</a>| <a href="http://lswqn.com" target="_blank">ҹҹƵѿ</a>| <a href="http://www99xyxy.com" target="_blank">avۺ߹ۿ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>