Android平台架构及特性

Android平台架构及特性

  Android系统的底层是建立在Linux系统之上,改平台由操作系统、中间件、用户界面和应用软件四层组成,它采用一种被称为软件叠层(Software Stack)的方式进行构建。

好处:这种软件叠层结构使得层与层互相分离,明确各层的分工,这种分工保证了层与层之间的低耦合,当下层内或者层下发生改变时,上层应用程序无需任何改变。

下图显示Android系统的体系结构:

 

1.应用程序层(Application)

  Android平台不仅仅是操作系统,也包含了许多应用程序,诸如SMS短信客户端程序、电话拨号程序、图片浏览器、Web浏览器等应用程序。这些应用程序都是用Java语言编写的,并且这些应用程序都是可以被开发人员开发的其他应用程序所替换,这点不同于其他手机操作系统固化在系统内部的系统软件,更加灵活和个性化。我们编写的主要是这一层上的应用程序。

2.应用程序架构层(Application Framework)

    应用程序框架层是我们从事Android开发的基础,很多核心应用程序也是通过这一层来实现其核心功能的,该层简化了组件的重用,开发人员可以直接使用其提供的组件来进行快速的应用程序开发,也可以通过继承而实现个性化的拓展。Android应用程序框架提供了大量的API供开发者使用。

  a) Activity Manager(活动管理器)

              管理各个应用程序生命周期以及通常的导航回退功能

      b) Window Manager(窗口管理器)

              管理所有的窗口程序

      c)  Content Provider(内容提供器)

              使得不同应用程序之间存取或者分享数据

      d) View System(视图系统)

              构建应用程序的基本组件

      e) Notification Manager(通告管理器)

              使得应用程序可以在状态栏中显示自定义的提示信息

       f) Package Manager(包管理器) 

              Android系统内的程序管理

       g)Telephony Manager(电话管理器)

              管理所有的移动设备功能

       h)Resource Manager(资源管理器)

              提供应用程序使用的各种非代码资源,如本地化字符串、图片、布局文件、颜色文件等

        i)Location Manager(位置管理器)

             提供位置服务

        j)XMPP Service(XMPP服务)

             提供Google Talk服务

3.系统运行库层:

  1)函数库(Libraries)

    函数是应用程序框架的支撑,是连接应用程序框架层与Linux内核层的重要纽带。一般来说,Android应用开发者不能直接调用这套C/C++库集,但可以通过上面的应用程序框架来调用这些库。

  下面列出一些核心库:

    a)系统C库( Libc):

      从BSD继承来的标准C系统函数库,专门为基于embedded linux的设备定制。

    b)Surface Manager:

      执行多个应用程序时候,负责管理显示与存取操作间的互动,另外也负责2D绘图与3D绘图进行显示合成.

    c) SGL

      底层的2D图形渲染引擎

    d) SSL

       在Andorid上通信过程中实现握手

    e) Media Framework

       多媒体库,基于PacketVideo OpenCore;支持多种常用的音频、视频格式录制和回放,编码格式包括MPEG4、MP3、H.264、AAC、ARM

      f) WebKit:

                  一套网页浏览器的软件引擎

           g)  OpenGL|ES:

                  根据OpenGL ES 1.0API标准实现的3D绘图函数库

           h)  SQLite:

                  小型的关系型数据库引擎

      2)Android运行时(Android Runtime):

    Android应用程序时采用Java语言编写,程序在Android运行时中执行,其运行时分为核心库和Dalvik虚拟机两部分。

   @  核心库

                 核心库提供了Java语言API中的大多数功能,同时也包含了Android的一些核心API,如android.os、android.net、android.media等等。

   @  Dalvik虚拟机

   Dalvik虚拟机非常适合在移动终端上使用,相对于在PC或者服务器上运行的虚拟机而言,Dalvik虚拟机不需要很快的CPU计算速度和大量的内存空间,它主要有以下两个特点:

   (1)运行专有的.dex文件。

   专有的.dex文件减少了.class文件中的冗余信息,而且会把.class文件整合到一个文件中,从而提高了运行性能;而且DX工具还会对.dex文件进行一些性能上的优化。

   (2)基于寄存器实现.

        大多数虚拟机包括JVM都是基于栈的,而Dalvik虚拟机则是基于寄存器的。一般来说基于寄存器的虚拟机具有更好的性能表现,但在硬件通用性上略差。

    JVM和Dalvik的区别:由于Android应用程序的编写语言是java,因此有人会把它们搞混。但实际上Dalvik并未遵守JVM规范,两者也不兼容。

    JVM运行的是java字节码(通常就是.class文件),但Dalvik运行的是其专有的dex(Dalvik Executable)文件。

      JVM直接从.class文件或者JAR包中加载字节码后运行;而Dalvik则无法直接从.class文件或者JAR包中加载字节码,他需要将应用程序的所有的.class文件编译成.dex文件,Dalvik则运行该.dex文件。

    2.Linux内核(Linux kernel)

  Android系统建立在Linux2.6之上,Linux内核提供了安全性、内存管理、进程管理、网络协议栈和驱动模型等核心系统业务,除此之外,Linux内核也是系统硬件和软件叠层之间的抽象层。

Android开发--Activity生命周期回顾理解

Activity和Servlet一样,都用了回调机制。我们通过类比servlet来学习Activity。当一个servlet开发出来之后,该servlet运行于Web服务器中。服务器何时创建servlet的实例,何时调用servlet的方法向用户生成响应,程序员无法控制,这种回调由服务器自行决定。Activity也一样,被开发出来,开发者只要在AndroidManifest.xml文件配置该Activity即可。至于该Activity何时被实例化,它的方法何时被调用,对开发者来说完全是透明的。

