Android期末复习篇_传智课后习题以及答案(选择、填空、判断、简答、编码题)

写在前面

此为移动应用开发传智课后习题及答案,供期末复习使用,注意


目录
  • 1.1习题
  • 1.2习题
  • 1.3习题
  • 1.4习题
  • 1.5习题
  • 1.6习题
  • 1.7习题
  • 1.8习题

1.1 习题
一、 填空题

1、 Android 是 Google 公司基于__Linux____平台开发的手机及平板电脑的___操作系统___。
2、 Android 系统采用分层架构,由高到低依次为___应用程序层___、应用程序框架层、核心类库___和___Linux 内核。_
3、 ADB 的常见指令中,用于开启 ADB 服务的是 adb start-server_。
4、 在 Android 程序中,src 目录用于放置程序的___ java 代码文件___。
5、 Android 程序开发完成后,如果要发布到互联网上供别人使用,需要将程序___ 打包成.apk 文件___。

二、 判断题

1、 Android 实际上就是一个手机( ×)。
2、 WCDMA 是中国自己独自制定的 3G 标准,中国移动使用的就是这种标准(×)。
3、 Android 第 1 个版本 Android1.1,是 2008 年 9 月发布的(√)。
4、 gen 目录是自动生成的,主要有一个 R.java 文件,该文件可手动修改(× )。
5、 AndroidManifest.xml 文件是整个程序的配置文件( √)。

三、选择题

1、 随着智能手机的发展,移动通信技术也在不断地升级,目前传输最快的通信技术是(D)
A、 1G B、2G C、3G D、4G
2、 ADT Bundle 中包含了三个重要组成部分,分别是(ABC )。
A、 Eclipse B、SDK C、SDK Manager.exe D、ADB
3、 应用程序层是一个核心应用程序的集合,主要包括(B )。
A、 活动管理器 B、短信程序 C、音频驱动 D、Dalvik 虚拟机
4、 ADB 的常见指令中“列出所有设备”的指令是(C )。
A、 adb uninstall B、 adb install C、adb device D、adb emulator –avd
5、 创建程序时,填写的 Application Name 表示(A )。
A、 应用名称 B、项目名称 C、项目的包名 D、类的名字 。

四、 简答题
1、 请简要说明 Android 体系结构中每个层的功能

答:Android 体系结构总共包含四层,分别是:

  • 应用程序层:设备上安装的软件应用都属于这一层
  • 应用程序框架层:包含应用 API
  • 核心类库:包含系统库和运行环境,系统库包含了底层 C 代码;运行环境包含了 Java
    的核心库和 Dalvik 虚拟机
  • Linux 内核:提供 Android 的底层驱动。
2、 请简要说明 ADB Bundle 开发工具中 SDK 的作用。

答:SDK 包含了 Android 的 API 源代码、各种工具、示例工程、用到的各种资源模板等。

1.2 习题
一、填空题

1、 Android 中的布局分为六种,分别是__RelativeLayout____、LinearLayout、TableLayout、GirdLayout、FrameLayout__和___AbsoluteLayout。
2、 Android 相对布局中,表示“是否跟父布局左对齐”的属性是___android:layout_alignParentLeft。
3、 线性布局主要有两种形式,一种___水平___线性布局,一种是____竖直__线性布局。
4、 创建 Android 程序时,默认使用的布局是___RelativeLayout___。
5、 LogCat 区域中有 V、D、I、W 和 E 五个字母,其中 V 代表____显示全部信息__、D 代表____显示调试信息__、I 代表
显示一般信息、W 代表___显示警告信息___、E 代表___显示错误信息___。

二、 判断题

1、 相对布局中 android:layout_alignRight 属性表示“与指定控件右对齐”( √ )。
2、 Toast 的作用是显示一些提示信息( √)。
3、 TableRow 必须要设置 layout_width 和 layout_height 属性(×)。
4、 帧布局中可以添加多个控件,这些控件会重叠的在屏幕左上角显示(√)。
5、 Android 程序中是不支持国际化的(×)。

三、 选择题

1、 以下属性中,哪个属性可以“在指定控件左边”是(D )
A、 android:layout_alignLeft B、android:layout_alignParentLeft
C、android:layout_left D、android:layout_toLeftOf
2、 表格布局中 android:layout_column 属性的作用是指定(B )。
A、 行数 B、列数 C、总行数 D、总列数
3、 实际开发中刮刮乐游戏的布局是按照(C )布局写的。
A、 相对布局 B 线性布局 C 帧布局 D 绝对布局
4、 网格布局是 Android(D )新增的布局。
A、3.0 B、3.1 C、3.2 D、4.0
5、 相对布局中,“是否跟父布局底部对齐”是属性(B )。
A、 android:layout_alignBottom B、android:layout_alignParentBottom
C、android:layout_alignBaseline D、android:layout_below

四、 简答题
1、 请简述一下如何在程序中使用 Toast。

使用 Toast 可以直接调用 Tosast 的静态方法:
Toast.makeText(this, text, duration).show();
也可以创建出 Toast 对象,如:
Toast toast = new Toast(this); toast.setText(“提示信息”); toast.show();

2、 请说明布局有几种类型,每种类型的作用。

答:一共有六种布局,它们的作用分别是:

  • RelativeLayout:相对于其他控件或者容器决定控件的位置;
  • LinearLayout:使控件以竖直或者水平方向排列;
  • TableLayout:使控件以表格形式排列;
  • GirdLayout:能使控件交错显示,能够避免因布局嵌套对设备性能的影响,更利于自由
    布局的开发;
  • FrameLayout:使控件按照创建顺序在屏幕的左上角重叠显示;
  • AbsoluteLayout:通过绝对的坐标控制控件摆放的位置。
3、 请编写一个用户登录界面,界面中必须要有文本提示信息(TextView),编辑框(EditText),按钮(Button),分别用于显示“用户名”、“密码”,输入用户名、密码,登录功能。
<RelativeLayout 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"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical" >
        <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/login" />
        <EditText
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_marginTop="10dp"
            android:hint="请输入用户名"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_marginTop="10dp"
            android:inputType="textPassword"
            android:hint="请输入密码"/>
        <Button
            android:layout_marginTop="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/soil_backgroud_content2"
            android:textColor="@android:color/white"
            android:text="登录"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="注册用户"
            android:textColor="#35A8F4"/>
    </LinearLayout>

