Android传感器、语音识别、定位系统、Google Map API、快捷方式、widget编程总结及示例

 Android特色开发
第一部分 传感器
   传感器是一种物理装置或生物器官,能够探测、感受外界的信号、物理条件(如:光、热、湿度)或化学组成(如:烟雾),并将探知的信息传递给其他设备或器官。
   Android支持的传感器有如下几种:
    Sensor.TYPE_ACCELEROMETER    加速度传感器
    Sensor.TYPE_GYROSCOPE     陀螺仪传感器
    Sensor.TYPE_LIGHT      亮度传感器
    Sensor.TYPE_MAGNETIC_FIELD    地磁传感器
    Sensor.ORIENTATION      方向传感器
    Sensor.TYPE_PRESSURE     压力传感器
    Sensor.TYPE_PROXIMITY     近程传感器
    Sensor.TYPE_TEMPERATURE     温度传感器
   Android中传感器 (此特效必须在真机中才能看到效果)
    Android传感器的使用需要掌握SensorManager和SensorEventListener
    SensorManager 就是传感器的一个综合管理类
     SensorManager mSensorManager = (SensorManger)getSystemService(SENSOR_SERVICE);//通过getSystemService得到SensorManager对象
     List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);//此处通过getSensorList获得我们需要的传感器类型,并保存到一个传感器列表中
     Boolean mRegisteredSensor = mSensorManager.registerListener(this,sensors,SensorManager.SENSOR_DELAY_FASTEST);//通过registerListener注册一个监听器其中
                          方法中参数  this---接收信号的Listener
                             sensors---接收传感器类型的列表即上一步的List<Sensor>
                             SensorManager.SENSOR_DELAY_FASTEST---接收频度
                          此方法调用之后返回一个boolean值,true为成功 ,false为失败
     mSensorManager.unregisterListener(this);//在不使用时需要通过unregisterListener卸载传感器
    SensorEventListener 传感器的核心部分 以下两个方法必须实现
     onSensorChanged(SensorEvent event) 此方法在传感器值更改时调用。该方法只由受此应用程序监视的传感器调用。
      其中参数为SensorEvent对象,该对象包括一组浮点数,表示传感器获得的方向、加速度等信息如下:
      float x = event.values[SensorManager.DATA_X];
      float y = event.values[SensorManager.DATA_Y];
      float z = event.values[SensorManager.DATA_Z];
     onAccuracyChanged(Sensor sensor,int accuracy) 此方法在传感器的精准度发生改变时调用。
      其中参数 第一个表示传感器 第二个表示传感器新的准确值
     除上两种重要方法外还有以下几种
      getDefaultSensor 得到默认的传感器对象
      getInclination  得到地磁传感器倾斜角的弧度制
      getOrientation  得到设备选择的方向
      getSensorList  得到指定传感器列表
      
   下例为实现了一个方向传感器的例子 实现了如何获得传感器的方向,加速度等信息,可以根据得到的数值与上一次得到的数值之间的关系进行需要操作。 
   public class Activity01 extends Activity implements SensorEventListener{
    private boolean   mRegisteredSensor; 
    private SensorManager  mSensorManager;//定义SensorManager

    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     mRegisteredSensor = false;  
     mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);//取得SensorManager实例
    }
    protected void onResume(){
     super.onResume(); 
     List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);//接受SensorManager的一个列表(Listener),这里我们指定类型为TYPE_ORIENTATION(方向感应器)
     if (sensors.size() > 0){
      Sensor sensor = sensors.get(0);   
      mRegisteredSensor = mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);//注册SensorManager,this->接收sensor的实例,第二个参数为接收传感器类型的列表,第三个参数为接受的频率
     }
    }
    protected void onPause(){
     if (mRegisteredSensor){   
      mSensorManager.unregisterListener(this);//通过unregisterListener来卸载\取消注册
      mRegisteredSensor = false;
     }
     super.onPause();
    } 
    public void onAccuracyChanged(Sensor sensor, int accuracy){//当进准度发生改变时调用此方法,sensor->传感器,accuracy->精准度
  
    }
    public void onSensorChanged(SensorEvent event){// 此方法在传感器在被改变时触发 
     if (event.sensor.getType() == Sensor.TYPE_ORIENTATION){// 接受方向感应器的类型
      //这里我们可以得到数据,然后根据需要来处理,由于模拟器上面无法测试效果,因此我们暂时不处理数据
      float x = event.values[SensorManager.DATA_X];
      float y = event.values[SensorManager.DATA_Y];
      float z = event.values[SensorManager.DATA_Z];
     }
    }
   }