当开发者开发一个Servlet时,根据不同的需求场景,可能需要选择性的的实现如下方法:

  • init(servletConfig config)
  • destroy()
  • doGet(HttpServletRequest req,HttpServletResponse resp)
  • doPost(HttpServletRequest req,HttpServletResponse resp)
  • sevice(HttpServletRequest req,HttpServletResponse resp
  • 当把Servlet部署到Web应用中之后,Web服务器将会在特定的时刻,调用该Servlet上面的各种方法---这种调用就被称为回调。

Activity的回到机制与此类似,当Activity被部署到Android应用之后,随着应用程序的运行,Activity会不断的在不同的状态进行切换,该activity中特定的方法就会被回调-----开发者就可以选择性的重写这些方法来加入业务相关的处理。Android运行过程的不同状态被称为生命周期。

Android的生命周期:当activity处于Android的应用中的运行时,它的活动状态由Android运行时以Activity栈的形式管理。当前活动的Activity位于栈顶。

Android的生命周期演示:android大致经过如下四个状态:

  • 活动状态:当前Activity位于前台,用户可见,可以获得焦点。
  • 暂停状态:其他Activity位于前台,该Activity依然可见,只是不能获得焦点。
  • 停止状态:该Activity不可见,失去焦点
  • 销毁装填:该activity结束,或者activity所在的Dalvik进程被结束。

下面是官方API所提供的生命周期图:

 

下面使用代码亲自测下Android的生命周期,测完就明白了:

package com.lp.ecjtu.activitydemo1;


import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.EditText;

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private EditText editText;
//创建Activity被回调
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = (EditText) findViewById(R.id.editText);
        Log.e(TAG, "Start onCreate =========");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    //启动Activity被回调
    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Log.e(TAG, "Start onStart =========");
    }
    //重新启动Activity被回调
    @Override
    protected void onRestart() {
        // TODO Auto-generated method stub
        super.onRestart();
        Log.e(TAG, "Start onRestart =========");
    }
    //恢复Activty被回调
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        Log.e(TAG, "Start onResume =========");
    }
    //暂停Activity被回调
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        Log.e(TAG, "start onPause=============");
    }    
    //停止Activity被回调
    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        Log.e(TAG, "start onStop=============");
    }
    //销毁Activity被回调
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.e(TAG, "start onDestroy=============");
    }

}

运行上面的代码:我们打开应用程序时回调了OnCreate()-->onStart()-->onResume()方法。在LogCat窗口可以看到:

Back键:当我们按返回键的时候这个应用程序或者Activity将结束,依次回调了OnPause()-->onStop()-->Ondestroy()方法:在LogCat窗口可以看到:

HOME键:当我们正在打游戏的时候,突然来了条短信,我们想看短息,按HOME键,然后打开短信的应用,当我们按HOME键的时候Activity先后执行了OnPause()-->OnStop方法,在LogCat窗口可以看到:

而我们看完短息在启动应用的时候:会执行OnRestart()-->onStart-->OnResume方法。在LogCat窗口可以看到:

 

通过上面的操作,想必我们都对Android Activity生命周期有了深刻的了解,我们就可以在开发Activity的时候,选择性的重写生命周期的方法来解决业务上的一些需求。

例如:下面的这个例子,当我们在看视屏的时候,或者在注册的时候,刚好填完用户的注册信息,不小心按到了Home键,当我们在进入应用程序的时候,发现之前填的注册信息全没了,这时候我们就要哭了,说明这个应用程序做的比较垃圾。正常情况下,我们之前填写的注册信息还在,也就是说和我们按Home键之前的状态是一致的。

为了理解,我们用一个小例子说明问题:

在XML代码代码中增加EditText:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" 
    android:orientation="vertical">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_Activity" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:ems="10" />

</LinearLayout>

java代码不变,运行程序,在EditText中输入peter,

然后按HOME键,在次启动MainActivity,发现之前输入的内容没了。

这显然不是正常的应用程序,我们都会哭的。那么就需要我们队生命周期非常了解了,当我们按Home键的时候,Activity回调了onPause-->OnStop()方法,再次进入应用程序的时候回调了OnRestart-->OnStart-->onResume()方法,说明我们只要在onPause()和OnRestart方法里面做处理既可以保存之前的状态:下面看代码

package com.lp.ecjtu.activitydemo1;


import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.EditText;

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private EditText editText;
    //定义一个String字符串用于存放用户输入的字符串
    private String userString;
    //创建Activity被回调
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = (EditText) findViewById(R.id.editText);
        Log.e(TAG, "Start onCreate =========");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    //启动Activity被回调
    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Log.e(TAG, "Start onStart =========");
    }
    //重新启动Activity被回调
    @Override
    protected void onRestart() {
        // TODO Auto-generated method stub
        super.onRestart();
        //再次启动应用时,把先前用户输入的值重新设置EditText
        editText.setText(userString);
        Log.e(TAG, "Start onRestart =========");
    }
    //恢复Activty被回调
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        Log.e(TAG, "Start onResume =========");
    }
    //暂停Activity被回调
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        //按home键的时候,保存用户输入的字符串信息。
        userString = editText.getText().toString();
        Log.e(TAG, "start onPause=============");
    }    
    //停止Activity被回调
    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        Log.e(TAG, "start onStop=============");
    }
    //销毁Activity被回调
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.e(TAG, "start onDestroy=============");
    }

}