</RelativeLayout>


==================strings.xml======================
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">登录界面</string>
    <string name="menu_settings">Settings</string>
    <string name="hello_world">Hello world!</string>

</resources>

4、 自定义一个样式,使用这个样式将界面中的背景色修改,并且美化界面中的文字信息。
<RelativeLayout 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"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        style="@style/MyStyle"/>

</RelativeLayout>


====================== styles.xml文件 =====================

<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>
    
    <style name="MyStyle">
        <item name="android:background">#35A8F4</item>
        <item name="android:text">你好</item>
        <item name="android:textColor">@android:color/white</item>
   </style>
    

</resources>
1.3 习题
一、 填空题

1、 Activity 生命周期的三种状态分别是__运行状态____、暂停状态____和___停止状态_。
2、 Activity 的四种启动模式是__ standard____、singleTop、singleTask___和___singleInstance。
3、 Android 中 Intent 寻找目标组件的方式有两种___隐式 Intent___和____显示 Intent__。
4、 Activity 生命周期中“回到前台,再次可见时执行”时调用的方法是__ onRestart()。
5、 要在 Activity 中实现数据回传,则需要使用__ startActivityForResult()方法开启另一个 Activity。

二、 判断题

1、 Activity 是 Android 应用程序的四大组件之一(√)。
2、 Intent 一般只用于启动 Activity 不能开启广播和服务(× )。
3、 Intent 可以用来开启 Activity,同样它也可以用来在 Activity 之间传递数据(√ )。
4、 Activity 默认的启动模式是 singleTop 模式(× )。
5、 在数据传递时,如果需要获取返回的数据,需要使用 onActivityResult()方法(√ )。

三、 选择题

1、 一个应用程序默认会包含(A )个 Activity。
A、1 个 B、5 个 C 、10 个 D、若干个
2、 下列方法中,Activity 第一次启动到关闭不会执行的是( D)。
A、 onCreate() B、onStart() C、onResume() D、onRestart()
3、 下列组件中,不能使用 Intent 启动的是(D )。
A、 Activity B、启动服务 C、广播 D 内容提供者
4、 startActivityForResult()方法接收两个参数,第一个是 Intent,第二个是(C )。
A、 resultCode B、request C、requestCode D、data
5、 下列关于 Activity 的描述,错误的是( C)。
A、 Activity 是 Android 的四大组件之一
B、 Activity 有四种启动模式
C、 Activity 通常用于开启一个广播事件
D、 Activity 就像一个界面管理员,用户在界面上的操作是通过 Activity 来管理。

四、 简答题
1、 请简要说明 Activity 四种启动模式的区别。

1、四种启动模式分别是:

  • Standard:每当启动一个新的 Activity,它就会进入任务栈,并处于栈顶的位置,对于使
    用 standard 模式的 Activity,系统不会判断该 Activity 在栈中是否存在,每次启动都会创
    建一个新的实例。
  • SingleTop:与 standard 类似,不同的是,当启动的 Activity 已经位于栈顶时,则直接使
    用它不创建新的实例。如果启动的 Activity 没有位于栈顶时,则创建一个新的实例位于
    栈顶。
  • SingleTask:创建的 Activity 只存在一个实例。已经存在则直接使用该实例,并将当前
    Activity 之上的所有 Activity 出栈
    ,如果没有发现则创建一个新的实例。
  • singleInstance:启动一个新的任务栈管理 Activity
2、 请简要说明 Activity 的三种状态以及不同状态使用的方法。

Activity 三种状态分别是:

  • 运行状态:该状态下可以对界面进行操作
  • 暂停状态:界面可见但不具有焦点无法点击
  • 停止状态:界面不可见,一般在停止状态时保存数据以防止程序被系统强制杀死。
五、 编程题
1、 请编写一个程序,通过隐式意图打开系统中的浏览器。
package cn.itcast.demo1;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	/**
	 * 打开系统默认浏览器
	 * */
	public void openDefaultBrowser(View view) {
		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		Uri content_url = Uri.parse("http://www.baidu.com");
		intent.setData(content_url);
		startActivity(intent);
	}

	/**
	 * 打开指定浏览器
	 * */
	public void openSpecifiedBrowser(View view) {
		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		Uri content_url = Uri.parse("http://www.163.com");
		intent.setData(content_url);
		intent.setClassName("com.android.browser",
				"com.android.browser.BrowserActivity");
		startActivity(intent);
	}
}

2、 请编写一个数据传递的小程序,要求在第一个界面输入姓名、年龄,第二个界面上面显示“恭喜您!来到这个世界 n 年!”。
=============== MainActivity.java===============
package cn.itcast.demo2;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends Activity {
	private EditText editText_inputName, editText_inputAge;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		editText_inputName = (EditText) findViewById(R.id.editText_inputName);
		editText_inputAge = (EditText) findViewById(R.id.editText_inputAge);
	}

	public void transferData(View view) {
		String name = editText_inputName.getText().toString().trim();
		String age = editText_inputAge.getText().toString();
		Intent intent = new Intent(this, ReceiveData.class);
		intent.putExtra("name", name);
		intent.putExtra("age", age);
		startActivity(intent);
	}

}

====================== ReceiveData.java ============

package cn.itcast.demo2;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class ReceiveData extends Activity {

	private TextView tv_receiveData;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_receive_data);

		tv_receiveData = (TextView) findViewById(R.id.tv_receiveData);
		Intent intent = getIntent();
		String name = intent.getStringExtra("name");
		String age = intent.getStringExtra("age");
		tv_receiveData.setText("恭喜您_" + name + "_来到这个世界上" + age + "年");
	}
}

1.4 习题
一、 填空题