第二部分 语音识别
   Android中通过RecognizerIntent来实现语音识别。
   RecognizerIntent包含以下常量:
    ACTION_RECOGNIZE_SPEECH    开启语音活动
    ACTION_WEB_SEARCH     开启网络语音模式,结果将以网页搜索显示
    EXTRA_LANGUAGE      设置一个语言库
    EXTRA_LANGUAGE_MODEL    语音识别模式
    EXTRA_MAX_RESULTS     返回最大的结果
    EXTRA_PROMPT      提示用户可以开始语音了
    EXTRA_RESULTS      将字符串返回到一个ArrayList中
    LANGUAGE_MODEL_FREE_FORM   在一种语言模式上自由语音
    LANGUAGE_MODEL_WEB_SEARCH   使用语音模式在Web上搜索
    RESULT_AUDIO_ERROR     返回结果时,音频遇到错误
    RESULT_CLIENT_ERROR     返回结果时,客户端遇到错误
    RESULT_NETWORK_ERROR    返回结果时,网络遇到错误
    RESULT_NO_MATCH      没有检测到语音的错误
    RESULT_SERVER_ERROR     返回结果时,服务器遇到错误
   在使用语音识别时需要通过Intent来传递一个动作以及一些属性,然后通过startActivityForResult来开始语音 代码如下:
    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RcognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    intent.putExtra(RecognizerIntent.EXTRA_PROMPT,"开始语音");
    startActivityForResult(intent ,VOICE_RECOGNITION_REQUEST_CODE);//通过startActivityForResult来开始语音
    另外还需要实现onActivityResult方法,当语音接收时,会触发来获得语音的字符序列。
    
   下例中我们实现了 点击按钮时开始语音,并在onActivityResult方法中取得结果并显示出来
   main.xml
   <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
     <TextView 
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/hello"
     />
     <Button
      android:id="@+id/Button01"
      android:text="开始使用语音识别"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"/>
     <ListView
      android:id="@+id/ListView01"
      android:layout_width="fill_parent"
      android:layout_height="0dip"
      android:layout_weight="1" />
    </LinearLayout>

   public class Activity01 extends Activity{
    private static final int VOICE_RECOGNITION_REQUEST_CODE = 4321;
    private ListView mList;

    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
  
     mList = (ListView) findViewById(R.id.ListView01); 
     Button button = (Button) findViewById(R.id.Button01);
     button.setOnClickListener(new View.OnClickListener() {                      
      public void onClick(View v){
       try{     
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);//通过Intent传递语音识别的模式,开启语音     
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);//语言模式和自由形式的语音识别     
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT,"开始语音");//提示语音开始    
        startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);//开始执行我们的Intent、语音识别
       }catch (ActivityNotFoundException e){//如果找不到设置,就会抛出ActivityNotFoundException    
        Toast.makeText(Activity01.this,"ActivityNotFoundException", Toast.LENGTH_LONG).show(); //找不到语音设备装置
       }
      }     
     });
    } 
    protected void onActivityResult(int requestCode, int resultCode, Intent data){//当语音结束时的回调函数onActivityResult 
     if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK){// 判断是否是我们执行的语音识别  
      ArrayList<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);// 取得语音的字符
      //设置视图更新
      //mList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,results));
      String resultsString = "";
      for (int i = 0; i < results.size(); i++){
       resultsString += results.get(i);
      }
      Toast.makeText(this, resultsString, Toast.LENGTH_LONG).show();
      super.onActivityResult(requestCode, resultCode, data);
     }
    }
   }