重新启动app,按home键,在进入应用程序OK了,看下面的图:

总结:理解生命周期的关键是,我们可以在开发过程选择性的重写生命周期中的方法,解决一些实际问题,这才是关键,学以致用!

Notification定义与应用

首先要明白一个概念:

Intent 与 PendingIntent 的区别:

  Intent:是意图,即告诉系统我要干什么,然后做Intent应该做的事,而intent是消息的内容

  PendingIntent 为Intent的包装,这里是启动Intent的描述,PendingIntent.getActivity 返回的PendingIntent表示,此PendingIntent实例中的Intent是用于启动 Activity 的Intent。PendingIntent.getActivity的参数依次为:Context,发送者的请求码(可以填0),用于系统发送的 Intent,标志位。

  包装Intent,intent是我们直接使用startActivity,startService,senbBroadcast启动某项工作的内容,而某些时候我们并不能直接调用 startActivity,startService,senbBroadcast,而是系统或者程序达到某一条件才发送intent,例如下面要学习的Notification,当用户点击Notification之后,由系统发出一条activity的intent。如果我们不用某种方法告诉系统的话,系统是不知道是使用startActivity(),startService还是senbBroadcast...来启动intent的,因此需要PendingIntent,对intent进行包装,调用getActivity()方法。

 

前面我们说过,NotificationManager是所有Notification的大管家,它的主要职责是加入/移除Notification。

NotificationManager类

   通过获取系统服务来获取该对象:

      NotificationManager mNotificationManager = (NotificationManager)getSystemServic(Context.NOTIFICATION_SERVICE) ;

 

  常用方法:

        public  void cancelAll()                  移除所有通知         (只是针对当前Context下的Notification)

        public  void cancel(int id)              移除标记为id的通知 (只是针对当前Context下的所有Notification)

        public  voidnotify(String tag ,int id, Notification notification)              将通知加入状态栏, 标签为tag,标记为id

        public  void notify(int id, Notification notification)                                 将通知加入状态栏,,标记为id

一般来说, 一个Notification应该传送的消息包括:

                 1 、一个状态条图标        

                 2、在拉伸的状态栏窗口中显示额外的信息和启动一个Application的Intent 

                 3、闪灯或LED

                 4、电话震动 

         在状态栏(Status Bar)中,通知主要有两类(使用FLAG_标记,后面讲解到):

                 1、正在运行的事件

                 2、通知事件 

Notification类介绍:

         常量

              //表示发送一个Notification的所携带的效果

             DEFAULT_ALL              使用默认字段

             DEFAULT_LIGHTS       默认闪光

             DEFAULT_SOUND      默认声音(uri,指向路径)

             DEFAULT_VIRATE       默认震动,后来得知需要添加震动权限VIBRATE: android.permission.VIBRATE

   其中震动和闪光都需要在AndroidManifest.xml中添加权限

    <!-- 添加操作闪光灯的权限 -->
      <uses-permission android:name="android.permission.VIBRATE"/>
      <!-- 添加操作震动的权限 -->
      <uses-permission android:name="android.permission.FLASHLIGHT"/>

          PS:以上的效果常量可以累加,即通过mNotifaction.defaults |=DEFAULT_SOUND   (有些效果只能在真机上才有,比如震动)

            //设置Flag位

            FLAG_AUTO_CANCEL           该通知能被状态栏的清除按钮给清除掉

            FLAG_NO_CLEAR                  该通知不能被状态栏的清除按钮给清除掉

            FLAG_ONGOING_EVENT      通知放置在正在运行

常用字段  

           contentView                  通知在状态栏的显示View(自定义,具体请看下文) ,常与contentIntent配合使用,点击该通知后,

                                          即触发contentIntent 

           contentIntent                 设置PendingIntent对象,点击该通知时发送该Intent

           flags                                  设置flag位,例如FLAG_NO_CLEAR等

           defaults                             添加效果 

           tickerText                        显示在状态栏中的文字

           when                               发送此通知的时间戳

           icon                                  设置图标

    常用方法介绍

       void setLatestEventInfo(Context context , CharSequence contentTitle,CharSequence  contentText,PendingIntent contentIntent)    

        功能: 显示在拉伸状态栏中的Notification属性,点击后将发送PendingIntent对象。

            参数: context             上下文环境

                      contentTitle      状态栏中的大标题

                      contentText      状态栏中的小标题

                      contentIntent    点击后将发送PendingIntent对象

        另外的就是Notification的几步不同构造方法了,其构造方法的参数含义如上,请参考SDK 。

 注意,关于通知(Notification)的显示类型有两种:

              第一种:使用默认的形式(效果图如上显示)。具体使用是为Notification对象设置setLatestEventInfo()方法(该方法内部创建

                           了默认的RemoteViews对象,因此为默认显示),否则程序会报异常 ;

              第二种:   使用自定义的View(RemoteViews对象)显示(功能更加自由,强大),具体方法为设置Notification对象的

                        contentView 属性和contentIntent属性 ,此时不需要设置setLatestEventInfo()方法。具体使用方法如下:

    第一种:例子:main.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="fill_parent"
        android:orientation="vertical" >

      <TextView
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="@string/hello" />
       <Button android:id="@+id/showButton"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="showNotification"/>
       <Button android:id="@+id/cancelButton"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="cancelNotification"/>
  </LinearLayout>