1、 序列化是将对象状态转换为 可保持或传输___的过程。
2、 Android 中的文件可以存储在___内存___和___SD 卡___中。
3、 通常情况下,解析 XML 文件有三种方式,分别为 DOM_、SAX、PULL。
4、 SharedPreferences 是一个轻量级的存储类,主要用于存储一些应用程序的____ 配置参数__。
5、 Android 中的数据存储方式有五种,分别是____文件__、Sharedpreferences、Sqlite、网络、和___ContentProvider。

二、 判断题

1、 SharedPreferences 本质上是一个 XML 文件,以 Map<Object,Object>形式存入文件中( √)。
2、 文件存储是通过 I/O 流的形式把数据存储到文档中( √)。
3、 XML 文件只能用来保存本地数据,不能在网络中传输( ×)。
4、 ContentProvider 表示内容提供者,用于显示程序中的数据( ×)。 解决进程间数据通信
5、 当用户将文件保存至 SD 卡时,需要在清单文件中添加权限"android.permission. WRITE_EXTERNAL_STORAGE"(√ )。

三、 选择题

1、 下列文件操作权限中,指定文件内容可以追加的是( C)。
A、 MODE_PRIVATE B、MODE_WORLD_READABLE C、MODE_APPEND D、MODE_WORLD_WRITEABLE
2、 下列代码中,用于获取 SD 卡路径的是(D )。
A、 Environment.getSD ();
B、 Environment.getExternalStorageState();
C、 Environment.getSDDirectory();
D、 Environment.getExternalStorageDirectory();
3、 下列选项中,关于文件存储数据的说法错误的是(D )。
A、 文件存储是以流的形式来操作数据的
B、 文件存储可以将数据存储到 SD 卡中
C、 文件存储可以将数据存储到内存中
D、 Android 中只能使用文件存储数据
1、下列选项中,关于 XML 序列化和解析描述合理的是(ABD )。
A、 DOM 解析会将 XML 文件的所有内容以文档树方式存放在内存中
B、 在序列化对象时,需要使用 XmlSerialize 序列化器,即 XmlSerializer 类
C、 XmlSerializer 类的 startDocument()方法用于写入序列号的开始节点
D、 XmlSerializer 类的 setOutput()方法用于设置文件的编码方式
5、如果要将程序中的私有数据分享给其他应用程序,可以使用的是(C )。
A、文件存储 B、SharedPreferences C、ContentProvider D、SQLite

四、 简答题
1、 请简述 Android 系统中的五种数据存储方式各自的特点。

1、五种存储方式各自的特点分别是:

  • 文件存储:可以存储较大文件,以 IO 流形式传输数据。
  • Sqlite:占用内存小,所有文件都存放在单一文件中。
  • 网络:通过网络将数据传输到服务器存储,避免了客户端的安全隐患。
  • Sharedpreference:使用方便,可以存储配置信息,以键值对的形式存于内存中
  • ContentProvider:提供自身暴漏的数据给第三方应用使用,统一了数据访问格式,以数据库
    形式保存数据。
2、 请简述 SharedPreferences 如何存储数据。

使用 Sharedpreference 储存数据时因为它本身没有写文件的功能,因此需要使用 Editor 对象
将数据存入内存,比如:

SharedPreferences sp = getSharedPreferences(“config”, 0);
Editor editor = sp.edit();
editor.putString(“a”, “a”);
editor.commit();

五、 编程题
1、 请自定义一个 XML 文件,并将 XML 文件中的内容解析出来。

===================== xml文件 =================
<?xml version="1.0" encoding="UTF-8"?>
<plants>
    <plantsInfo>
        <name>仙人球</name>
        <content>仙人球为多年生肉质多浆草本植物,是双子叶植物,在植物分类学中属于仙人掌科。茎呈球形或椭圆形,高可达25厘米,绿色,球体有纵棱若干条,棱上密生针刺,黄绿色,长短不一,作辐射状。花着生于纵棱刺丛中,银白色或粉红色,长喇叭形,长可达20厘米,喇叭外鳞片,鳞腑有长毛。仙人球开花一般在清晨或傍晚,持续时间几小时到一天。球体常侧生出许多小球,形态优美、高雅。</content>
    </plantsInfo>
    <plantsInfo>
        <name>薰衣草</name>
        <content>薰衣草原野生于法国和意大利南部地中海沿海的阿尔卑斯山南麓一带, 以及西班牙、北非等地。13世纪,它是欧洲医学修道院园圃中的主要栽种植物。15世纪,海尔幅夏地区开始种植。16世纪末,在法国南部地区开始栽培。18世纪,萨里的密契、伦敦南区的熏衣山、法国的普罗旺斯、格拉斯附近的山区都以种植薰衣草而闻名,并成为世界闻名的旅游胜地。19世纪,英、澳等国相继引种栽培,现已遍及地中海与黑海沿岸诸国。</content>
    </plantsInfo>
    <plantsInfo>
        <name>向日葵</name>
        <content>向日葵又名朝阳花,因其花常朝着太阳而得名。英语称之为sunflower却不是因为它的这一特性,因为其黄花开似太阳的缘故。16世纪~17世纪sunflower一词从拉丁语flos solis借译过来。向日葵的法语,意大利语和西班牙语名称tournesol,girasol和girasol同汉语名称一样,也是基于“向日”这一特性来命名的。</content>
    </plantsInfo>
</plants>
package cn.itcast.plant;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import cn.itcast.plant.bean.PlantInfo;

public class MainActivity extends Activity implements OnClickListener {

	private List<PlantInfo> plantInfos;
	private TextView mPlantContentTV;
	private ImageView mPlantImgv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		try {
			plantInfos = utils.getPlantInfos(MainActivity.class
					.getClassLoader().getResourceAsStream("plant.xml"));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		initView();
	}

