Activity定义

Activity, 直译为活动, 它是Android定义的四大应用组件之一,也是最重要用得最多的
用来提供一个能让用户操作并与之交互的界面
一个应用有多个界面, 也就是包含多个Activity
打电话,发短信, 拍照,发邮件等功能都是通过Activity来做的

组件的特点

它的类必须实现特定接口或继承特定类

需要在配置文件中配置其全类名

它的对象不是通过new来创建的, 而是系统自动创建的

它的对象具有一定的生命周期, 它的类中有对应的生命周期回调方法
比如我们之前学习的网页开发中的Servlet接口就是组件的接口
Servlet是一个interface, 我们的Servlet类都必须是此接口的实现类,是一种服务器端的组件, 用来处理 客户端(浏览器)提交的请求, 并返回一个响应界面
两个进行对比:

Servlet

Activity

组件

服务器端组件

Android客户端组件

接口

Servlet接口

Activity类

注册

web.xml

AndroidManifest.xml

发出的请求源

浏览器

手机屏幕

Intent

这个不是Android中的四大应用组件之一,但是和Activity相关性很大
Intent, 直译为意图, 也就是你想要做什么或想要去哪?
Intent是Activity, Service和BroadcastReceiver这三个应用组件之间进行通信的信使,
例如: 我要在Activity中启动另一个Actvity, 就必须使用Intent对象
意图对象还可以携带数据

Intent的分类

显示意图 :
明确指定的目标组件的意图,比如其他应用要明确打开微信
创建对象 : Intent(Context context, Class clazz)
何时使用 : 当操作当前自己应用的组件时使用

隐式意图 :
没有明确指定目标组件的意图,
比如图片要分享,但是分享的路径有很多,比如分享到微信,邮件…
创建对象 : Intent(String action)
何时使用 : 当操作其它应用的组件时使用

IntentFilter(意图过滤器)

这个就是上面不是有一个意图吗?就是想跳转到其他的Activity,但是手机这么知道跳转到哪一个呢?那就是意图过滤器起作用了.
就好像我们之前学习的Servlet,每一个请求(对应这里的意图)都要首先和< url-pattern>(对应这里的意图过滤器)就行匹配,如果匹配成功,就给< url-pattern>对应的servlet进行处理

在配置Activity时, 可以为Activity指定一个IntentFilter的配置
如果你的Activity希望其它应用能访问到, 需要配置< intent-filter>
如果你想启动其它应用的界面你必须用隐式intent, 且目标界面Activty配置了< intent-filter>
比如想让这个activity成为应用的第一个活动,就设置

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

对应的常见API

Activity: 活动
startActivity(Intent intent): 一般启动Activity
startActivityForResult(int reqCode, Intent intent): 带回调启动Activity
onActivityResult(int reqCode, int resultCode, Intent data): 回调方法
setResult(int resultCode, Intent data): 设置要返回的结果
finish(): 结束当前Activity
getIntent():
Intent: 意图
Intent(Context packageContext, Class<?> cls) : 用于创建显示意图对象
Intent(String action): 用于创建隐式意图对象
putExtra(String name, Xxx value): 保存额外数据
Xxx getXxxExtra(String name): 获取额外数据
setData(Uri data):
View: 代表视图的根基类
setOnClickListener(OnClickListener listener): 设置点击监听
setOnLongClickListener(OnLongListener listener):
Activity生命周期相关方法
onCreate()
onStart()
onResume()
onPause()
onRestart()
onStop()
onDestory()
设置点击监听的2种方式     
方式一: Activity中添加监听:
view.setOnClickListener(OnClickListener listener);
方式二: 布局添加监听:
layout中: android:onclick=“方法名”
Activity中: public void 方法名(View v) { }

设置长按监听
view.setOnLongClickListener(OnLongClickListener listener)

利用到反射技术的

1.就比如之前使用过的意图(显式的)它创建对象时候是使用Intent(Context context,Class c)
2.比如之前的布局文件,之前只是写一个名字Button就知道要创建Button对象,也是通过反射的
3.功能清单文件中,包名不用写,也是通过反射技术的

应用上面的例子

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

<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="9" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name=".Message"
android:label="@string/title_activity_message" >
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Message2"
android:label="@string/title_activity_message2" >
</activity>
</application>

</manifest>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<EditText
android:id="@+id/editTextMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="携带的信息"
>

<requestFocus />
</EditText>

</LinearLayout>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
android:onClick="back1"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="带结果返回"
android:onClick="back2"/>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="需要携带的信息"
>

<requestFocus />
</EditText>

</LinearLayout>

<Button
android:id="@+id/Button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="一般启动" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="回调启动" />