Intent.FLAG_ACTIVITY_CLEAR_TOP :如果在当前Task中,有要启动的Activity,那么把该Acitivity之前的所有Activity都关掉,并把此Activity置前以避免创建Activity的实例

Intent.FLAG_ACTIVITY_NEW_TASK :系统会检查当前所有已创建的Task中是否有该要启动的Activity的Task,若有,则在该Task上创建Activity,若没有则新建具有该 Activity属性的Task,并在该新建的Task上创建Activity。更多请参见 “ (转载)Android下Affinities和Task ”

 

NotificationDemoActivity.java

 package com.lp.ecjtu;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class NotificationDemoActivity extends Activity implements OnClickListener {
    /** Called when the activity is first created. */
    private Context mContext;
    private Button showButton,cancelButton;
    private Notification mNotification;
    private NotificationManager mNotificationManager;
    private static final int NOTIFICATION_ID = 0x0001;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setupViews();
    }

    private void setupViews() {
        mContext = NotificationDemoActivity.this;
        showButton = (Button) findViewById(R.id.showButton);
        cancelButton = (Button) findViewById(R.id.cancelButton);
        mNotification = new Notification(R.drawable.ic_launcher, "this is Notification", System.currentTimeMillis());
        //将使用 默认的声音来提醒用户,添加震动,后来得知需要添加震动权限 : Virbate Permission  
        //mNotification.defaults = Notification.DEFAULT_SOUND;
        //mNotification.defaults = Notification.DEFAULT_VIBRATE;
        mNotification.defaults = Notification.DEFAULT_LIGHTS;
        mNotificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
        showButton.setOnClickListener(this);
        cancelButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(v==showButton){
            Intent intent = new Intent(mContext, NotificationDemoActivity.class);
            //这里需要设置Intent.FLAG_ACTIVITY_NEW_TASK属性  
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
            PendingIntent mContentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
           //这里必需要用setLatestEventInfo(上下文,标题,内容,PendingIntent)不然会报错.
            mNotification.setLatestEventInfo(mContext, "10000", "您的话费不足,请充值!", mContentIntent);
            //这里发送通知,消息ID,通知对象
            mNotificationManager.notify(NOTIFICATION_ID,mNotification);
        }else if(v==cancelButton){
            mNotificationManager.cancel(NOTIFICATION_ID);
        }
    }
}

别忘了添加震动的权限:

  <!-- 添加操作闪光灯的权限 -->
    <uses-permission android:name="android.permission.VIBRATE"/>

效果图:

第二种:自定义view

代码如下:

view.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"
    android:orientation="horizontal" >

   <ImageView android:id="@+id/image" android:layout_width="wrap_content"  
        android:layout_height="fill_parent" />  
 
    <TextView android:id="@+id/text" android:layout_width="wrap_content"  
        android:layout_toRightOf="@+id/image"  
        android:layout_height="wrap_content" android:textColor="#000" />  
          
    <ProgressBar android:id="@+id/progress_horizontal"  
        style="?android:attr/progressBarStyleHorizontal"   
        android:layout_below="@+id/text"  
        android:layout_toRightOf="@+id/image"  
        android:layout_width="fill_parent" android:layout_height="wrap_content"  
        android:max="100" android:progress="50" android:secondaryProgress="75" />  
 
</RelativeLayout >

java 代码

NotificationRomoteViewActivity.java

 

 package com.lp.ecjtu;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RemoteViews;

public class NotificationRomoteViewActivity extends Activity {
    private Notification mNotification;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        showViewNotification();
    }
    private void showViewNotification() {
        // TODO Auto-generated method stub
          mNotification = new Notification(R.drawable.ic_launcher, "自定义View", System.currentTimeMillis()+10000);
            //1.创建一个自定义布局
            //2.在程序代码中使用RemoteViews的方法来定义image和text。然后把RemoteViews对象传到contentView字段
          mNotification.flags = Notification.FLAG_INSISTENT;
          RemoteViews remoteViews = new RemoteViews(this.getPackageName(), R.layout.view);//自定义Notification
          remoteViews.setImageViewResource(R.id.image, R.drawable.ic_launcher);
          remoteViews.setTextViewText(R.id.text, "自定义View");
          mNotification.contentView = remoteViews;
          // 3、为Notification的contentIntent字段定义一个Intent(注意,使用自定义View不需要setLatestEventInfo()方法)  
          //点击启动setting
          PendingIntent mPendingIntent = PendingIntent.getActivity(NotificationRomoteViewActivity.this,
                                                                      0, new Intent("android.settings.SETTINGS"), 0);
          mNotification.contentIntent = mPendingIntent;
          NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
          mNotificationManager.notify(0, mNotification);
    }
}

Android handler组件等