	/**
	 * 初始化控件
	 */
	private void initView() {
		findViewById(R.id.btn_xrq).setOnClickListener(this);
		findViewById(R.id.btn_xrk).setOnClickListener(this);
		findViewById(R.id.btn_xyc).setOnClickListener(this);
		 mPlantContentTV = (TextView)findViewById(R.id.tv_plants_content);
		 mPlantImgv = (ImageView) findViewById(R.id.imgv_plant);
		mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(0).getPlantContent());
		mPlantImgv.setBackgroundResource(R.drawable.a);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_xrq:
			mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(0).getPlantContent());
			mPlantImgv.setBackgroundResource(R.drawable.a);
			break;
		case R.id.btn_xyc:
			mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(1).getPlantContent());
			mPlantImgv.setBackgroundResource(R.drawable.c);
			break;
		case R.id.btn_xrk:
			mPlantContentTV.setText("\u3000\u3000"+plantInfos.get(2).getPlantContent());
			mPlantImgv.setBackgroundResource(R.drawable.b);
			break;
		}
	}
}


======================== utils.java========================
package cn.itcast.plant;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
import cn.itcast.plant.bean.PlantInfo;

/** 解析xml文件的工具类 */
public class utils {

	// 返回天气信息的集合
	public static List<PlantInfo> getPlantInfos(InputStream is)
			throws Exception {
		// 得到pull解析器
		XmlPullParser parser = Xml.newPullParser();
		// 初始化解析器,第一个参数代表包含xml的数据
		parser.setInput(is, "utf-8");
		List<PlantInfo> plantInfos = null;
		PlantInfo plantInfo = null;
		// 得到当前事件的类型
		int type = parser.getEventType();
		// END_DOCUMENT文档结束标签
		while (type != XmlPullParser.END_DOCUMENT) {
			switch (type) {
			// 一个节点的开始标签
			case XmlPullParser.START_TAG:
				// 解析到全局开始的标签 infos 根节点
				if ("plants".equals(parser.getName())) {
					plantInfos = new ArrayList<PlantInfo>();
				} else if ("plantsInfo".equals(parser.getName())) {
					plantInfo = new PlantInfo();
				} else if ("name".equals(parser.getName())) {
					// parset.nextText()得到该tag节点中的内容
					String name = parser.nextText();
					plantInfo.setPlantName(name);
				} else if ("content".equals(parser.getName())) {
					String content = parser.nextText();
					plantInfo.setPlantContent(content);
				}
				break;
			// 一个节点结束的标签
			case XmlPullParser.END_TAG:
				// 一个城市的信息处理完毕,city的结束标签
				if ("plantsInfo".equals(parser.getName())) {
					// 一个城市的信息 已经处理完毕了.
					plantInfos.add(plantInfo);
					plantInfo = null;
				}
				break;
			}
			// 只要不解析到文档末尾,就解析下一个条目。得到下一个节点的事件类型
			// 注意,这个一定不能忘,否则会成为死循环
			type = parser.next();
		}
		return plantInfos;
	}
}

=================== Bean =======================
package cn.itcast.plant.bean;
/**植物信息*/
public class PlantInfo {
	
	private String plantName;
	private String plantContent;
	
	public String getPlantName() {
		return plantName;
	}
	public void setPlantName(String plantName) {
		this.plantName = plantName;
	}
	public String getPlantContent() {
		return plantContent;
	}
	public void setPlantContent(String plantContent) {
		this.plantContent = plantContent;
	}
}



2、 请编写一个短信草稿箱的程序,要求用户在文本编辑框中输入短信内容后,点击“保存短信” 按钮,将短信保存在 SharedPreferences 中。
package cn.itcast.chapter04.sms;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	/**短信文本输入框*/
    private EditText mSmsContentET;
    /**存储信息按钮*/
	private Button mSaveBTN;
	/**读取已存信息按钮*/
	private Button mReadBTN;
	private SharedPreferences mSP;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSP = getSharedPreferences("data", Context.MODE_PRIVATE);
        mSmsContentET = (EditText) findViewById(R.id.et_smscontent);
        mSaveBTN = (Button) findViewById(R.id.btn_save);
        mReadBTN = (Button) findViewById(R.id.btn_read);
        mSaveBTN.setOnClickListener(this);
        mReadBTN.setOnClickListener(this);
    }

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_read:
			getSms();
			break;
		case R.id.btn_save:
			saveSms();             
			break;

		}
	}
	
	/***
	 * 保存信息
	 */
	private void saveSms() {
		if(!TextUtils.isEmpty(mSmsContentET.getText().toString().trim())){
			Editor edit = mSP.edit();
			edit.putString("sms", mSmsContentET.getText().toString().trim());
			edit.commit();
			Toast.makeText(MainActivity.this, "信息存储成功!", 0).show();
		}else{
			Toast.makeText(MainActivity.this, "短信内容不能为空!!!", 0).show();
		}
	}

	/**
	 * 读取信息
	 */
	private void getSms() {
		String sms = mSP.getString("sms", null);
		if(sms != null){
			mSmsContentET.setText(sms);
		}else{
			Toast.makeText(MainActivity.this, "请先保存信息!!!", 0).show();
		}
	} 
	
	
	
}

1.5 习题
一、填空题

1、 ListView 常用的适配器有三种,分别是___BaseAdapter__、SimpleAdapter___和___ArrayAdapter。
2、 创建数据库以及数据库版本更新需要继承____ SQLiteOpenHelper__。
3、 SQLite 创建时调用___onCreate()方法,升级时调用___onUpgrade()方法。
4、 要查询 SQLite 数据库中的信息需要使用 Cursor___接口,使用完毕后调用___close()关闭。
5、 创建 ListView 的布局界面必须通过 Id____属性才能使数据显示在界面上。

二、判断题

1、 SQLite 数据库使用完后不需要关闭,不影响程序性能( ×)。
2、 使用 ListView 显示较为复杂的数据时最好用 ArrayAdapter 适配器(× )。
3、 SQLite 即支持 Android 的 API 又支持 SQL 语句进行增删改查操作( √)。
4、 使用 BaseAdapter 控制 ListView 显示多少条数据是通过 getView()方法设置(× )。
5、 SQLite 支持 NULL、INTEGER、REAL、TEXT 和 BLOB 五种数据类型( √)。

三、选择题

