当前位置: 代码迷 >> Android >> 4,android四大组件基础介绍及打电话,发短信简单应用 &单元测试
  详细解决方案

4,android四大组件基础介绍及打电话,发短信简单应用 &单元测试

热度:650   发布时间:2016-05-01 18:55:54.0
四,android四大组件基础介绍及打电话,发短信简单应用 &单元测试

1,本章是android入门最后一篇,从后面开始将进入进阶阶段。我也会加快更新速度。但愿能保持每天三篇博文的数量。但是是在保证质量的前提下。后面我还会发布一些实际开发中用到的应用案例。敬请关注!

应用组件是一个android应用程序的重要基石。每个组件的应用角度不同,各自负责所特有的功能。并非所有的组件都有实际的切入点,或许与别的组件相互依赖。但都作为一个独立的实体存在,起着特定的作用。有四种不同类型的应用组件。每种类型提供不同的用途,并各自拥有不同的生命周期。

所谓组件你可以这么理解。一个汽车的构成一般有发动机,变速箱,底盘,车身,悬挂这几部门组成。每一部分又都有独立的作用。这和android中得组件类似。

下面是四种类型的应用程序组件:

Activity?

??????字面意思活动,其实就表示与用户交互的一块单屏幕。比如说短信应用程序可能有一个活动,显?

??????示收发短信的列表,另一项活动,可以编写短信。他们是不同的两块屏幕。一个Activity是单独

??????的,它的关注点在于用户能做什么。几乎所有的Activity都与用户交互。在Android中一个程序?可?????????

??????以访问另一个程序中得某个Activity,这在其他语言程序中是不可想象的。极大的节省了系统资源。

??????所有的Activity必须在?AndroidManifest.xml.清单文件中注册方可使用。

????Service??

??????服务是运行在后台的一个组件,提到服务你可能首先想到的是windows中的服务。它在后台默默??

??????的为你提供着你需要的功能。Android中得服务其实与windows中得服务类似,它执行长时间运

??????行的操作,或运程进程执行工作。服务不提供用户界面,例如在后台下载东西,播放音乐,在你

??????播放音乐的同时还可以干其他事情,而不会阻塞用于与其他活动的交互。另一个组件,比如Activity

??????可以启动一个服务,并运行或者绑定到它。

???ContentProvider

??????内容提供者主要用于应用程序的数据共享设置,你可以把数据存储在文件系统中,或者SQLite数?

??????据库上,网络,或者其他的持久性存储位置。你可以访问这些数据或者修改,其他应用程序也可

??????以访问或者修改。(当然这需要内容提供商的允许)。最典型的例子就是android程序中得通讯录

??????它就是通过内容提供者对外共享数据的。

???BroadcastReceiver

??????广播接收者,其实和我们生活中得广播意思相近,在发生什么事情的时候,会以广播的形式告知

??????我们。广播又分为普通广播和有序广播。普通广播是异步的,理论上是同时收到的。你不能对他

??????做任何操作,不能终止。有序广播,在接收到广播时可以加入自己的操作,传递给下一个接收者,

??????也可以终止广播。??举个例子?温州动车追尾了,国家通过电视广播的方式同时告知了我们。你没

??????办法终止它,或者改变它。这属于普通广播。有序广播就是,比如张三的老婆郭美美在动车上,

??????国家通过电话通知张三:“你老婆很不幸在这次事故中丧生了”。张三可以在接到通知时终止它,

??????不告诉他丈母娘,也可以加入自己的操作,然后再告知丈母娘:“妈呀,美美在火车上出了点事,

??????在医院呢。”当然有序广播是有优先级的。国家打电话优先通知她老公。而不是她老母。这在后面

??????会详细讲解!Android系统中最常见的广播电池电量低得时候,收到短信的时候,USB连接的时

??????候等等。

?

先暂时介绍一下四大组件,进阶部分会有详尽讲解。多谢关注!下面来个简单的例子作为入门的结束!

先上图:

?



?


?

<!--EndFragment-->

打电话的主要代码:

mCall.setOnClickListener(new Button.OnClickListener(){	 @Override	 public void onClick(View v) {		String phoneNumber=mPhoneNumber.getText().toString();		//意图 用于激活组件,绑定数据。充 当信使的作用		Intent intent=new Intent();		/*要执行的动作。执行不同的动作的Action去这找		 http://developer.android.com/reference/android/content/Intent.html */		 intent.setAction("android.intent.action.CALL");		 //绑定数据		 intent.setData(Uri.parse("tel:"+phoneNumber));		  //激活打电话组件 通过隐式意图 另外不要忘记在清单文件中注册一下打电话的权限		 startActivity(intent);		}        	        });

?发送短信的主要代码:

mSendButton.setOnClickListener(new Button.OnClickListener(){	@Override	public void onClick(View v) {	          	String phoneNumber=mPhoneNumber.getText().toString();	         	 String content=mMessage.getText().toString();		//得到短信管理器		SmsManager manager=SmsManager.getDefault();		//如果短信内容超过70个字将被分割成多条		ArrayList<String> messages=manager.divideMessage(content);		//循环发送		for(String ms:messages){ 		//注:在模拟器中发送中文短信会乱码 这跟底层的网络有关。不过到真机上就没事了。		      	manager.sendTextMessage(phoneNumber, null, ms, null, null);			Toast.makeText(getApplicationContext(), "发送成功!", 0).show();			}		}        	        });

?之所以还会在讲这一点主要是 这是电话的最基本的两个功能,还有一点在很多应用中还是会用到这些的,比如在CRM,OA,SNS应用上都有可能用上这个功能。最典型的在CRM上,在客户资料上有电话号码这一项,你可以直接加一按钮就能拨打,总比再把号码记下来用内置的拨打吧。

?

2,在实际开发中,开发android应用程序的过程中是需要不断的进行单元测试的,使用JUnit测试框架,是正规android开发比用技术,良好的测试习惯,一是能减少后期维护?和增强软件的健壮性。在JUnit中可以得到组件,可以模拟发送事件和检测程序处理的正确性。

???其实android中也是扩展了JUnit,派生出好几个类倾向于不同情况下的测试。这一点与Spring中初始化容器相似,你可以通过BeanFactory?也可以通过?ApplicationContext?来完成。只不过他们的倾向点不同。在android中你可以使用这些类来完成单元测试:

?Test—TestCase—AndroidTestCase?:多用于对业务逻辑的单元测试

?Test—TestCase—InstrumentationTestCase?:用于测试与组件交互的功能

?Test—TestSuite—InstrumentationTestSuite?:一组测试用例

?TestListener——BaseTestRunner—AndroidTestRunner

?InstrumentationInstrumentationTestRunner

我们常用到的一般是前前两个,你会发现他们的基类都是Test。只不过各自的应用场景不同。

第一步:在AndroidManifest.xml中加入下面蓝色代码:

<!--EndFragment-->

<application android:icon="@drawable/icon" android:label="@string/app_name">    	<!-- 使用的类库 -->    	<uses-library android:name="android.test.runner"/>        <activity android:name="com.iteye.androidtoast.JUnitActivity"                  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>    <!-- 这里的 targetPackage的内容与上面package内容需相同。表示该测试运行在此包下,说白了就是在同一个进程 -->    <instrumentation android:name="android.test.InstrumentationTestRunner"     android:targetPackage="com.iteye.androidtoast" android:label="Tests for My App" />

?第二步,看代码

? 首先是AndroidTestCase的简单应用

??

package com.iteye.service.tests;import junit.framework.Assert;import android.test.AndroidTestCase;import android.util.Log;import com.iteye.service.SomeService;/** * 需要测试类要继承AndroidTestCase * AndroidTestCase 多用于对系统中业务逻辑的测试 * 需要与界面交互的测试一般采用InstrumentationTestCase * @author androidtoast * */public class SomeServiceTest extends AndroidTestCase {		private static final String TAG="SomeServiceTest";	SomeService some;	protected int a;	protected int b;		//初始化测试环境 在实例化当前类的时候自动调用此方法	@Override	protected void setUp() throws Exception {			super.setUp();			some=new SomeService();			a=3;			b=8;	}	//测试结束后调用此方法,用于清理测试环境中得变量	@Override	protected void tearDown() throws Exception {		super.tearDown();		Log.i(TAG, "Test Over!");	}	//测试getAdd方法	public void testAdd()throws Exception{		Log.d(TAG, "testAdd");		int result=some.getAdd(a, b);		Assert.assertEquals(11, result);	}}

?

? InstrumentationTestCase应用代码:

????

package com.iteye.androidtoast.tests;import com.iteye.androidtoast.JUnitActivity;import com.iteye.androidtoast.R;import android.content.Intent;import android.os.SystemClock;import android.test.InstrumentationTestCase;import android.view.View;import android.widget.Button;import android.widget.TextView; /** * InstrumentationTestCase多用于测试与组件相关的操作 * @author androidtoast * */public class JUnitActivityTest extends InstrumentationTestCase {    JUnitActivity mActivityTested;		public JUnitActivityTest() {	}	/**	 * 初始化测试环境	 */	@Override	protected void setUp() throws Exception {		super.setUp();		//意图用于激活Activity		Intent intent = new Intent();		//设置用于激活哪个Activity		intent.setClassName("com.iteye.androidtoast", JUnitActivity.class.getName());		//启动一个新的任务 并在后台运行		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);		//获得Instrumentation 启动一个活动		mActivityTested = (JUnitActivity) getInstrumentation().startActivitySync(intent);	}	//清理资源 	@Override	protected void tearDown() throws Exception {		mActivityTested.finish();//测试完成后关闭Activity		super.tearDown();	}	//测试方法 (其实就是一个点击按钮 然后隐藏自身显示文本这么一简单功能)	public void testClickButtonToShowText() throws Exception {		TextView tv = (TextView) mActivityTested.findViewById(R.id.text);		SystemClock.sleep(2000);//等待两秒		//如果当前的TextView的状态是隐藏的则正确通过		assertEquals("TextView should be Gone before Button Clicking",				View.GONE, tv.getVisibility());				Button btn = (Button) mActivityTested.findViewById(R.id.button);		//在主线程里执行点击按钮这一动作		getInstrumentation().runOnMainSync(new PerformClick(btn));		SystemClock.sleep(2000);		assertEquals("TextView should be Visible after Button Clicking",				View.VISIBLE, tv.getVisibility());			}		private class PerformClick implements Runnable {		Button mBtnClicked;				public PerformClick(Button button) {			mBtnClicked = button;		}				public void run() {			mBtnClicked.performClick();		}	}}

?

1 楼 :倾诉 2011-09-21  
发短信方面我想在字数过多需要拆分多条时,加个弹出对话框提示是否拆分信息,可是一直有错,要怎么debug?加断点都没作用,System打印也打印不出东西?
2 楼 :倾诉 2011-09-21  
manager.sendTextMessage(phoneNumber, null, ms, null, null);里面null代表的是什么啊?
通过findViewById得到mPhoneNumber等控件是在软件安装时执行还是刚打开软件使用的时候执行的啊?
3 楼 androidtoast 2011-09-21  
:倾诉 写道
manager.sendTextMessage(phoneNumber, null, ms, null, null);里面null代表的是什么啊?
通过findViewById得到mPhoneNumber等控件是在软件安装时执行还是刚打开软件使用的时候执行的啊?


不好意思兄弟,回来晚,留言又多没注意你的留言。
sendTextMessage(
            String destinationAddress, String scAddress, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent)

scAddress:服务中心的地址,如果为空的话,默认就SMSC.一般都为空就行
PendingIntent sentIntent:这个参数要设置的话就是,比如 发送成功 或者失败 它会通知你,发送成功或者失败。
PendingIntent deliveryIntent:当信息广播传递给接收方。

findViewById:在打开软件,严格的说打开一个Activity时调用onCreate方法的时候实例化。

短信只要超过70个字,默认就会截断。调试在你需要调试的代码前打一个断点,勇Debug As模式运行android程序,单步调试 。就行。这个说不太清网上有教程你可以看看!
4 楼 :倾诉 2011-09-21  
androidtoast 写道
:倾诉 写道
manager.sendTextMessage(phoneNumber, null, ms, null, null);里面null代表的是什么啊?
通过findViewById得到mPhoneNumber等控件是在软件安装时执行还是刚打开软件使用的时候执行的啊?


不好意思兄弟,回来晚,留言又多没注意你的留言。
sendTextMessage(
            String destinationAddress, String scAddress, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent)

scAddress:服务中心的地址,如果为空的话,默认就SMSC.一般都为空就行
PendingIntent sentIntent:这个参数要设置的话就是,比如 发送成功 或者失败 它会通知你,发送成功或者失败。
PendingIntent deliveryIntent:当信息广播传递给接收方。

findViewById:在打开软件,严格的说打开一个Activity时调用onCreate方法的时候实例化。

短信只要超过70个字,默认就会截断。调试在你需要调试的代码前打一个断点,勇Debug As模式运行android程序,单步调试 。就行。这个说不太清网上有教程你可以看看!


多谢!我忘了要debug,直接点运行了
5 楼 :倾诉 2011-09-21  
大哥有空的时候回复我一下哈
还有个小问题是 我发信息给本身的模拟器却收不到?发给另一台模拟器是可以的.就是5554发给5556成功  发给5554就收不到信息了
6 楼 androidHome 2011-09-26  
有序广播的例子很给力!
  相关解决方案