第三部分 账户管理
   Android中通过android.accounts包中所包含的集中式的账户管理API,用于安全地存储和访问认证的令牌和密码。
   android.accounts包中的功能:
    AccountManagerCallback   账户管理回调接口
    AccountManagerFuture   代表一个AccountMananger的异步调用结果
    OnAccountUpdateListener   账户监听回调接口
    AbstractAccountAuthenticator 创建AccountAuthenticators(账户验证)的一个基类
    Account       AccountManager中的一个账户信息及类型
    AccountAuthenticatorActivity 用于实现一个AbstractAccountAuthenticator的活动
    AccountAuthenticatorResponse 账户验证响应
    AccountManager     账户管理器
    AuthenticatorDescription  一个Parcelable类型的值包括了账户验证的信息
   
    mAccountManager = AccountManager.get(this);//通过AccountManager类的get方法获得AccountManager对象
    AccountManager中的常用方法
     addAccount      添加一个账户
     addOnAccountUpdatedListenenr 添加一个账户更新的监听器
     removeOnAccountsUpdatedListener 取消一个账户更新的监听器
     clearPassword     清除指定账户的密码数据
     getAccounts      得到所有的账户信息
     getAccountsByType    得到指定类型的账户信息
     getPassword      得到指定账户的密码
     setUserData      设置指定账户的信息
     setPassword      设置指定账户的密码
     removeAccount     删除一个账户
 
    public class SleepyAccountAuthenticatorActivity extends AccountAuthenticatorActivity{//此类供用户输入信息
     protected void onCreate(Bundle icicle){
      super.onCreate(icicle);
      setContentView(R.layout.new_account);

      final Button done = (Button) findViewById(R.id.new_account_done);
      final EditText server = (EditText) findViewById(R.id.new_account_server);
      final EditText username = (EditText) findViewById(R.id.new_account_username);
      final EditText password = (EditText) findViewById(R.id.new_account_password);
      final Activity self = this;
      done.setOnClickListener(new OnClickListener() {
       public void onClick(View v){    
        Account account = new Account(username.getText().toString(), getString(R.string.ACCOUNT_TYPE));//通过指定账户名和账户类型构建一个Account对象
        Bundle userdata = new Bundle(); //将服务器数据通过Bundle方式加入进来
        userdata.putString("SERVER", server.getText().toString());    
        AccountManager am = AccountManager.get(self);//取得AccountManager    
        if (am.addAccountExplicitly(account, password.getText().toString(), userdata)){//通添addAccountExplicitly向账户管理器中添加一个账户信息
         Bundle result = new Bundle();
         result.putString(AccountManager.KEY_ACCOUNT_NAME, username.getText().toString());
         result.putString(AccountManager.KEY_ACCOUNT_TYPE, getString(R.string.ACCOUNT_TYPE));
         setAccountAuthenticatorResult(result);
        }
        finish();
       }
      });
     }
    }

    public class SleepyAccountAuthenticator extends AbstractAccountAuthenticator{//在添加、操作账户信息时会通过AbstractAccountAuthenticator实现异步调用
     private String _tag = "SleepyAccountAuthenticator";
     private Context _context;

     public SleepyAccountAuthenticator(Context context){
      super(context);
      _context = context;
     }
     public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
                                 throws NetworkErrorException{//添加账户addAccount方法
      Log.d(_tag, accountType + " - " + authTokenType);
      Bundle ret = new Bundle();
      Intent intent = new Intent(_context, SleepyAccountAuthenticatorActivity.class);
      intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
      ret.putParcelable(AccountManager.KEY_INTENT, intent);
      return ret;
     }
     public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options){
      Log.d(_tag, ".confirmCredentials");
      return null;
     }
     public Bundle editProperties(AccountAuthenticatorResponse response, String accountType){
      Log.d(_tag, ".editProperties");
      return null;
     }
     public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws NetworkErrorException{
      Log.d(_tag, ".getAuthToken");
      return null;
     }
     public String getAuthTokenLabel(String authTokenType){
      Log.d(_tag, ".getAuthTokenLabel");
      return null;
     }
     public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException{
      Log.d(_tag, ".hasFeatures");
      return null;
     }
     public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions){
      Log.d(_tag, ".updateCredentials");
      return null;
     }
    }
 
    public class SleepyAccountsService extends Service{//账户服务类
     private SleepyAccountAuthenticator _saa;
     public IBinder onBind(Intent intent){
      IBinder ret = null;
      if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)){
       ret = getSleepyAuthenticator().getIBinder();//通过getIBinder方法返回一个IBinder
       return ret;
      }
     }
     private SleepyAccountAuthenticator getSleepyAuthenticator(){
      if (_saa == null)
       _saa = new SleepyAccountAuthenticator(this);
      return _saa;
     }
    }
  
    public class Activity01 extends Activity{
     private String   _tag = "Activity01";
     private TextView  _accountList;
     private AccountManager _am;

     protected void onCreate(Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      setContentView(R.layout.manage_accounts);

      _accountList = (TextView) findViewById(R.id.manage_accounts_accountlist);
      _am = AccountManager.get(this);//取得AccountManager对象
      Button newacc = (Button) findViewById(R.id.manage_accounts_newaccount);
      final Activity self = this;
      newacc.setOnClickListener(new OnClickListener() {
       public void onClick(View v){
        _am.addAccount(getString(R.string.ACCOUNT_TYPE), null, null, null, self, new AccountManagerCallback<Bundle>() {
         @Override
         public void run(AccountManagerFuture<Bundle> amfuture){
          try{
           Log.d(_tag, amfuture.getResult().toString());
          }catch (Exception e){
           Log.e(_tag, e.getMessage(), e);
          }
          listAccounts();
         }
        }, null);
       }
      });
      listAccounts();
     }
     private void listAccounts(){//显示出所有账户
      Account[] accounts = _am.getAccountsByType(getString(R.string.ACCOUNT_TYPE));//得到指定类型的账户
      _accountList.setText("账户列表:");
      for (Account account : accounts){
       _accountList.setText(_accountList.getText().toString() + '\n' + account.name + " - " + account.type);
      }
     }
    }


    res.xml.authenticator.xml文件
    <?xml version="1.0" encoding="utf-8"?>
     <account-authenticator
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:accountType="com.yarin.AccountType"
      android:icon="@drawable/icon"
      android:smallIcon="@drawable/icon"
      android:label="@string/ACCOUNT_LABEL"
      android:accountPreferences="@xml/account_preferences"
      />
      
    res.xml.account_preferences.xml文件
    <?xml version="1.0" encoding="utf-8"?>
     <PreferenceScreen
      xmlns:android="http://schemas.android.com/apk/res/android">
     </PreferenceScreen>

    res.layout.new_account.xml文件
    <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
      <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="用户名"
      ></TextView>
      <EditText
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/new_account_username"
       android:text="请输入用户名"
      ></EditText>
      <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="密码"
      ></TextView>
      <EditText
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/new_account_password"
       android:text="请输入密码"
      ></EditText>
      <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="服务器"
      ></TextView>
      <EditText
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/new_account_server"
       android:text="请输入账户服务器"
      ></EditText>
      <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/new_account_done"
       android:text="完成"
      ></Button>
     </LinearLayout>
     
    res.layout.manage_account.xml文件
    <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
      <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="新建账户"
       android:id="@+id/manage_accounts_newaccount"
      ></Button>
      <ScrollView
       android:id="@+id/ScrollView01"
       android:layout_height="fill_parent"
       android:layout_width="fill_parent"
       >
       <TextView
        android:text="@+id/TextView01"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:id="@+id/manage_accounts_accountlist"
       ></TextView>
      </ScrollView>
     </LinearLayout>
    
    AndroidManifest.xml文件
    <?xml version="1.0" encoding="utf-8"?>
     <manifest
      xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.yarin.android.Examples_09_08"
      android:versionCode="1"
      android:versionName="1.0"
      >
      <application
       android:icon="@drawable/icon"
       android:label="@string/app_name"
       >
       <service //开启一个账户管理服务
        android:name="SleepyAccountsService">
        <intent-filter>
         <action android:name="android.accounts.AccountAuthenticator" ></action>
        </intent-filter>
        <meta-data
         android:name="android.accounts.AccountAuthenticator"
         android:resource="@xml/authenticator">
        </meta-data>
       </service>
       <activity
        android:name=".auth.SleepyAccountAuthenticatorActivity"
        >
        <intent-filter>
         <action
          android:name="android.accounts.AccountAuthenticator"
         ></action>
        </intent-filter>
       </activity>
       <activity
        android:name="Activity01"
        >
        <intent-filter>
         <action
          android:name="android.intent.action.MAIN"
         ></action>
         <category
          android:name="android.intent.category.LAUNCHER"
         ></category>
        </intent-filter>
       </activity>
      </application>
       //因要对账户信息进行操作,需要在AndroidManifest.xml文件中对操作权限进行声明 确定API为5
      <uses-sdk android:minSdkVersion="5"/>
      <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"></uses-permission>
      <uses-permission android:name="android.permission.ACCOUNT_MANAGER"></uses-permission>
      <uses-permission android:name="android.permission.GET_ACCOUNTS"></uses-permission>
      <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"></uses-permission>
     </manifest>