1、 使用 SQLite 数据库进行查询后,必须要做的操作是(AC )。
A、 关闭数据库 B、直接退出 C、关闭 Cursor D、使用 quit 函数退出
2、 关于适配器的说法正确的是(B )。
A、 它主要用来存储数据 B、它主要用来把数据绑定在组件上
C、它主要用来存储 XML 数据 D、它主要用来解析数据
3、 使用 SQLiteOpenHelper 类的( )方法可以创建一个可写的数据库对象。(B )
A、 getDatabase() B、getWriteableDatabase()
C、getReadableDatabase() D、getAbleDatabase()
4、 下下列命令中,属于 SQLite 下的命令是(C )。
A、 shell B、push C、quit D、keytool
5、 下列关于 ListView 使用的描述中,不正确的是(B )。
A、 要使用 ListView,则必须使用 Adapter 进行数据适配
B、 要使用 ListView,该布局文件对应的 Activity 必须继承 ListActivity
C、 ListView 中每一项的视图布局既可以使用内置的布局,也可以使用自定义的布局方式
D、 要实现 ListView 的条目点击,就需要实现 OnItemClickListener 接口

四、简答题
1、 请简要说明 SQLite 数据库创建的过程。

1、首先创建一个类继承 SQLiteOpenHelper,重写 onCreate()方法并在该方法中创建表,使用创
建出的 SQLiteOpenHelper 的子类对象的 getWritableDatabase()方法获得一个可读写的数据库
对象。

2、 请简要说明 BaseAdapter 适配器四个抽象方法以及它们的具体作用。

四个抽象方法分别是:

  • getCount:得到 Item 的总数
  • getItem:根据 position 得到某个 Item 的对象
  • getItemId:根据 position 得到某个 Item 的 id
  • getView:得到相应 position 对应的 Item 视图,position 当前 Item 的位置,convertView
    复用的 View 对象。
五、编程题
1、 请使用 ListView 显示 10 行数据在界面上,分别用三种适配器实现。
package cn.itcast.listviewdemo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class MainActivity extends Activity {
	private ListView listView;
	private MyBaseAdapter baseAdapter;

	private static String[] simpleData = new String[] { "JAVA", "C", "C++",
			"C#", "JavaScript", "PHP", ".Net", "Go*", "Object-C", "Python" };
	private static String[] arrayData = new String[] { "Android", "IOS",
			"Windows", "UNIX", "Linux", "Mac OS X", "WP", "Chrome OS",
			"WindowsXP", "Windows 10", };
	private static String[] baseData = new String[] { "华为", "魅族", "小米", "中兴",
			"苹果", "三星", "黑莓", "诺基亚", "酷派", "索尼" };
	private int[] baseImageData = new int[] { R.drawable.huawei,
			R.drawable.meizu, R.drawable.xiaomi, R.drawable.zhongxing,
			R.drawable.iphone, R.drawable.sanxing, R.drawable.heimei,
			R.drawable.nokia, R.drawable.kupai, R.drawable.sony };

	private ArrayAdapter<String> arrayAdapter;
	private SimpleAdapter simpleAdapter;
	private List<Map<String, Object>> list;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 1. 获取listvoew对象
		listView = (ListView) findViewById(R.id.listview);
		// 2. 封装数据到list.lis包含很多map对象,包含title、img等信息,待会simpleApapter要用
		list = getData();

		// 3. 使用arayAdapter测试,只包含文字string[]
		arrayAdapter = new ArrayAdapter<String>(this,
				R.layout.listview_array_item, R.id.tv_array_content, arrayData);
		listView.setAdapter(arrayAdapter);
	}



	// 1. baseAdapter
	public void baseAdapter(View view) {
		baseAdapter = new MyBaseAdapter(this, baseData, baseImageData);
		listView.setAdapter(baseAdapter);
	}

	// 2. arrayAdapter
	public void arrayAdapter(View view) {
		listView.setAdapter(arrayAdapter);
	}
	//3.	simpleAdapter需要 读取数据到list,list包含很多map对象
	private List<Map<String, Object>> getData() {
		List<Map<String, Object>> mList = new ArrayList<Map<String, Object>>();
		for (int i = 0; i < simpleData.length; i++) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("title", simpleData[i]);
			map.put("img", R.drawable.ic_launcher);
			mList.add(map);
		}
		return mList;
	}
	// 3. simpleAdapter
	public void simpleAdapter(View view) {
		simpleAdapter = new SimpleAdapter(this, list, R.layout.listview_item,
				new String[] { "title", "img" }, new int[] { R.id.tv_content,
						R.id.iv_content });
		listView.setAdapter(simpleAdapter);
	}

	
}
================================= MyBaseAdapter.java =====================================
package cn.itcast.listviewdemo;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyBaseAdapter extends BaseAdapter {
	private String[] data;
	private Context context;
	private int[] imageData;

	public MyBaseAdapter(MainActivity mainActivity, String[] baseData,
			int[] baseImageData) {
		this.data = baseData;
		this.context = mainActivity;
		this.imageData = baseImageData;
	}

	@Override
	public int getCount() {
		return data.length;
	}

	@Override
	public Object getItem(int position) {
		return data[position];
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		convertView = View.inflate(context, R.layout.listview_item, null);
		ImageView iv_content = (ImageView) convertView
				.findViewById(R.id.iv_content);
		TextView tv_content = (TextView) convertView
				.findViewById(R.id.tv_content);

		iv_content.setImageResource(imageData[position]);
		tv_content.setText(data[position]);

		return convertView;
	}

}

<RelativeLayout 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"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/ll_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="baseAdapter"
            android:text="BaseAdapter"
            android:textSize="12dp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="arrayAdapter"
            android:text="ArrayAdapter"
            android:textSize="12dp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="simpleAdapter"
            android:text="SimpleAdapter"
            android:textSize="12dp" />
    </LinearLayout>

    <ListView
        android:id="@+id/listview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ll_title" />

</RelativeLayout>
================== listview_array_item.xml ===== arrayAdapter 渲染 title====================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_array_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_margin="15dp"
        android:text="文字"
        android:textSize="18sp" />

</RelativeLayout>


============== listview_item.xml======= simpleAdapter、baseAdapter 渲染 title + img ===============
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/iv_content"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:contentDescription="图片显示"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="文字" />
    </LinearLayout>