</LinearLayout>
package com.example.hello;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Message extends Activity implements OnClickListener
{
/*
* 步骤:
* 1.建好界面布局
* 2.实现Activity的功能:
* 1)定义所有的需要操作的视图对象并且初始化
* 2)设置监听事件,实现回调逻辑
* 3.实现一般的跳转
* 1)定义好第二个的界面
* 1)布局
* 2)定义Activity类
* 3)在功能清单配置好
* 4)重写onCreate方法
* 2)启动界面二
* 1)创建显式的Intent对象
* 2)通过Intent对象携带额外数据
* 3)启动Activity
* 4)在另外一个界面得到Intent对象
* 5)读取到数据后显示出来
*/
private EditText editText1;
private Button Button1;
private Button Button2;


@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.message);
//初始化视图对象
editText1=(EditText) findViewById(R.id.editText1);
Button1=(Button) findViewById(R.id.Button1);
Button2=(Button) findViewById(R.id.button2);

//设置监听事件
Button1.setOnClickListener(this);
Button2.setOnClickListener(this);
}


@Override
public void onClick(View v)
{
if(v==Button1)
{
Toast.makeText(this, "一般启动", 0).show();
//创建对象
Intent intent = new Intent(this, Message2.class);
//携带数据
intent.putExtra("message", editText1.getText().toString());
//启动Activity
startActivity(intent);
}
else if(v==Button2)
{
Toast.makeText(this, "回调启动", 0).show();
//创建对象
Intent intent = new Intent(this, Message2.class);
//携带数据
intent.putExtra("message", editText1.getText().toString());
//带回调启动Activity
int requestCode=1;
startActivityForResult(intent, requestCode);
}
}
//带结果的返回是父类的方法,只需要重写就行
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==1&&resultCode==2)
{
String string = data.getStringExtra("result").toString();
editText1.setText(string);
}
}
}
package com.example.hello;

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

public class Message2 extends Activity
{
private EditText edittext;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message2);

edittext=(EditText) findViewById(R.id.editTextMessage);
Intent intent = getIntent();
edittext.setText(intent.getStringExtra("message"));

}
//使用的是另外一种方法添加监听
public void back1(View v)
{
finish();
}
public void back2(View v)
{
//在关闭之前先准备好要返回的值,然后将它设置好就关闭当前Activity
int resultCode=2;
Intent data=new Intent();
data.putExtra("result", edittext.getText().toString());
setResult(resultCode, data);
finish();
}

}

启动一个Activity的流程

Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_数据

Activity界面的四种状态和回调方法

四种状态

运行状态: 可见也可操作

暂停状态: 可见但不可操作,就比如在当前窗口有一个警告的窗口弹出来,
当前窗口还能看到,但是操作不了当前窗口,只能操作那个警告的窗口

停止状态: 不可见,但对象存在,就比如按了home键返回桌面

死亡状态:

回调方法

onCreate()
onStart()
onResume()
onPause()
onRestart()
onStop()
onDestory()

Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_数据_02

Activity的加载模式(launchMode)

在Android中, 启动一个Activity有时需要总是创建一个新对象, 有时需要复用已有的对象, 
可以通过在配置activity时通过launchMode属性指定
下面以三个Activity来说明,分别是1,2,3这三个Activity,它们之间都可以互相调用
launchMode属性值(4):

standard:
标准模式,每次调用startActivity()方法就会产生一个新的实例。
1调用2就会产生2对象放在栈顶,然后
2调用1也会重新产生一个1对象放在栈顶,然后
1调用1自己也会产生一个新的1的对象放在栈顶
栈的对象有1-2-1-1

singleTop:
如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例;如果不位于栈顶,会产生一个新的实例。
1调用1就什么也没有产生,栈顶只有1自己,然后
1调用2就会产生2对象放在栈顶,然后
2调用1也会重新产生一个1对象放在栈顶,然后
栈的对象有1-2-1

singleTask:
只有一个实例, 默认在当前Task中
1调用1就什么也没有产生,栈顶只有1自己,然后
1调用2就会产生2对象放在栈顶,然后
2调用1也会销毁2,暴露1出来给你看,然后
栈的对象有1,因为2已经销毁了

singleInstance:
只有一个实例, 创建时会新建一个栈, 且此栈中不能有其它对象
这个特殊时候还是挺好用的
例如给2设置singleInstance,其他的不设置
1调用2,就会产生新的一个栈并且放在第一个栈(当前栈)的前面
现在就是显示2
2调用3,那么3就会在第一个栈的栈顶创建,
现在显示的是第一个栈的栈顶的3
现在第一个栈在新建的栈的前面
现在销毁3,显示的是1
销毁1,现在才显示2

如何找某个应用的action

现在以Phone为例

先是让手机模拟器处于桌面,

新建一个LogCat的过滤器,过滤出来Tag是ActivityManager的输出内容

然后点击手机模拟器的电话应用

LogCat的内容是

Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_android_03


里面的ActivityManager跟你说启动一个com.android.dialer/.DialtactsActivity

现在我们知道启动的是DialtactsActivity这样一个类,