第四部分 桌面组件
  一、快捷方式
   在应用程序中通过代码来将一个应用程序添加到Android的Shortcuts列表中。
   下例实现了添加一个发送邮件的应用到快捷方式列表中去。
   public class Activity01 extends Activity{
    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState); 
     Intent addShortcut; //要添加的快捷方式的Intent
  
     if (getIntent().getAction().equals(Intent.ACTION_CREATE_SHORTCUT)){//判断是否要添加快捷方式
      addShortcut = new Intent();    
      addShortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, "发送邮件");//设置快捷方式的名字   
      Parcelable icon = Intent.ShortcutIconResource.fromContext(this,R.drawable.mail_edit);  //构建快捷方式中专门的图标  
      addShortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,icon);//添加快捷方式图标 其实android提供了Intent.ShortcutIconResource.fromContext来创建快捷方式的图标,
                           最后通过setResult来返回构建一个快捷方式   
      Intent mailto = new  Intent(Intent.ACTION_SENDTO, Uri.parse( "mailto:[email protected]" )); //构建快捷方式执行的Intent  
      addShortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, mailto);  //添加快捷方式Intent 对应快捷方式执行的事件   
      setResult(RESULT_OK,addShortcut); //通过setResult来返回构建一个快捷方式
     }else{  
      setResult(RESULT_CANCELED); //取消
     }  
     finish();  //关闭
    }
   }
   AndroidManifest.xml
   <?xml version="1.0" encoding="utf-8"?>
    <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.yarin.android.Examples_09_05"
     android:versionCode="1"
     android:versionName="1.0">
     <application
      android:icon="@drawable/icon" android:label="@string/app_name">
      <activity
       android:name=".Activity01"
       android:label="@string/app_name">
       <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.CREATE_SHORTCUT" /> //注册时添加一个Action为android.intent.action.CREATE_SHORTCUT的IntentFilter
                         添加之后Shortcuts列表中就会出现应用程序的图标和名字
       </intent-filter>
      </activity>
     </application>
     <uses-sdk android:minSdkVersion="5" />
    </manifest>
   最后可以在Shortcuts列表中找到所添加的快捷方式,并可将其添加到桌面。
  二、实时文件夹
   Live Folders就是一个查看你的手机中所有电子书、电子邮件、ress订阅、播放列表的快捷方式,并且这些内容是实时更新的。
   Live Folders本身不存储任何信息,都是以映射的方式查看其ContentProvider所指向的数据信息,并可以自定义显示格式,所以LiveFold可以实时的更新显示内容。
   在开发时要确保所指定数据信息URI的ContentProvider支持文件夹查询。
   Live Folders的常用属性
    EXTRA_LIVE_FOLDER_BASE_INTENT  选中选项后执行的事件
    EXTRA_LIVE_FOLDER_NAME    实时文件夹的名字
    EXTRA_LIVE_FOLDER_ICON    实时文件夹的图标
    EXTRA_LIVE_FOLDER_DISPLAY_MODE  实时文件夹的显示模式(列表和宫格)
   下例中通过Live Folders调用电话本中的信息,当点击其中一条信息时,便执行呼叫该联系人的动作。
   public class Activity01 extends Activity{
    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     // setContentView(R.layout.main);  
     if (getIntent().getAction().equals(LiveFolders.ACTION_CREATE_LIVE_FOLDER)){// 判断是否创建实时文件夹
      Intent intent = new Intent();//将实时文件夹的信息装入Intent对象
      intent.setData(Uri.parse("content://contacts/live_folders/people"));// 设置数据地址   
      intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT, new Intent(Intent.ACTION_CALL, ContactsContract.Contacts.CONTENT_URI));// 设置当我们单击之后的事件,这里单击一个联系人后,呼叫  
      intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, "电话本");// 设置实时文件夹的名字  
      intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON, Intent.ShortcutIconResource.fromContext(this, R.drawable.contacts));// 设置实施文件夹的图标   
      intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);// 设置显示模式为列表   
      setResult(RESULT_OK, intent);// 设置为Intent
     }else{
      setResult(RESULT_CANCELED);
     }
     finish();//结束Activity
    }
   }
   AndroidManifest.xml文件
   <?xml version="1.0" encoding="utf-8"?>
    <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.yarin.android.Examples_09_06"
     android:versionCode="1"
     android:versionName="1.0">
     <application
      android:icon="@drawable/icon" android:label="@string/app_name">
      <activity
       android:name=".Activity01"
       android:label="@string/app_name">
       <intent-filter>  //注册一个action动作为android.intent.action.CREATE_LIVE_FOLDER的Intentfilter
        <action android:name= "android.intent.action.CREATE_LIVE_FOLDER" />
        <category android:name= "android.intent.category.DEFAULT" />
       </intent-filter>
      </activity>
     </application>
     <uses-sdk android:minSdkVersion="5" />
    </manifest>
  三、Widget开发
   作用:可以显示即将到来的日历事件,或者一首后台播放的歌曲的详细信息。

   public class ExampleAppWidgetProvider extends AppWidgetProvider{//创建一个Widget
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){//周期更新时调用
     final int N = appWidgetIds.length;
     for (int i = 0; i < N; i++){
      int appWidgetId = appWidgetIds[i];
      String titlePrefix = Activity01.loadTitlePref(context, appWidgetId);
      updateAppWidget(context, appWidgetManager, appWidgetId, titlePrefix);
     }
    } 
    public void onDeleted(Context context, int[] appWidgetIds){//当桌面部件删除时调用
     //删除appWidget
     final int N = appWidgetIds.length;
     for (int i = 0; i < N; i++){
      Activity01.deleteTitlePref(context, appWidgetIds[i]);
     }
    } 
    public void onEnabled(Context context){//当AppWidgetProvider提供的第一个部件被创建时调用
     PackageManager pm = context.getPackageManager();
     //用ComponentName来表示应用程序中某个组件的完整名字
     pm.setComponentEnabledSetting(new ComponentName("com.yarin.android.Examples_09_07", ".ExampleBroadcastReceiver"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    } 
    public void onDisabled(Context context){//当AppWidgetProvider提供的最后一个部件被删除时调用
     PackageManager pm = context.getPackageManager();
     //用ComponentName来表示应用程序中某个组件的完整名字
     pm.setComponentEnabledSetting(new ComponentName("com.yarin.android.Examples_09_07", ".ExampleBroadcastReceiver"),
                       PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    } 
    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, String titlePrefix){//更新 
     RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider);//构建RemoteViews对象来对桌面部件进行更新  
     views.setTextViewText(R.id.appwidget_text, titlePrefix);//更新文本内容,指定布局的组件  
     appWidgetManager.updateAppWidget(appWidgetId, views);//将RemoteViews的更新传入AppWidget进行更新
    }
   }
 
   public class ExampleBroadcastReceiver extends BroadcastReceiver{//创建一个BroadcastReceiver类来接收更新的消息,在收到更新消息后就更新这个桌面的Widget组件
    public void onReceive(Context context, Intent intent){
     //通过BroadcastReceiver来更新AppWidget
     String action = intent.getAction();
     if (action.equals(Intent.ACTION_TIMEZONE_CHANGED) || action.equals(Intent.ACTION_TIME_CHANGED)){
      AppWidgetManager gm = AppWidgetManager.getInstance(context);
      ArrayList<Integer> appWidgetIds = new ArrayList<Integer>();
      ArrayList<String> texts = new ArrayList<String>();  
      Activity01.loadAllTitlePrefs(context, appWidgetIds, texts);   
      final int N = appWidgetIds.size();//更新所有AppWidget
      for (int i = 0; i < N; i++){
       ExampleAppWidgetProvider.updateAppWidget(context, gm, appWidgetIds.get(i), texts.get(i));
      }
     }
    }
   }

   public class Activity01 extends Activity{//此类为android.configure指定的类,用来输入信息
    private static final String PREFS_NAME  = "com.yarin.android.Examples_09_07.ExampleAppWidgetProvider";
    private static final String PREF_PREFIX_KEY = "prefix_";
    int       mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
    EditText     mAppWidgetPrefix;
    public Activity01(){
     super();
    }
    public void onCreate(Bundle icicle){
     super.onCreate(icicle);
     setResult(RESULT_CANCELED);
     setContentView(R.layout.appwidget_configure);
     mAppWidgetPrefix = (EditText) findViewById(R.id.appwidget_prefix);
     findViewById(R.id.save_button).setOnClickListener(mOnClickListener);
     Intent intent = getIntent();
     Bundle extras = intent.getExtras();
     if (extras != null){
      mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
     }
     if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID){
      finish();
     }
     mAppWidgetPrefix.setText(loadTitlePref(Activity01.this, mAppWidgetId));
    }
    View.OnClickListener mOnClickListener = new View.OnClickListener() {             
     public void onClick(View v) {
      final Context context = Activity01.this;
      String titlePrefix = mAppWidgetPrefix.getText().toString();
      saveTitlePref(context, mAppWidgetId, titlePrefix);   
      AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);//取得AppWidgetManager实例   
      ExampleAppWidgetProvider.updateAppWidget(context, appWidgetManager, mAppWidgetId, titlePrefix);//更新AppWidget
      Intent resultValue = new Intent();
      resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
      setResult(RESULT_OK, resultValue);
      finish();
     }
    };
    static void saveTitlePref(Context context, int appWidgetId, String text){
     SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
     prefs.putString(PREF_PREFIX_KEY + appWidgetId, text);
     prefs.commit();
    }
    static String loadTitlePref(Context context, int appWidgetId){
     SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
     String prefix = prefs.getString(PREF_PREFIX_KEY + appWidgetId, null);
     if (prefix != null){
      return prefix;
     }else{
      return context.getString(R.string.appwidget_prefix_default);
     }
    }
    static void deleteTitlePref(Context context, int appWidgetId){
    }
    static void loadAllTitlePrefs(Context context, ArrayList<Integer> appWidgetIds, ArrayList<String> texts){
    }
   }
   
   rew.xml.appwidget_provider.xml//用于描述桌面属性的文件
   <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:minWidth="100dp"//桌面组件的最小宽度和最小高度,其值可以用公式计算 .最小尺寸 = (单元格数*74)-2; 单元格数---期望的单元格数
     android:minHeight="50dp"
     android:updatePeriodMillis="86400000"//自动更新的时间间隔
     android:initialLayout="@layout/appwidget_provider"//界面描述文件
     android:configure="com.yarin.android.Examples_09_07.Activity01"//此条代码可选  如果你的Widget需要在启动前需要先启动一个Activity,则需要设定该项为你的Activity
     >
    </appwidget-provider>
  
   res.layout.appwidget_configure.xml
   <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
     >
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/appwidget_configure_instructions"
     />
     <EditText
      android:id="@+id/appwidget_prefix"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
     />
     <Button
      android:id="@+id/save_button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@android:string/ok"
     />
    </LinearLayout>

   res.layout.appwidget_provider.xml
   <?xml version="1.0" encoding="utf-8"?>
    <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/appwidget_text"
     android:textColor="#ff000000"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     />
     
   AndroidManifest.xml//注册AppWidget、BroadcastReceiver和Activity
   <?xml version="1.0" encoding="utf-8"?>
    <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.yarin.android.Examples_09_07"
     android:versionCode="1"
     android:versionName="1.0">
     <application
      android:icon="@drawable/icon"
      android:label="@string/app_name">
      <receiver
       android:name=".ExampleAppWidgetProvider">
       <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/appwidget_provider" />
       <intent-filter>
        <action
         android:name="android.appwidget.action.APPWIDGET_UPDATE" />
       </intent-filter>
      </receiver>
      <activity
       android:name=".Activity01">
       <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
       </intent-filter>
      </activity>
      <receiver
       android:name=".ExampleBroadcastReceiver"
       android:enabled="false">
       <intent-filter>
        <action android:name="android.intent.ACTION_TIMEZONE_CHANGED" />
        <action android:name="android.intent.ACTION_TIME" />
       </intent-filter>
      </receiver>
     </application>
     <uses-sdk android:minSdkVersion="5" />
    </manifest>
   将Widget添加到桌面上,和添加快捷方式一样。
   