</RelativeLayout>

2、 请创建一个 fruit.db 表,在表中存入五种水果信息,并将这些信息显示到 ListView 控件中。

============== MainActivity =======
package cn.itcast.sqlitedemo;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

	private ListView listView;
	private FruitDao dao;
	private List<Fruit> queryAll;
	private String[] names = new String[] { "香蕉", "苹果", "橘子", "西瓜", "草莓" };
	private String[] addresses = new String[] { "亚洲东南部", "北半球的温带地区",
			"长江中下游和长江以南地区", "非洲", "南美洲" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listView = (ListView) findViewById(R.id.listview);
		
		dao = new FruitDao(this);

		for (int i = 0; i < names.length; i++) {
			Fruit fruit = new Fruit(names[i], addresses[i]);
			// 插入数据库
			dao.insert(fruit);
		}
		// 查询所有保存到list
		queryAll = dao.queryAll();

		// list 渲染至 listview
		listView.setAdapter(new MyAdapter());
	}

	private class MyAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			return queryAll.size();
		}

		@Override
		public Object getItem(int position) {
			return queryAll.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			convertView = View.inflate(MainActivity.this,
					R.layout.listview_item, null);
			Fruit fruit = queryAll.get(position);
			TextView tv_name = (TextView) convertView
					.findViewById(R.id.tv_name);
			TextView tv_address = (TextView) convertView
					.findViewById(R.id.tv_address);
			tv_name.setText(fruit.getName());
			tv_address.setText("原产地:" + fruit.getAddress());
			return convertView;
		}

	}
}

================ MySQLite =============

package cn.itcast.sqlitedemo;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MySQLite extends SQLiteOpenHelper {

	public MySQLite(Context context) {
		super(context, "fruit.db", null, 1);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("CREATE TABLE fruit(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20),address VARCHAR(20))");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

	}

}


============== Bean ===============
package cn.itcast.sqlitedemo;

public class Fruit {

	private String name;
	private String address;

	public Fruit(String name, String address) {
		this.name = name;
		this.address = address;
	}

	public Fruit() {

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
}


================ Dao ==================
package cn.itcast.sqlitedemo;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class FruitDao {
	private MySQLite helper;

	public FruitDao(Context context) {
		helper = new MySQLite(context);
	}

	public void insert(Fruit fruit) {
		// 获取数据库对象
		List<Fruit> queryAll = queryAll();
		if (queryAll != null) {
			for (int i = 0; i < queryAll.size(); i++) {
				if (fruit.getName().equals(queryAll.get(i).getName())) {
					return;
				}
			}
		}
		SQLiteDatabase db = helper.getWritableDatabase();
		// 用来装载要插入的数据的 Map<列名, 列的值>
		ContentValues values = new ContentValues();
		values.put("name", fruit.getName());
		values.put("address", fruit.getAddress());
		// 向fruit表插入数据values,
		db.insert("fruit", null, values);
		db.close(); // 关闭数据库
	}

	// 根据id 删除数据
	public int delete(String name) {
		SQLiteDatabase db = helper.getWritableDatabase();
		// 按条件删除指定表中的数据, 返回受影响的行数
		int count = db.delete("fruit", "name=?", new String[] { name });
		db.close();
		return count;
	}

	// 更新数据
	public int update(Fruit fruit) {
		SQLiteDatabase db = helper.getWritableDatabase();
		ContentValues values = new ContentValues(); // 要修改的数据
		values.put("name", fruit.getName());
		values.put("balance", fruit.getAddress());
		int count = db.update("fruit", values, "name=?",
				new String[] { fruit.getName() + "" }); // 更新并得到行数
		db.close();
		return count;
	}

	// 查询所有数据倒序排列
	public List<Fruit> queryAll() {
		SQLiteDatabase db = helper.getReadableDatabase();
		Cursor c = db.query("fruit", null, null, null, null, null, "name");
		List<Fruit> list = new ArrayList<Fruit>();
		while (c.moveToNext()) {
			// 可以根据列名获取索引
			String name = c.getString(c.getColumnIndex("name"));
			String address = c.getString(c.getColumnIndex("address"));
			list.add(new Fruit(name, address));
		}
		c.close();
		db.close();
		return list;
	}

}


1.6 习题
一、填空题

1、 ContentProvider 匹配 Uri 需要使用的类是 UriMatcher__。
2、 使用内容观察者时,调用____ onChange()方法可以得到数据变化的信息。
3、 ContentProvider 提供了对数据增删改查的方法,分别为_ insert___、delete__、update___和___query。
4、 ContentProvider 用于___ 保存___和____检索__数据,是 Android 中不同应用程序之间共享数据的接口。
5、 在应用程序中,使用 ContentProvider 暴露自己的数据,通过___ContentResolver___对暴露的数据进行操作。

二、判断题

1、 ContentProvider 所提供的 Uri 可以随便定义( ×)。
2、 ContentResolver 可以通过 ContentProvider 提供的 Uri 进行数据操作(√)。
3、 ContentObserver 观察指定 Uri 数据发生变化时,调用 ContentProvider 的 onChange 方法( √)。
4、 使用 ContentRsolver 操作数据时,必须在清单文件进行注册(× )。
5、 ContentProvider 与 Activitry 一样,创建时首先会调用 onCreate()方法(√ )。

三、选择题

1、 下列选项中,属于 Android 中四大组件的是(AC )。
A、 Activity B、ContentReceiver C、Service D、ContentObserver
2、 下列关于 ContentResolver 的描述,错误的是(C )。
A、 可以操作数据库数据 B、操作其他应用数据必须知道包名
C、不能操作 ContentProvider 暴露的数据 D、可以操作 ContentProvider 暴露的数据
3、 下列关于内容提供者的描述,正确的是(ACD )。
A、 提供的 Uri 必须符合规范 B、可以提供本应用所有数据供别人访问
C、必须在清单文件注册 D、authorities 属性必须和包名一致
4、 继承 ContentProvider 类必须重写它的什么方法(AB )。
A、 delete() B、insert() C、onStart() D、onUpdate()
5、 下列关于内容观察者的说法,正确的是(C )。
A、 可以观察任何数据 B、观察其他应用数据需要权限
C、只能观察到指定 Uri 的数据 D、观察其他应用数据必须在清单文件注册

四、简答题
1、 请简要说明 ContentProvider 对外共享数据的好处。

通过 ContentProvider 共享数据统一了数据访问方式,使用起来更规范,通过数据库存储并指
定了 URI,只有通过特定 URI 才能访问数据,使数据更安全

2、 请简要说明 ContentProvider、ContentResolver 和 ContentObserver 之间的联系。

ContentProvider 可以共享自己的数据给外部应用访问,要访问 ContentProvider 暴漏的数据就
要用到 ContentResolver。而 ContentObserver 就相当于中间人的角色,它可以事实监听
ContentProvider 的 数 据 是 否 发 生 变 化 , 如 果 发 生 变 化 就 会 触 发 onChange() 方 法 ,
Contentresolver 可以在 onChange()方法中查询的哪些数据发生了变化再对数据进行操作。

五、编程题
1、 使用 ContentProvider 管理联系人信息,将联系人信息展示在界面上。
package cn.itcast.chapter06.contact;

import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import cn.itcast.chapter06.contact.bean.ContactEntity;
import cn.itcast.chapter06.contact.utils.ContactUtil;

public class MainActivity extends Activity {