一、 基础篇

         需要掌握的技能如下:

               1、熟练掌握基本控件以及容器控件的使用 ;

                         常用的基本控件有:Button 、TextView、EditText、ListView等

                         常用的容器控件有:FrameLayout、LinearLayout、RelativeLayout等

               2、熟练掌握相关监听器的注册和使用:

                         常用监听器有: OnClickListener、OnLongClickListener、OnItemClickListener等

               3、掌握Log的使用以及分析方法 ;

               4、掌握Activity、Service的生命周期和使用方法 ;

               5、掌握BroadcastReceiver(广播)的接受和使用   ;

               6、掌握Intent以及IntentFilter的使用   ;

               7、基本掌握数据库方面知识,包括SQLiteDatabase以及ContentProvider的使用方法

  

         除此之外,我们必须得掌握adb shell 的使用方法,常用功能有:

                        adb pull 、  adb push 、 adb remount 指令等

         由于shell类同于Linux shell ,我们还得掌握基本的Linux指令等,例如cat、cd 等 。

 

    知识获取渠道主要为:

                  Android SDK以及网上大牛的博客。

      附: 关于基础知识的介绍,国内的一些书籍质量真是相当差劲,味同嚼蜡。强烈不建议在此阶段买书籍。

    

       这时,您已经小有所成了,能够基本掌握Android开发了。这儿,我推荐一个手把手讲解Android项目的视频:

               zhengping老师讲解的,强烈推荐。

                  视频下载地址:http://www.verycd.com/topics/2847310/

                百度视屏:http://blog.csdn.net/coolszy/

     实践出真知。这个阶段,你可以自己编写一些小Demo了,帮助自己在更深层次发展了。

        PS:我通过看了Mars老师视频后,编写了一个简易的音乐播放器Demo, 感觉挺有成就感的。

  通过前面的学习,我们可以成功进入第二个阶段了。

  二、 提高篇

        需要掌握的技能如下:

                 1掌握Canvas类的使用-- 如何绘图

                 2、掌握消息通信机制---Handler相关类的使用以及原理

                 3、掌握Context类以及实现原理

                 4、掌握View树的绘制流程  。 View绘制流程很重要,掌握它就基本上掌握了Android核心之一了。

                         4.1、掌握触摸事件的分发流程--- onInterceptTouchEvent以及onTouchEvent方法流程

                         4.2、掌握相关监听器的调用机制。例如OnClickListener监听时怎么调用的?

                         4.3、能够编写自定义View以及ViewGroup

                 5、理解Binder机制----Binder机制很重要,Android的进程间通信都是靠它完成的。掌握它,才能够好的完成接下

                    来的学习。

                 6、基本掌握ActivityManagerService类的使用,主要掌握的知识点包括如下:

                          6.1、startActivity()流程,即启动一个Activity的流程  ;

                          6.2、startService()流程,即启动一个Service的流程 ;

                 7、基本掌握PackageManagerService类的使用,主要掌握的知识点包括如下:

                          7.1、开机时如何解析所有已安装应用程序的Apk包的信息

                          7.2、Intent以及IntentFilter的匹配规则以及解析过程

                 8、基本掌握View添加至窗口的过程---即WindowManagerIml 、WindowManagerService类的用法

    知识渠道: 

Android引进的Handler类,可以说是Runnable和Activity交互的桥梁,所有的UI线程要负责View的创建并且维护它,例如更新某个TextView显示的内容,都必须在主线程中去做,我们不能直接在UI线程中创建子线程,要利用消息机制:handler,如下就是handler的简单工作原理图:

下面是一个原理图:

UI线程中去创建子线程,要利用消息机制:handler,如下就是handler的简单工作原理图: 

我们只要在run方法中发送Message,而在Handler里,通过不同的Message执行不同的任务。

package com.lp.ecjtu;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

public class HandlerTestActivity extends Activity {
    //title为setTitle方法提供变量,这里为了方便我设置成了int型  
    private int title=0;
    private Handler mhandler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            // TODO 接收消息并且去更新UI线程上的控件内容
            switch (msg.what) {
            case 1:
                 updateTitle();  
                break;
            }
        }
        
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Timer timer = new Timer();
        timer.schedule(new Mytask(), 1,500);
    }
    private class Mytask extends TimerTask{

        @Override
        public void run() {
            //子线程中通过handler发送消息给handler接收,由handler去更新title
            Message msg = new Message();
            msg.what=1;
            mhandler.sendMessage(msg);
        }
        
    }
    protected void updateTitle() {
        setTitle("welcome to ecjtu:"+title);
        title++;
    }
}

为什么要使用Handlers?

    因为,我们当我们的主线程队列,如果处理一个消息超过5秒,android 就会抛出一个 ANP(无响应)的消息,所以,我们需要把一些要处理比较长的消息,放在一个单独线程里面处理,把处理以后的结果,返回给主线程运行,就需要用的 Handler来进行线程建的通信,关系如下图;

     mainthread

Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear. 面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!

ProgressBar 

下面介绍两种进度条分别是圆形进度条和长形进度条的代表:

下面我们看一下两都皆有之的Android自带的浏览器的效果图如下:

第一步:新建一个Android工程命名为ProgressBarDemo.

 

第二步:修改main.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="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
 <ProgressBar   
         android:id="@+id/rectangleProgressBar"    
         style="?android:attr/progressBarStyleHorizontal" lp_style="?android:attr/progressBarStyleHorizontal"     
         android:layout_width="fill_parent"   
         android:layout_height="wrap_content"  
         android:visibility="gone"  
         />  
     <ProgressBar   
         android:id="@+id/circleProgressBar"    
         style="?android:attr/progressBarStyleLarge" lp_style="?android:attr/progressBarStyleLarge"  
         android:layout_width="wrap_content"   
         android:layout_height="wrap_content"  
         android:visibility="gone"   
         />  
        
     <Button android:id="@+id/button"   
             android:text="Show ProgressBar"    
             android:layout_width="wrap_content"   
             android:layout_height="wrap_content" />
</LinearLayout>   
        
     <Button android:id="@+id/button"   
             android:text="Show ProgressBar"    
             android:layout_width="wrap_content"   
             android:layout_height="wrap_content" />