然后去到Android的原码进行查找是哪一个应用的

Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_数据_04


Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_xml_05


Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_android_06


然后找到这个应用的清单文件

Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_xml_07


从里面找DialtactsActivity就可以找到对应的action,就是对应的​​android.intent.action.DIAL​​,这不就好起来了吗?

Android四大组件之Activity:定义,Intent意图,IntentFilter意图过滤器,Activity启动流程,状态和回调,加载模式launchMode,查看应用action_android_08

例子

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

<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="9" />
<!-- 打开打电话的权限 -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<!-- 打开发短信的权限 -->
<uses-permission android:name="android.permission.SEND_SMS"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name=".Message"
android:label="@string/title_activity_message" >
>



</activity>
<activity
android:name=".Message2"
android:label="@string/title_activity_message2" >
</activity>
<activity
android:name=".First"
android:label="@string/title_activity_first" >
</activity>
<activity
android:name=".Second"
android:label="@string/title_activity_second" >
</activity>
<activity
android:name=".Third"
android:label="@string/title_activity_third" >
</activity>
<activity
android:name=".Phone"
android:label="@string/title_activity_phone" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电话号码: " />

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

<requestFocus />
</EditText>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="短信内容: " />

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

<requestFocus />
</EditText>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<Button
android:id="@+id/call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打电话" />

<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发短信" />
</LinearLayout>

</LinearLayout>
package com.example.hello;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Phone extends Activity implements OnLongClickListener
{
private EditText editTextPhone;
private EditText editTextMessage;
private Button call;
private Button send;
private OnClickListener onClickListener=new OnClickListener()
{

@Override
public void onClick(View v)
{
if(v==call)
{
Toast.makeText(Phone.this, "点击打电话", 0).show();
/*
* 创建一个Intent(隐式),因为是不同的应用之间的调用了
* 10-03 09:07:04.041: I/ActivityManager(387): Displayed com.android.dialer/.DialtactsActivity: +1s254ms
* <action android:name="android.intent.action.DIAL" />
*/
String action="android.intent.action.DIAL";
action=Intent.ACTION_DIAL;//值和上面是一样的
Intent intent=new Intent(action);

//设置携带的数据,因为电话应用数据有约束<data android:scheme="tel" />,所以使用setData的方式
String number = editTextPhone.getText().toString();
intent.setData(Uri.parse("tel:"+number));

startActivity(intent);
}
else if(v==send)
{
Toast.makeText(Phone.this, "点击发短信", 0).show();
String action=Intent.ACTION_SENDTO;
Intent intent=new Intent(action);
String number=editTextPhone.getText().toString();
intent.setData(Uri.parse("smsto:"+number));
String sms=editTextMessage.getText().toString();
intent.putExtra("sms_body", sms);
startActivity(intent);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone);

editTextPhone=(EditText) findViewById(R.id.editTextPhone);
editTextMessage=(EditText) findViewById(R.id.editTextMessage);
call=(Button) findViewById(R.id.call);
send=(Button) findViewById(R.id.send);

//新的方法,设置成员变量进去的
call.setOnClickListener(onClickListener);
send.setOnClickListener(onClickListener);

call.setOnLongClickListener(this);
send.setOnLongClickListener(this);
}
@Override
public boolean onLongClick(View v)
{
if(v==call)
{
Toast.makeText(Phone.this, "长按打电话", 0).show();

/*
* 和上面的点击一样的,就是action不一样
* 只不过你会遇到权限的问题,需要给这个应用打电话的权限
* 在功能清单文件里面配置
* <!-- 打开打电话的权限 -->
* <uses-permission android:name="android.permission.CALL_PHONE"/>
* 或者直接在功能清单文件的下面找到permissions按钮,在里面找到你需要的
* 权限,然后直接添加,然后软件就会帮你生成对应的代码
*/
String action=Intent.ACTION_CALL;
Intent intent=new Intent(action);
intent.setData(Uri.parse("tel:"+editTextPhone.getText().toString()));
startActivity(intent);
}
else if(v==send)
{
Toast.makeText(Phone.this, "长按发短信", 0).show();
SmsManager smsManager=SmsManager.getDefault();

String number=editTextPhone.getText().toString();
String text=editTextMessage.getText().toString();
/*
* * @param destinationAddress the address to send the message to
* 这个destinationAddress就是电话号码
*
* * @param scAddress is the service center address or null to use
* the current default SMSC
* scAddress就是服务中心的地址,没有就默认
*
* @param text the body of the message to send
* text是短信的内容
*
* sentIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is successfully sent, or failed.
* The result code will be <code>Activity.RESULT_OK</code> for success,
* 后面两个就是短息发送成功和阅读成功的回执
*/
smsManager.sendTextMessage(number, null, text, null, null);
}

return true;//返回true,不会再触发点击事件,代表此事件已经被消费了
}
}