	private ListView mListView;
	private ContactUtil contactUtil;
	private List<ContactEntity> contacts = new ArrayList<ContactEntity>();
	private MyAdapter adapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mListView = (ListView) findViewById(R.id.lv_contacts);
		adapter = new MyAdapter();
		mListView.setAdapter(adapter);
		contactUtil = new ContactUtil();
		initData();
	}

	/** 获取联系人信息 */
	private void initData() {
		contacts.addAll(contactUtil.getContactData(this));
		adapter.notifyDataSetChanged();
	}

	/***
	 * ListView适配器
	 * @author admin
	 */
	class MyAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			return contacts.size();
		}

		@Override
		public Object getItem(int position) {
			return contacts.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder = null;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = View.inflate(MainActivity.this,
						R.layout.list_item, null);
				holder.tvName = (TextView) convertView
						.findViewById(R.id.tv_name);
				holder.tvNumber = (TextView) convertView
						.findViewById(R.id.tv_number);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			ContactEntity contactEntity = contacts.get(position);
			holder.tvName.setText(contactEntity.contactName);
			holder.tvNumber.setText(contactEntity.phoneNumber);
			return convertView;
		}
		class ViewHolder {
			TextView tvName;
			TextView tvNumber;
		}
	}
}

2、 获取系统图库的信息,使用 ContentProvider 制作本地图片查看器。

1.7 习题
一、填空题

1、 广播接收者有在清单文件,使用___ receiver___注册。
2、 终止广播需要使用___ abortBroadcast()方法。
3、 广播的发送有两种形式,分别为_ 有序广播__和___无序广播___。
4、 代码注册广播需要使用___ registerReceiver___方法,解除广播需要使用___unregisterReceiver___方法。
5、 指定发送有序广播的方法是___ sendOrderedBroadcast()。

二、判断题

1、 每一个广播只能有一个广播接收者接收(× )。
2、 广播接收者是四大组件之一,必须要在清单文件中注册(√)。
3、 一个清单文件中只能注册一个广播接收者( ×)。
4、 可以在 BroadcastReceiver 的 onReceive 方法中处理耗时复杂的业务( ×)。
5、 广播接收者注册后必须要手动关闭(× )。

三、选择题

1、 继承 BroadcastReceiver 会重写哪一个方法(A )。
A、 onReceiver() B、onUpdate() C、onCreate() D、onStart()
2、 关于广播的作用,说法正确的是(AC )。
A、 它主要用来接收系统发布的一些消息的 B、它可以进行耗时的操作
C、它可以启动一个 Activity D、广播接收者不需要注册
3、 下列方法中,用于发送一条有序广播的是(B )。
A、 startBroadcastReceiver() B、sendOrderedBroadcast()
C、sendBroadcast() D、sendReceiver()
4、 在清单文件中,注册广播时使用的节点是( C)。
A、 B、 C、 D、
5、 关于 BroadcastReceiver 说法不正确的是(B )。
A、 用于接收系统或程序中的广播事件
B、 一个广播事件只能被一个广播接收者所接收
C、 对有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者
D、 接收者声明的优先级别在 android:priority 属性中声明,数值越大优先级别高

四、简答题
1、请说明注册广播有几种方式,这些方式有何优缺点。

1、 注册广播有两种方式。

  • 非常驻型广播:这种广播依赖于注册广播的组件的生命周期,例如,在 Activity 中注册
    广播接收者,当 Activity 销毁后广播也随之被移除。
  • 常驻型广播:当应用程序关闭后,如果接收到其他应用程序发出的广播,那么该程序
    会自动重新启动。但是 4.0 以上的系统中如果安装了应用但是没有打开过,当有广播发
    出时应用也接收不到广播信息。
2、请简要说明接收系统广播时哪些功能需要使用权限。
  • 拨打电话:<uses-permission android:name="android.permission.CALL_PHONE" />
  • 发送短信:<uses-permission android:name="android.permission.SEND_SMS" />
  • 设备开机:<uses-permission android:name=android.permission.RECEIVE_BOOT_COMPLETED />
  • 电池电量低:<action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
五、编程题
1、 请编写程序,监控手机电量,当电量小于百分之 15 时进行提示。
package cn.itcast.BatteryChecker;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private TextView tv_cell;
	private BatteryReceiver batteryReceiver;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		tv_cell = (TextView) findViewById(R.id.tv_cell);
		// 注册广播接受者java代码
		IntentFilter intentFilter = new IntentFilter(
				Intent.ACTION_BATTERY_CHANGED);
		batteryReceiver = new BatteryReceiver();
		// 注册receiver
		registerReceiver(batteryReceiver, intentFilter);
	}

	/**
	 * 广播接受者
	 */
	private class BatteryReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
				int level = intent.getIntExtra("level", 0);
				tv_cell.setText("电池电量为" + level + "%");

				if (level < 15) {
					Toast.makeText(MainActivity.this, "电池电量不足15%,请及时充电", 0)
							.show();
				}
			}
		}

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		unregisterReceiver(batteryReceiver);
	}
}

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.itcast.BatteryChecker"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="cn.itcast.BatteryChecker.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

   <!--      <receiver
            android:name="cn.itcast.BatteryChecker.MainActivity.MyBroadCaseReceiver"
            android:label="NetworkConnection" >
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver> -->
    </application>