</LinearLayout>   

第三步:修改ProgressBarDemo.java代码如下:

package com.lp.ecjtu;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class ProgressBarDemoActivity extends Activity {
    /** Called when the activity is first created. */
    private ProgressBar rectangleProgressBar,circleProgressBar;  
    private Button mButton;  
    protected static final int STOP = 0x10000;  
    protected static final int NEXT = 0x10001;  
    private int iCount = 0;  
      
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        rectangleProgressBar = (ProgressBar) findViewById(R.id.rectangleProgressBar);
        circleProgressBar = (ProgressBar) findViewById(R.id.circleProgressBar);
        mButton = (Button) findViewById(R.id.button);
        rectangleProgressBar.setIndeterminate(false);//设置不确定模式下
        circleProgressBar.setIndeterminate(false);
        mButton.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                rectangleProgressBar.setVisibility(View.VISIBLE);
                circleProgressBar.setVisibility(View.VISIBLE);
                rectangleProgressBar.setMax(100);
                rectangleProgressBar.setProgress(0);
                circleProgressBar.setProgress(0);
                //创建一个此线程,每秒步长为5,到100%时停止
                Thread mThread = new Thread(new Runnable() {
                    
                    @Override
                    public void run() {
                        //循环
                        for(int i=0;i<10;i++){
                            try {
                                iCount = (i+1)*10;//步长为10进行增加,直到100
                                Thread.sleep(1000);//1秒
                                //当i=9的时候进度为100,停止
                                if(i==9){
                                    Message msg = new Message();
                                    msg.what=STOP;
                                    mHandler.sendMessage(msg);
                                    break;
                                }else{
                                    Message msg = new Message();
                                    msg.what=NEXT;
                                    mHandler.sendMessage(msg);
                                }
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }//
                            
                        }
                    }
                });
                mThread.start();
            }
        });
    }
    //定义一个Handler
    private Handler mHandler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case STOP:
                rectangleProgressBar.setVisibility(View.GONE);
                circleProgressBar.setVisibility(View.GONE);
                Thread.currentThread().interrupt();//中断线程
                break;
            case NEXT:
                if(!Thread.currentThread().isInterrupted()){//不中断
                    rectangleProgressBar.setProgress(iCount);//设置进度条的状态
                    circleProgressBar.setProgress(iCount);
                }
                break;
            }
        }
        
    };
}

效果图:


Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear. 面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!

Android——横屏和竖屏的切换,以及明文密码的显示

查看API文档: android.content.pm.ActivityInfo

   在手机的使用中,我们要根据不同的需求来改变屏幕的显示方向,一般在浏览信息时是竖屏,在玩游戏的时候就要切换到横屏。在Android中要想完成屏幕方向的切换,需要Activity类的一些方法的支持。

     getRequestedOrientation();取得当前手机屏幕的方向
     setReqestedOrentation(ing requestedOrientation);设置手机屏幕方向
     onConfigurationChanged(Configuration newConfig);系统设置改变时触发此事件(当使用setRequestedOrientation()方法改变了屏幕显示方向后触发此事件,表示 对系统设置改变进行监听,当系统改变之后,对于每一个Activity程序而言都相当于重新加载,如果要对一些组件做操作,就只能通过这个方法来完成)。
     在设置和取得手机屏幕方向的操作中,需要一个int型的操作数据,这个数据由android.content.pm.ActivityInfo类所提供,该类中定义了3个常量
     SCREEN_ORIENTATION_LANDSCAPE :屏幕横屏显示,表示数值为0
     SCREEN_ORIENTATION-PROTRAIT:屏幕竖屏显示,表示数值为1
     SCREEN_ORIENTATION_UNSPECIFIED:未指定的屏幕显示,表示数值为-1
有时候,我们在输入密码的时候为了确保输入的密码正确,希望可以以明文的方式来显示输入的密码,而不是*代替,此功能就可以借助EditText的setTransformationMethod()方法来完成,
   密文显示:android.text.method.HideReturnsTransformationMethod
   明文显示:android.text.method.PasswordTransformationMethod
 
当复选框选中和不选中的时候,密码明文和密文进行显示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
showPass =(CheckBox) this.findViewById(R.id.showpass);
        showPass.setOnCheckedChangeListener(new OnCheckedChangeListener() {
 
            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) {
                if (isChecked == true) {
                    // 如果复选框被选中,文本框内容可见
                    LoginGalleryActivity.this.userpass
                            .setTransformationMethod(HideReturnsTransformationMethod
                                    .getInstance());
                } else {
                    //如果复选框没有被选中,文本框内容不可见
                    LoginGalleryActivity.this.userpass
                            .setTransformationMethod(PasswordTransformationMethod
                                    .getInstance());
                }
            }
        });
 

下面就是横屏和竖屏的显示功能的实现了,由于横屏和竖屏的切换会引起系统配置的改变,我们还需要在Manifest.xml中进行声明