第五部分 Google Map开发
   在Android SDK 1.5预装的add-on中提供了一个Map拓展库com.google.android.maps加强了地图功能。这个库的位置"Android SDK路径"\add-ons\google_apis-3\libs 。这个库并不是标准
   的Android sdk的内容,可以从这个位置下载,并放到你的SDK中,就可以为你新建的应用或者已有的应用加上地图功能了。
   在使用Android Map API之前的准备工作
    1、申请一个Android Map API Key步骤:
     为了顺利的申请Android Map API Key,必须要准备Google的账号和系统的证明书。一般Google 发布Key都需要Google的账号,Google的账号是通用的,Gmail的账号就可以了
     (可到http://www.google.com申请)。当一个应用程序发布时必须要证明书,证明书其实就是MD5. eclipse中测试可以使用Debug版的证明书。
     步骤1:找到你的debug.keystore文件
      证书的一般路径为:C:\Documents and Settins\当前用户\Local Settions\Application Data\Android\debug.keystore.
      如果在Eclipse开发中,便可以通过Windows\Preference\Android\Build.其中Default debug keystore的值便是debug.keystore的路径。
     步骤2:取得debug.keystore的MD5值
      首先在命令提示符下进入debug.keystore文件所在路径,执行命令:keytool-list-keystore debug.keystore这时会提示你输入密码,这里输入默认的密码"android",即可
      获得MD5值。
     步骤3:申请Android Map的API Key
      打开浏览器,输入网址:http://code.google.com/intl/zh-CN/android/maps-api-signup.html,登陆Google账号,在Google的Android Map API Key申请页面上输入步骤2
      得到的MD5认证指纹,选中"I have read and agree with the terms and conditons"选项,然后选中"Generate API Key"按钮,即可以得到申请的API Key.
    2、创建基于GoogleAPIs的AVD
     在Eclipse中打开AVD管理界面,在"Create AVD"部分的Name处填写AVD的名字,在Target处选择"Google APIs-1.5".点击"Create AVD"完成创建。
    3、创建基于Google APIs的工程
     同创建一般工程一样,但需要在Build Target处需要选择Google APIs。在运行工程时也需要选择我们刚刚创建的基于Google APIs的AVD来运行。
     下面将开始学习如何使用Google API来开发地图应用程序。
     
   Google Map API的使用
    Android中定义的包com.google.android.maps中几个重要的类:
     MapActivity
      这个类是用于显示Google Map的Activity类,它需要连接底层网络。MapActivity是一个抽象类,任何想要显示MapView的activity都需要派生自MapActivity,并且
      在其派生类的onCreate()中,创建一个MapView的实例。
     MapView
      用于显示地图的View组件。它派生自android.view.ViewGroup.它必须和MapActivity配合使用,而且只能被MapActivity创建,这是因为MapView需要通过后台的线程来连接网络或者
      文件系统,而这些线程要由MapActivity来管理。
     MapController
      MapController用于控制地图的移动,缩放等
     Overlay
      一个可显示于地图之上的可绘制的对象
     GeoPoint
      一个包含经纬度位置的对象
     
    第一例实现了地图浏览程序
     步骤1、创建工程,注意选择Builed Target为"Google APIs"
     步骤2、修改AndroidManifest.xml文件
     步骤3、创建MapView用于显示地图,即在xml文件中的布局,见例子
     步骤4、实现MapActivity,见例子
     步骤5、MapController的使用
     步骤6、Overlay的使用
     
     AndroidManifest.xml文件
     <?xml version="1.0" encoding="utf-8"?>
      <manifest
       xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.yarin.android.Examples_09_03"
       android:versionCode="1"
       android:versionName="1.0">
       <application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        <uses-library android:name="com.google.android.maps" />//要从网络获取数据,需添加权限
        <activity
         android:name=".Activity01"
         android:label="@string/app_name">
         <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
        </activity>
       </application>
       <uses-permission android:name="android.permission.INTERNET" />
       <uses-sdk android:minSdkVersion="5" />
      </manifest>
     
     main.xml文件
     <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       >
       <com.google.android.maps.MapView  //当然也可以在程序中通过代码 MapView map = new MapView(this,"[Android Maps API Key]");
        android:id="@+id/MapView01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:apiKey="0dYpmIXGIdwiVm-HEpzuUW2fjNYsFQ9EvYir1sg"/> //apiKey即是我们申请的Map API Key
      </RelativeLayout>
     
     public class Activity01 extends MapActivity{//实现了地图浏览程序
      private MapView  mMapView;
      private MapController mMapController;
      private GeoPoint mGeoPoint;

      public void onCreate(Bundle savedInstanceState){
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       mMapView = (MapView) findViewById(R.id.MapView01);
  
        //mMapView.setTraffic(true);//设置为交通模式 
       mMapView.setSatellite(true);//设置为卫星模式   
        //mMapView.setStreetView(false);//设置为街景模式 
       mMapController = mMapView.getController(); //取得MapController对象(控制MapView),用于设置地图显示的地点以及放大倍数
       mMapView.setEnabled(true);
       mMapView.setClickable(true);  
       mMapView.setBuiltInZoomControls(true); //设置地图支持缩放  
       mGeoPoint = new GeoPoint((int) (30.659259 * 1000000), (int) (104.065762 * 1000000));//构建一个GeoPoint来表示地点的经度和纬度,此设置起点为成都  
       mMapController.animateTo(mGeoPoint); //定位到成都,通过animateTo将地图定位到指定的GeoPoint上 
       mMapController.setZoom(12); //设置倍数(1-21)
        //添加Overlay,用于显示标注信息。
       MyLocationOverlay myLocationOverlay = new MyLocationOverlay();
       List<Overlay> list = mMapView.getOverlays();
       list.add(myLocationOverlay);
      }
      protected boolean isRouteDisplayed(){
       return false;
      }
      class MyLocationOverlay extends Overlay{//如果需要在地图上标注一下图标文字等信息,可以使用Overlay。
                 首先要将地图上的经度和纬度转换成屏幕上实际的坐标,才能将信息绘制上去。
       public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when){
        super.draw(canvas, mapView, shadow);//首先需要实现Overlay中的draw方法才能在地图上绘制信息
        Paint paint = new Paint();
        Point myScreenCoords = new Point();   
        mapView.getProjection().toPixels(mGeoPoint, myScreenCoords);// 可以通过toPixels(GeoPoint in,Point out)方法,将经纬度转换成实际屏幕坐标
        paint.setStrokeWidth(1);
        paint.setARGB(255, 255, 0, 0);
        paint.setStyle(Paint.Style.STROKE);
        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.home);
        canvas.drawBitmap(bmp, myScreenCoords.x, myScreenCoords.y, paint);
        canvas.drawText("天府广场", myScreenCoords.x, myScreenCoords.y, paint);
        return true;
       }
      }
     }
    第二例 实现了定位系统
     全球定位系统(Global Positioning System,GPS)又称为全球卫星定位系统,是一个中距离圆型轨道卫星导航系统,它可以为地球表面的绝大部分地区(98%)提供准确的定位、
     测速和高精度的时间标准。
     Android中关于地理定位系统的API全部位于android.location包中。包括如下几个重要类:
      LocationManager 此类包含了访问定位服务的功能,获取最佳定位提供者的功能,临近警报功能也可以借助该类来实现。
      LocationProvider 该类是定位提供者的抽象类。定位提供者具备周期性报告设备地理位置的功能。
      LocationListener 提供定位信息发生改变时的回调功能。必须先在定位管理器中注册监听器对象。
      Criteria 该类使得应用能够通过在LocationProvider中设置的属性来选择合适的定位提供者。
      Geocoder 用于处理地理编码和反向地理编码的类。地理编码是指将地址或其他描述转变为经度和纬度,反向地理编码则是将经度和纬度转变为地址或描述语言,其中包含
        了两个构造函数,需要传入经度和纬度的坐标。getFromLoction方法可以得到一组关于地址的数组。
     
     此例实现了自动通过定位系统获取用户当前的坐标,然后加载并显示地图,将坐标信息显示在一个TextView
     main.xml文件
     <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="vertical"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       >
       <TextView 
        android:id="@+id/TextView01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello"
       />
       <com.google.android.maps.MapView
        android:id="@+id/MapView01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:apiKey="0dYpmIXGIdwiVm-HEpzuUW2fjNYsFQ9EvYir1sg"/>
      </LinearLayout>

     AndroidManifest.xml
     <?xml version="1.0" encoding="utf-8"?>
      <manifest
       xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.yarin.android.Examples_09_04"
       android:versionCode="1"
       android:versionName="1.0">
       <application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        <uses-library android:name="com.google.android.maps" />
        <activity
         android:name=".Activity01"
         android:label="@string/app_name">
         <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
        </activity>
       </application>
       <uses-permission android:name="android.permission.INTERNET"/>//要使用API 需添加下例权限
       <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
       <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
       <uses-sdk android:minSdkVersion="5" />
      </manifest>
     
     public class Activity01 extends MapActivity {
      public MapController mapController;
      public MyLocationOverlay myPosition;
      public MapView myMapView;
      private static final int ZOOM_IN=Menu.FIRST;
      private static final int ZOOM_OUT=Menu.FIRST+1;

      public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       
       LocationManager locationManager;//取得LocationManager位置管理器实例
       String context=Context.LOCATION_SERVICE;
       locationManager=(LocationManager)getSystemService(context);//要使用地理定位,首先需要取得LocationManager的实例,可以通过getSystemService()方法获得。
                通过此实例我们可以获得一个位置提供者的列表。在一个真实的手持设备中,这个列表包含了一些GPS服务。
                当然我们也可以得到更强大、更精确、不带有其他附件服务的GPS 代码如:
                 LocationManager locationManager = (LocationManager)getSystemService(Context.LOC-ATION_SERVICE);
       myMapView=(MapView)findViewById(R.id.MapView01);      
       mapController=myMapView.getController();//取得MapController实例,控制地图
       //设置显示模式
       myMapView.setSatellite(true);
       myMapView.setStreetView(true);
      
       myMapView.displayZoomControls(false);  //设置缩放控制,这里我们自己实现缩放菜单 
       //设置使用MyLocationOverlay来绘图
       mapController.setZoom(17);
       myPosition=new MyLocationOverlay();
       List<Overlay> overlays=myMapView.getOverlays();
       overlays.add(myPosition);
       
       Criteria criteria =new Criteria();//设置Criteria(服务商)的信息
       //经度要求
       criteria.setAccuracy(Criteria.ACCURACY_FINE);
       criteria.setAltitudeRequired(false);
       criteria.setBearingRequired(false);
       criteria.setCostAllowed(false);
       criteria.setPowerRequirement(Criteria.POWER_LOW);
       //取得效果最好的criteria
       String provider=locationManager.getBestProvider(criteria, true);
       //得到坐标相关的信息
       Location location=locationManager.getLastKnownLocation(provider);      
       updateWithNewLocation(location);//更新坐标    
       locationManager.requestLocationUpdates(provider, 3000, 0,locationListener); //注册一个周期性的更新,第一参数设置服务提供者,第二个参数设置3000ms更新一次,
                      重点是第四个参数locationListener用来监听定位信息的改变 所以必须实现以下几个方法:
                     onLocationChanged(Location location);当坐标改变时触发此函数,如果Provider传进相同坐标,它就
                              不会触发。
                     onProviderDisabled(String provider);Provider禁用时触发此函数,比如GPS被关闭
                     onProviderEnabled(String provider);Provider启用时触发此函数,比如GPS被打开
                     onStatusChanged(String provider,int status,Bundle extras);Provider的转态在可用,暂时不可用和无服务
                                   状态直接切换时触发此函数                        
      }
      private void updateWithNewLocation(Location location) {
       String latLongString;
       TextView myLocationText = (TextView)findViewById(R.id.TextView01);    
       String addressString="没有找到地址\n";      
       if(location!=null){         
        myPosition.setLocation(location);//为绘制标志的类设置坐标         
        Double geoLat=location.getLatitude()*1E6; //取得经度和纬度
        Double geoLng=location.getLongitude()*1E6;
          
        GeoPoint point=new GeoPoint(geoLat.intValue(),geoLng.intValue()); //将其转换为int型
        //定位到指定坐标
        mapController.animateTo(point);
        double lat=location.getLatitude();
        double lng=location.getLongitude();
        latLongString="经度:"+lat+"\n纬度:"+lng;
           
        double latitude=location.getLatitude();
        double longitude=location.getLongitude();
          
        Geocoder gc=new Geocoder(this,Locale.getDefault()); //更具地理环境来确定编码
        try{
         //取得地址相关的一些信息\经度、纬度
         List<Address> addresses=gc.getFromLocation(latitude, longitude,1);//使用LocationManager和位置提供者进行getFromLocation的调用返回一个Location对象形式的快照
                          如果调用getFromLocationName方法可能返回一个表示一个地方名称的数据
         StringBuilder sb=new StringBuilder();
         if(addresses.size()>0){
          Address address=addresses.get(0);
          for(int i=0;i<address.getMaxAddressLineIndex();i++)
           sb.append(address.getAddressLine(i)).append("\n");                       
           sb.append(address.getLocality()).append("\n");
           sb.append(address.getPostalCode()).append("\n");
           sb.append(address.getCountryName());
           addressString=sb.toString();
         }
        }catch(IOException e){}
       }else{
        latLongString="没有找到坐标.\n";
       }    
       myLocationText.setText("你当前的坐标如下:\n"+latLongString+"\n"+addressString); //显示
      }
      private final LocationListener locationListener=new LocationListener(){    
       public void onLocationChanged(Location location){//当坐标改变时触发此函数
        updateWithNewLocation(location);
       }     
       public void onProviderDisabled(String provider){ //Provider被disable时触发此函数,比如GPS被关闭
        updateWithNewLocation(null);
       }     
       public void onProviderEnabled(String provider){ //Provider被enable时触发此函数,比如GPS被打开
       }      
       public void onStatusChanged(String provider,int status,Bundle extras){ //Provider的转态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
       }
      };
      protected boolean isRouteDisplayed(){
       return false;
      }  
      public boolean onCreateOptionsMenu(Menu menu){ //为应用程序添加菜单
       super.onCreateOptionsMenu(menu);
       menu.add(0, ZOOM_IN, Menu.NONE, "放大");
       menu.add(0, ZOOM_OUT, Menu.NONE, "缩小");
       return true;
      }
      public boolean onOptionsItemSelected(MenuItem item){
       super.onOptionsItemSelected(item);
       switch (item.getItemId()){
        case (ZOOM_IN):    
         mapController.zoomIn();//放大 通过MapController地图控制器来放大和缩小视图
         return true;
        case (ZOOM_OUT):    
         mapController.zoomOut();//缩小
         return true;
       }
       return true;
      }  
      class MyLocationOverlay extends Overlay{
       Location mLocation;  
       public void setLocation(Location location){//在更新坐标时,设置该坐标,一边画图
        mLocation = location;
       }
       public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when){
        super.draw(canvas, mapView, shadow);
        Paint paint = new Paint();
        Point myScreenCoords = new Point();
        // 将经纬度转换成实际屏幕坐标
        GeoPoint tmpGeoPoint = new GeoPoint((int)(mLocation.getLatitude()*1E6),(int)(mLocation.getLongitude()*1E6));
        mapView.getProjection().toPixels(tmpGeoPoint, myScreenCoords);
        paint.setStrokeWidth(1);
        paint.setARGB(255, 255, 0, 0);
        paint.setStyle(Paint.Style.STROKE);
        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.home);
        canvas.drawBitmap(bmp, myScreenCoords.x, myScreenCoords.y, paint);
        canvas.drawText("Here am I", myScreenCoords.x, myScreenCoords.y, paint);
        return true;
       }
      }
     }
    如果我们在模拟器上测试,要人为设置一个坐标。可用通过两种方法来设置一个模拟器的坐标值。
    第一种方法通过DDMS,我们可以在Eclipse的ADT插件中使用这种方法。步骤:Window---Show View---Emulator Control ---然后手动或通过KML和GPX文件来设置一个坐标
    第二种方法使用geo命令,需要telnet到本机的5554端口,然后输入类似于geo fix-121.45356 46.51119 4392这样的命令,后面3个参数代表了经度、纬度和(可选的)海拔。设置
    后模拟器上便多出个标志。

    
    
    
    
    
    
  

你可能感兴趣的:(编程,android,api,Google,layout,encoding)