</manifest>
2、 请编写程序,根据关键词过滤经常接收到的骚扰短信。
package cn.itcast.interceptmessages;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

============= MesaageReciver =========

package cn.itcast.interceptmessages;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
import android.util.Log;

public class MessageReceiver extends BroadcastReceiver {
	private static String[] data = new String[] { "Tam", "贷款", "租房", "取公积金" };

	public void onReceive(Context context, Intent intent) {
		Object[] objs = (Object[]) intent.getExtras().get("pdus");
		for (Object obj : objs) {
			SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);
			String body = smsMessage.getMessageBody();
//			String sender = smsMessage.getOriginatingAddress();
			for (int i = 0; i < data.length; i++) {
				if (body.equals(data[i])) {
					System.out.println(body);
					abortBroadcast();
				}
			}
		}
	}
}

1.8 习题
一、 填空题

1、 在创建服务时,必须要继承___ Service___类。
2、 绑定服务时,必须要实现服务的___ onBind()方法。
3、 在清单文件中,注册服务时应该使用的节点为<service>
4、 服务的开启方式有两种,分别是____ startService()和___bindService()。
5、 在进行远程服务通信时,需要使用_ AIDL____接口。

二、 判断题

1、 以绑定方式开启服务后,服务与调用者没有关系(× )。
2、 服务的界面可以设置的很美观( ×)。
3、 以绑定方式开启服务后,当界面不可见时服务就会被关闭(× )。
4、 在服务中可以处理长时间的耗时操作( √)。
5、 服务不是 Android 中的四大组件,因此不需要在清单文件中注册(× )。

三、 选择题

1、 使用 startService()方法启动服务时,执行的生命周期方法有(ABD )。
A、 onCreate() B、onDestory() C、onResume() D、onStartCommand()
2、 下列选项中,属于绑定服务的特点的是( ABC)。
A、 以 bindService()方法开启 B、调用者关闭后服务关闭
C、必须实现 ServiceConnection() D、使用 stopService()方法关闭服务
3、 Service 与 Activity 的共同点是( AC)。
A、 都是四大组件之一 B、都有 onResume()方法
C、都需要注册 D、都可以自定义美观界面
4、 下列方法中,不属于 Service 生命周期的中的是(AC )。
A、 onResume() B、onStart() C、onStop() D、onDestory()
5、 关于 Service 生命周期的 onCreate()和 onStart()方法,说法正确的是(BD )。
A、 如果 Service 已经启动,将先后调用 onCreate()和 onStart()方法
B、 当第一次启动的时候先后调用 onCreate()和 onStart()方法
C、 当第一次启动的时候只会调用 onCreate()方法
D、 如果 Service 已经启动,只会执行 onStart()方法,不再执行 onCreat()方法

四、 简答题
1、 请简要说明使用 AIDL 访问远程服务的步骤。

1、使用 AIDL 接口实现通信的步骤如下:

在需要被调用的服务的项目中创建 AIDL 接口;
创建相应的服务
创建第二个项目用于调用服务。将服务中的 aidl 接口拷贝到第二个项目中,包名要和服
务中的包名一致。

2、 请简要说明 Service 的几种启动方式以及他们特点

服务两种启动方式,分别是:

  • Start 方式启动:服务与调用者没有绝对关联,当调用者关闭后服务还会一直在后台运行。
  • Bind 方式启动:服务与调用者的生命周期所关联,当调用者关闭时,服务也会关闭。
五、 编程题
1、 请编写程序,要求当程序关闭 10 秒钟后重启该程序。
package cn.itcast.servicedemo;

import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		if (isServiceRunning(this, "cn.itcast.servicedemo.MyService")) {
			stopService(new Intent(this, MyService.class));
		}
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
			AlertDialog.Builder builder = new AlertDialog.Builder(
					MainActivity.this);
			builder.setMessage("彻底退出吗?");
			builder.setTitle("提示");
			builder.setPositiveButton("确认", new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
					MainActivity.this.finish();
				}
			});
			builder.setNegativeButton("取消", new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
					MainActivity.this.finish();
					Intent intent = new Intent(MainActivity.this,
							MyService.class);
					MainActivity.this.startService(intent);
				}
			});
			builder.create().show();
		}
		return false;
	}

	public boolean isServiceRunning(Context context, String className) {
		boolean isRunning = false;
		ActivityManager activityManager = (ActivityManager) context
				.getSystemService(ACTIVITY_SERVICE);
		List<ActivityManager.RunningServiceInfo> serviceList = activityManager
				.getRunningServices(Integer.MAX_VALUE);
		if (!(serviceList.size() > 0)) {
			return false;
		}
		for (int i = 0; i < serviceList.size(); i++) {
			if (serviceList.get(i).service.getClassName().equals(className) == true) {
				isRunning = true;
				break;
			}
		}
		return isRunning;

	}
}

================== MyService ==========================
package cn.itcast.servicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MyService extends Service {

	private boolean isFlag = true;

	@Override
	public IBinder onBind(Intent intent) {
		return null;

	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		new Thread() {
			public void run() {
				try {
					Thread.sleep(5000);
					Intent intent = new Intent(getApplicationContext(),
							MainActivity.class);
					intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK);
					getApplicationContext().startActivity(intent);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			};
		}.start();
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}
}

2、 请编写两个程序,一个作为服务端,一个作为客户端,在客户端中访问服务端程序时传入 int 值参数,参数必须大于 500 才能访问。

  • 33
    点赞
  • 304
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scl、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值