如图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
chageScrean = (Button) this.findViewById(R.id.screanChange);
        //改变屏幕显示为横屏或竖屏
        chageScrean.setOnClickListener(new OnClickListener() {
 
            @Override
            public void onClick(View v) {
                if (ShowGallery.this.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
                    chageScrean.setText("错误,无法改变屏幕方向");
                     
                } else if (ShowGallery.this.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                    ShowGallery.this.setRequestedOrientation(1);//设置当期屏幕为竖屏
                }else if(ShowGallery.this.getRequestedOrientation()==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                {
                    ShowGallery.this.setRequestedOrientation(0);//设置当前屏幕为横屏
                }
            }
        });
1
2
3
4
5
6
7
8
9
10
11
12
13
//系统设置改变时触发该方法,还需要在Manifest.xml文件中进行配置
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
      if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE)
      {
          ShowGallery.this.chageScrean.setText("改变屏幕方向为竖屏(当前为横屏)");
      }
      else if(newConfig.orientation==Configuration.ORIENTATION_PORTRAIT)
      {
          ShowGallery.this.chageScrean.setText("改变屏幕方向为横屏(当前为竖屏)");
      }
      super.onConfigurationChanged(newConfig);
  }

下面是横竖屏测试的程序:

我们这里主要是运用了getRequestedOrientation(),和setRequestedorientation()两个方法.但是要利用这两个方法必须先在AndroidManiefst.xml设置一下屏幕方属性,不然程序将不能正常的工作.

 

Step 1:我们建立一个Android工程,命名为ChangeScreemOrientationDemoActivity.

 

Step 2:设计UI,打开main.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="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <Button android:id="@+id/press"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="press me change screem orientation"/>

</LinearLayout>

Step 3:设计主程序ChangeScreemOrientationDemoActivity.java,修改其代码如下:

package com.lp.ecjtu;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ChangeScreemOrientationDemoActivity extends Activity {
    /** Called when the activity is first created. */
    private Button pressBtn;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        pressBtn = (Button) findViewById(R.id.press);
        pressBtn.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                //如果是竖屏,改为横屏
                if(getRequestedOrientation()== ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                }
                //如果是横屏,改为竖屏
                else if(getRequestedOrientation()==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                }
            }
        });
    }
}

 

Step 4:在AndroidManifest.xml文件里设置默认方向,不然程序不能正常工作哦.代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.android.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ChangeOrientationDemo"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="3" />

</manifest>

 

现在我们上网几乎都会用百度或者谷歌搜索信息,当我们在输入框里输入一两个字后,就会自动提示我们想要的信息,这种效果在Android 里是如何实现的呢? 事实上,Android 的AutoCompleteTextView Widget ,只要搭配ArrayAdapter 就能设计同类似Google 搜索提示的效果.

本例子先在Layout 当中布局一个AutoCompleteTextView Widget ,然后通过预先设置好的字符串数组,将此字符串数组放入ArrayAdapter ,最后利用AutoCompleteTextView.setAdapter 方法,就可以让AutoCompleteTextView 具有自动提示的功能.例如,只要输入ab ,就会自动带出包含ab 的所有字符串列表.

package com.lp.ecjtu;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;

public class AutoCompleteTextViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
      //定义字符串数组,作为提示的文本
        String[] books = new String[]{
            "疯狂Java讲义",
            "疯狂Ajax讲义",
            "疯狂XML讲义",
            "疯狂Workflow讲义"
        };
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            //创建一个ArrayAdapter,封装数组
            ArrayAdapter<String> aa = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_dropdown_item_1line,
                books);
            //获得AutoCompleteTextView组件
            AutoCompleteTextView actv = (AutoCompleteTextView)
                findViewById(R.id.auto);
            //设置Adapter
            actv.setAdapter(aa);
        }
    }

<?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="fill_parent"
    android:orientation="vertical" >

<!-- 定义一个自动完成文本框
    ,指定输入一个字符后进行提示 -->
<AutoCompleteTextView  
    android:id="@+id/auto"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:completionHint="请选择您喜欢的图书:"
    android:dropDownHorizontalOffset="20dp"
    android:completionThreshold="1"
    />
</LinearLayout>

java Android SDK安装与环境变量配置以及开发第一个Android程序

JAVA的安装与环境变量的配置

1、先下载JAVA,并且安装。 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u3- download-1501626.html

2、安装的时候,最好别改安装路径,默认路径一直点下一步即可!

3、安装完成后,接下来就是配置java环境变量了。

4、打开计算机属性,点击高级系统设置

5、选择“高级”-“环境变量”

 

二、  关于JDK 安装,以及Java环境的设置

1、下载JDK1.6,选择对应的安装路径

 

2、配置相应的Java 环境变量

 

A、属性名称:JAVA_HOME

    属性值:C:\Program Files\Java\jdk1.6.0_02

B、属性名称:PATH

    属性值:;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin

C、属性名称:CLASSPATH

    属性值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar

    要加.表示当前路径,另外,%JAVA_HOME%就是引用前面指定的JAVA_HOME

6. 关于环境变量是否安装成功的测试

“开始”->;“运行”,键入“cmd”;

  键入命令命令,出现画面,说明环境变量配置成功:

         A、java -version;

         B、java;

         C、javac;

=================华==丽==的==分==割==线======================

Android SDK的安装与环境变量配置

一、配置Andriod环境变量

1、下载Android SDK,点击安装,直接默认路径即可! 下载地址:http://developer.android.com/sdk/index.html

2、默认路径安装后,安装完成,开始配置环境变量。

3、打开计算机属性——高级系统设置——环境变量(如上文)

4、新建一个环境变量,变量名:ANDROID_HOME,变量值:D:\Program Files\android-sdk-windows(以你安装目录为准,确认里面有tools和add-ons等多个文件夹),点击确认。

5、在用户变量PATH后面加上变量值;%ANDROID_HOME%\platform-tools;点击确认即可。 在系统变量path中添加;D:\Program Files\android-sdk-windows\tools

6、Android SDK配置完成,接下来验证配置是否成功。

7、点击运行——输入cmd——回车——输入adb——回车,如果出现一堆英文,如下图所示,即表示配置成功,在输入Android,启动Android SDK Manager。

二、下载和安装Andriod SDK

1.SDK下载

    去http://www.android.com/ 在那个页面中有developers链接,点击后链接到developer.android.com网站上,如下图,下载相应的sdk版本就是了,由于我的电脑的操作系统是windows,所以我直接在选择了android-sdk_r12-windows(图中有标识).

image

下载完成后,解压后得到android-sdk-windows文件夹,该文件夹包含如下文件结构:

(1)add-ons:该目录存放额外的附件软件。刚解压时该目录为空。

(2)platforms:该目录存放不同版本的Android版本。刚解压时该目录为空。

(3)tools:该目录存放大量的Android开发,调试工具

(4)SDK Manager.exe:该程序就是Andriod SDK管理器。

(5)AVD Manager.exe:该程序就是Andoid虚拟设备。

(6)docs:该文件夹存放了Android SDK开发文件和API文档等

(7)platforms-tools:该文件夹存放Android平台和相关工具

(8)samples:该文件夹存放不同的Android平台和示例程序。

2.安装sdk开发使用的相应的包  

   运行之后安装了sdkmanager,然后sdkmanager启动后会去android仓库去取还未安装的包的信息,如下图(由于我的系统中已安 装好,因此每个包前面都是绿色打勾的),为了偷懒,我直接就选择了accept all,将所有的包安装上.其实,如果自己对android整个体系比较了解的话,可以选择只安装自己需要用到的部分.

 

三、在eclipes中配置和安装ADT(Android Development Tools)

1.安装ADT

首先的下载和安装Eclipse,登陆http://www.eclipse.org站点,下载Eclipse IDE for java EE Devlelopers的最新版本,然后安装。

ADT是eclipse的一个插件,如同cdt和jdt一个道理.要开发android程序,至少要有个cde(集成开发环境).而android官方推 荐的是eclipse.并且为eclipse下开发android准备了ADT这样一个插件.有了这个插件,就能比较方便的开发android程序了.

然后点击 Help->Install new Software,在弹出的窗口中点击add按钮

name:AndroidADT或者其它任何名字。

Location:https://dl-ssl.google.com/android/eclipse/ ,如果网络有问题的话,可以试下如下地址:http://dl-ssl.google.com/android/eclipse/

然后点击:ok

勾选Development tools,然后开始安装ADT插件。在Eclipse安装其它插件也一样,这里采用的是在线安装ADT插件,在网络好的情况下,可能需要一段时间,耐心等待。

2.配置ADT

点击eclipse菜单中的window,选择"Preferences...",在弹出窗口中选择android sdk的安装位置:这里是D:\Program Files\android-sdk-windows,配置如下图:

四.创建AVD(Android 虚拟机)

在eclipse菜单点击window,选着AVD Manager弹出:

然后点击 new在弹出的AVD中填写虚拟机的名称name:Android2.2,选着Android平台的版本Target:Android2.2 - API Level 8,设置虚拟的SD卡的大小,这里size是512MiB,可以设置弹出的虚拟器外观的大小:200*350

配置好后点击Edit AVD,最后点击Start启动

如图:

五、在eclipes中开发第一个Android应用

大致需要如下3步:

(1)创建一个Android项目.

(2)在XML布局文件中定义应用程序的用户解界面

(3)在java代码中编写业务实现

详细步骤如下:

1.通过在Eclipes下面"File->Android Project"

点击next:

选着2.3.3在点击next:

点击Finish。

第一个项目创建成功。

2.在Android项目的layout目录下面有一个main.xml文件,该文件用于定义Android的用户界面:

main.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="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/show"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <Button
        android:id="@+id/ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击我" />

</LinearLayout>


说明UI组件上几个通用的属性:

android:id:该属性指定了该控件的唯一标识,在java程序中可以通过findViewById("id")来获取指定的Android界面组件。

android:layout_width:指定该组件的宽度。如果属性为fill_parent,说明该组件与父组件具有相同的宽度;如果属性为wrap_content,则说明该组件的高度取于它的内容——基本能包裹它的内容即可。

思考:为什么把用户界面放在XML文档中定义,这样可以让XML文档专门负责用户UI设置,而java程序专门负责业务实现,这样可以较低程序耦合性。大家要接受Android这种优秀的设计,其实这种思想在学习三大框架时候就接触过了。

3.Android项目的src目录是Android项目的源代码:

HelloWorldActivity.java:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class HelloWorldActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //设置使用main文件定义的布局
        setContentView(R.layout.main);
        //获取UI界面中ID为R.id.ok的按钮
        Button bn = (Button) findViewById(R.id.ok);
        //为按钮绑定一个单击事件的监听器
        bn.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                //获取UI界面中ID为R.id.show的文本框
                final TextView show = (TextView) findViewById(R.id.show);
                //改变文本框的内容
                show.setText("hello world!");
            }
        });
    }
上面这个程序只做了三件事情:

(1)设置该Activity使用main文件定义的界面布局作为用户界面。

(2)获取ID为R.id.ok的按钮

(3)为第二部获得的按钮绑定事件监听器--在事件监听器处理方法中改变ID为R.id.show的文本的内容。

完整的Android应用就开发完成了。

 

posted @ 2021-12-21 20:59  hanease  阅读(1111)  评论(0编辑  收藏  举报