第六章:Android组件之间的信使Intent

Intent自动不同组件的方法

组件名称方法名称
Activity

startActivity()

startActivityForResult()

Srvice

startService()

bindService()

Broadcasts

sendBroadcast()

sendOrderedBroadcast()

sendStickyBroadcast()

Intent由以下几个部分组成:动作(Action)、数据(Data)、分类(Category)、类型(Type)、组件(Component)和扩展信息(Extra)。通过这些可以启动其他组件并携带信息。

Intent在寻找目标组件时有两种方法:第一,通过组件名称直接指定;第二,通过Intent Filter过滤指定。

一、Intent对象及其属性

Intent是对它要完成操作的一种抽象描述,我们可以使用Intent来启动一个Activity、发起一个Broadcast和启动或绑定一个Service。Intent使应用程序代码在运行时动态绑定成为可能,这也降低了不同代码之间的耦合性。Intent最常用的方法是用来启动一个Activity。Intent封装了它要执行动作的属性,这些属性最常见的是Action和Data。

1、Intent的ComponentName属性

后面我们将介绍Intent的查找组件策略,其中一种方法是显示查找,就是直接通过组件名称(Component Name)来查找。Intent的组件对象名称由ComponentName类来封装,组件名称包含包名和类名,被声明在AndroidManifest.xml文件中。

public class TestIntent_ComponentName extends Activity {
    private Button myButton;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        myButton = (Button) findViewById(R.id.componentNameButton01);
        myButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				//实例化组件名称
				ComponentName cn = new ComponentName(TestIntent_ComponentName.this, "mx.android.ch06.TestIntent_ComponentNameAnother");
				Intent intent = new Intent();
				//为Intent设置组件名称属性
				intent.setComponent(cn);
				startActivity(intent);
			}
		});
    }
}

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/componentNameButton01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试Intent的组件名称属性" />
</LinearLayout>
public class TestIntent_ComponentNameAnother extends Activity {
	private TextView myTextView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.other);		
		//获得Intent
		Intent intent = getIntent();
		//获得组件名称属性
		ComponentName cn = intent.getComponent();
		//获得包名称
		String packageName = cn.getPackageName();
		//获得类名称
		String className = cn.getClassName();		
		myTextView = (TextView) findViewById(R.id.componentNameTextView01);
		myTextView.setText("组件包名称:" + packageName + "\n" + "组件类名称:" + className);
	}
}

other.xml

<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/componentNameTextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />
</LinearLayout>

2、Intent的Action属性

Action是指Intent要完成的动作,是一个字符串常量。在Intent类里面定义了大量的Action常量属性。例如,ACTION_CALL(打电话)、ACTION_EDIT(编辑数据)ACTION_BATTERY_LOW(电量低广播Action)等。我们也可以定义自己的Action来使用。
我们可以使用setAction()来设置Intent的Action属性,使用getAction()来获得Intent的Action属性。

1)、自定义Action属性

我们可以为Intent定义一个Action属性来访问,Action属性是一个字符串,我们在程序中定义,并在要访问组件(例如Activity)的InterFilter中声明就可以了。下面的实例将演示如何自定义一个Inter Action属性。

public class TestIntent_Action1 extends Activity {
	//定义Action属性常量
	private static final String MY_ACTION="mx.android.ch06.MY_ACTION";
	private Button myButton;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		myButton = (Button) findViewById(R.id.actionButton01);
		myButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent();
				//为Intent设置Action属性
				intent.setAction(MY_ACTION);
				startActivity(intent);
			}
		});
	}
}

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >    
     <Button
        android:id="@+id/actionButton01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试Intent的Action属性" />
</LinearLayout>

 

public class TestIntent_Action1Another extends Activity {
	private TextView myTextView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.result);
		//获得Intent对象
		Intent intent = getIntent();
		//获得Action
		String action = intent.getAction();
		myTextView = (TextView) findViewById(R.id.actionTextView01);
		myTextView.setText(action);
	}
}

result.xml

<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/actionTextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />
</LinearLayout>

AndroidManifest.xml

添加

	<activity android:name=".TestIntent_Action1Another">
            <intent-filter>
                <action android:name="mx.android.ch06.MY_ACTION" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

2)、访问系统Action属性

例如:我们实现了一个发送短信的程序,在这个程序当中,我们需要选择对方的电话号码,这时候我们可以调用系统电话本来查找电话号码。我们可以使用Intent.ACTION_GET_CONTENT常量调用系统Activity来实现该功能。

public class TestIntent_Action2 extends Activity {
	private Button myButton;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		myButton = (Button) findViewById(R.id.action2Button01);
		myButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent intent = new Intent();
				intent.setAction(Intent.ACTION_GET_CONTENT);
				intent.setType("vnd.android.cursor.item/phone");
				startActivity(intent);
			}
		});
	}
}

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >    
    <Button
        android:id="@+id/action2Button01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试Intent的Action属性" />
</LinearLayout>

3、Intent的Data属性

Intent的Data属性是执行动作的URI和MIME类型,不同的Action有不同的Data数据指定。例如,ACTION_EDIT Action应该和要编辑的文档URI Data匹配,ACTION_VIEW应用和要显示的URI匹配。

Intent的Action和Data属性匹配

Action属性Data属性说明
ACTION_VIEWcontent://contacts/people1显示_id为1的联系人信息
ACTION_DIALcontent://contacts/people1将_id为1的联系人电话号码显示在拨号界面中
ACTION_VIEWtel:123显示电话为123的联系人信息
ACTION_VIEWhttp://www.google.com在浏览器中浏览该网址
ACTION_VIEWfile:///sdcard/mymusic.mp3播放mp3
ACTION_VIEWgeo:39.3256,116.2312显示地图

4、Intent的Category属性
Intent的Category属性是一个执行Action的附加信息。例如,CATEGORY_LAUNCHER意味着在加载程序时,Activity出现在最上面。还有CATEGORY_HOME则表示回到Home界面。

当我们创建一个应用程序的时候,程序第一个加载的Activity中有如下代码:

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

上述代码表明当前的Activity是加载程序时第一个出现的界面。

下面的实例演示了如何回到Home界面。

public class TestIntent_Gategory extends Activity {
	private Button btn;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test_category);
		btn = (Button) findViewById(R.id.categoryButton01);
		btn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				//实例化Intent
				Intent intent = new Intent();
				//添加Action属性
				intent.setAction(Intent.ACTION_MAIN);
				//添加Category属性
				intent.addCategory(Intent.CATEGORY_HOME);
				startActivity(intent);
			}
		});
	}
}

5、Intent的Extras属性

Intent的Extras属性是添加一些组件的附加信息。例如,如果我们要通过一个Activity来发送一个Email,就可以通过Extras属性来添加subject和body。

下面的实例在第一个Activity的EditText中输入年龄,该年龄保存在Intent的Extras属性中,当单击按钮时在第二个Activity中从Intent的属性中取出来显示。

public class TestIntent_Extras extends Activity {
	private EditText myEditText;
	private Button myButton;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		myEditText = (EditText) findViewById(R.id.extrasEditText);
		myButton = (Button) findViewById(R.id.extrasAButton);
		myButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent();
				//设置Intent的class属性,跳转到另一个Activity
				intent.setClass(TestIntent_Extras.this, TestIntent_ExtrasResult.class);
				//为Intent添加额外信息
				intent.putExtra("age", myEditText.getText().toString());
				startActivity(intent);
			}
		});
	}
}
public class TestIntent_ExtrasResult extends Activity {
	private TextView myTextView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.result);
		myTextView = (TextView) findViewById(R.id.extrasresultTextView01);
		Intent intent = getIntent();
		myTextView.setText(intent.getStringExtra("age"));
	}
}

二、标准系统Activity Action应用

Activity Action常量

常量名称常量值意义
ACTION_MAINandroid.intent.action.MAIN应用程序的入口
ACTION_VIEWandroid.intent.action.VIEW显示数据给用户
ACTION_ATTACH_DATAandroid.intent.action.ATTACH_DATA指明附加给其他地方的一些数据
ACTION_EDITandroid.intent.action.EDIT显示可编辑的数据
ACTION_PICKandroid.intent.action.PICK选择数据
ACTION_CHOOSERandroid.intent.action.CHOOSER显示一个Activity选择器
ACTION_GET_CONTENTandroid.intent.action.GET_CONTENT获得内容
ACTION_DIALandroid.intent.action.GET_CONTENT获得打电话面板
ACTION_CALLandroid.intent.action.DIAL直接打电话
ACTION_SENDandroid.intent.action.SEND直接发送短信
ACTION_SENDTOandroid.intent.action.SENDTO选择发送短信
ACTION_ANSWERandroid.intent.action.ANSWER应答电话
ACTION_INSERTandroid.intent.action.INSERT插入数据
ACTION_DELETEandroid.intent.action.DELETE删除数据
ACTION_RUNandroid.intent.action.RUN运行数据
ACTION_SYNCandroid.intent.action.SYNC同步数据
ACTION_PICK_ACTIVITYandroid.intent.action.PICK_ACTIVITY选择Activity
ACTION_SEARCHandroid.intent.action.SEARCH搜索
ACTION_WEB_SEARCHandroid.intent.action.WEB_SEARCHWeb搜索
ACTION_FACTORY_TESTandroid.intent.action.FACTORY_TEST工厂测试入口点


1、和打电话相关的标准Activity Action应用

这里我们通过一个实例来演示和打电话相关的标准Activity Action的应用,我们可以通过这些标准Activity Action来查看联系人信息(ACTION_VIEW)、编辑联系人信息(ACTION_EDIT)、显示打电话界面(ACTION_DIAL)、直接拨打电话(ACTION_CALL)等。

下面的实例定义一个Activity继承ListActivity,在ListView中显示不同的应用类型。当该选择项被选择时启动一个Activity演示效果。

public class TestActivityAction_Tel extends ListActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//菜单项数组
		String[] menus = {"查看电话信息","编辑电话信息","显示拨打电话界面","直接打电话","访问浏览器","访问地图"};
		//将菜单项数组设置为ListView的列表项展示
		setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,menus));
		getListView().setTextFilterEnabled(true);
	}
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		//实例化Intent
		Intent intent = new Intent();
		//声明Uri
		Uri uri;
		//声明数据字符串
		String data;		
		switch(position){
			//查看_id为1的用户电话信息
			case 0:
				//字符串Uri
				data = "content://contacts/people/1";
				//将字符串Uri转换为Uri实例
				uri = Uri.parse(data);
				//设置Intent的Action属性
				intent.setAction(Intent.ACTION_VIEW);
				//设置Intent的Data属性
				intent.setData(uri);
				//启动Activity
				startActivity(intent);
				break;
			//编辑_id为1的用户电话信息
			case 1:
				data = "content://contacts/people/1";
				uri = Uri.parse(data);
				intent.setAction(Intent.ACTION_EDIT);
				intent.setData(uri);
				startActivity(intent);
				break;
			//显示拨打电话界面
			case 2:
				data = "tel:18217301798";
				uri = Uri.parse(data);
				intent.setAction(Intent.ACTION_DIAL);
				intent.setData(uri);
				startActivity(intent);
				break;
			//直接拨打电话
			case 3:
				data = "tel:18217301798";
				uri = Uri.parse(data);
				intent.setAction(Intent.ACTION_CALL);
				intent.setData(uri);
				startActivity(intent);
				break;
			//访问浏览器
			case 4:
				data = "http://www.google.com";
				uri = Uri.parse(data);
				intent.setAction(Intent.ACTION_VIEW);
				intent.setData(uri);
				startActivity(intent);
				break;
			//访问地图
			case 5:
				data = "geo:39.92,116.46";
				uri = Uri.parse(data);
				intent = new Intent(Intent.ACTION_VIEW,uri);
				startActivity(intent);
				break;
			default:
				break;
		}
	}
}

2、访问浏览器和地图

浏览器的URI格式是:http://www.xxx.yyy。地图URI的格式是:geo:经度,纬度。

实例在上面例子中

3、发邮件

我们可以使用内置的Gmail引擎来发送邮件,也可以使用SMTP来发送E-mail。

public class TestActivityAction_SendEmail extends Activity {
	private EditText sendToText,subjectText,contentText;
	private Button myButton;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		sendToText = (EditText) findViewById(R.id.emailSendToPeople);
		subjectText = (EditText) findViewById(R.id.emailSubject);
		contentText = (EditText) findViewById(R.id.emailContent);
		myButton = (Button) findViewById(R.id.emailSendButton);
		
		myButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				//邮件目标地址
				String to = sendToText.getText().toString();
				//邮件主题
				String subject = subjectText.getText().toString();
				//邮件内容
				String content = contentText.getText().toString();
				//创建Intent
				Intent emaillIntent = new Intent(android.content.Intent.ACTION_SEND);
				//设置内容类型
				emaillIntent.setType("plain/text");
				//设置额外信息
				emaillIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{to});
				emaillIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
				emaillIntent.putExtra(android.content.Intent.EXTRA_TEXT, content);
				//启动Activity
				startActivity(Intent.createChooser(emaillIntent, "发送邮件..."));
			}
		});
	}
}

main.xml

<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/emailTextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="收件人:" />    
    <EditText
        android:id="@+id/emailSendToPeople"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="" />    
    <TextView
        android:id="@+id/emailTextView02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="主题:" />    
    <EditText
        android:id="@+id/emailSubject"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="" />    
    <TextView
        android:id="@+id/emailTextView03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="内容:" />    
    <EditText
        android:id="@+id/emailContent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="" />
    <Button
        android:id="@+id/emailSendButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送" />    
</LinearLayout>

3、Intent的实现策略

Intent是如何找到目标组件的呢?Intent寻找目标组件的方式可以分为两种。一种是显式Intent,这种方式是通过指定Intent组件名称来实现的,这种方式在我们上面讲到的Intent组件名称属性时提到过,它一般用在源组件知道目标组件名称的前提下,一般是在相同应用程序内容部实现的。那么不同的应用程序之间呢?我们并不知道目标组件的名称,又该如何找到目标组件呢?在这种情况下,我们使用第二种方式,隐式Intent,这种方式是通过Intent Filter实现的。

在使用Intent Filter进行过滤Intent通常考虑的三个属性是Action、Data和Category。

对于显式Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的Action、Category、Data这三个属性来进行判断的,判断方法说明如下:

1)、Action测试

如果Intent指明定了Action,则目标组件IntentFilter的Action列表中就必须包含这个Action,否则不能匹配。如果Intent中没有指定Action,则Action测试自动通过。

Action的声明在AndroidManifest.xml中。每个Android组件(例如Activity、Service等)都会有一个 <intent-filter>元素来声明Intent过滤器。Action作为 <intent-filter>的子元素来声明,例如:

	<intent-filter>
                <action android:name="mx.android.ch06.TEST_ACTION1" />
                <action android:name="mx.android.ch06.TEST_ACTION2" />
                <action android:name="mx.android.ch06.TEST_ACTION3" />
	</intent-filter> 

</intent-filter> 列表中的Action不能为空,否则程序将阻塞不能通过。如果Intent对象指定了一个Action属性,那么要想通过Action测试,Intent对象指定的属性必须和IntentFilter中的一个匹配,否则不能通过测试。如果Intent对象没有指定Action属性,则自动通过测试。

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >    
    <Button
        android:id="@+id/actiontest01Button01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试Intent Filter" />
</LinearLayout>

main1.xml

<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/actiontest02TextView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试 Intent Filter" />
</LinearLayout>

AndroidManifest.xml

	<intent-filter>
                <action android:name="mx.android.ch06.TEST_ACTION1" />
                <action android:name="mx.android.ch06.TEST_ACTION2" />
                <action android:name="mx.android.ch06.TEST_ACTION3" />
                
                <data android:scheme="content" android:path="mx.android.ch06/abc" />
                <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
public class TestActionTest01 extends Activity {
	private static final String ACTION1 = "mx.android.ch06.TEST_ACTION1";
	private static final String ACTION2 = "mx.android.ch06.TEST_ACTION2";
	private static final String ACTION3 = "mx.android.ch06.TEST_ACTION3";
	private static final String CATEGORY1 = "mx.android.ch06.CATEGORY1";	
	private Button btn;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test_actiontest01);
		btn = (Button) findViewById(R.id.actiontest01Button01);
		btn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent();
				//1、Action测试(去掉Intent的Action属性,添加一个Data属性,仍然能成功启动)
				//intent.setAction(ACTION1);
				Uri data = Uri.parse("content://mx.android.ch06/abc");
				intent.setData(data);
				//2、Category测试
				intent.addCategory(CATEGORY1);
				//3、Data测试
				intent.setAction("android.intent.action.VIEW");
				intent.setData(Uri.parse("http://www.google.com"));
				startActivity(intent);
			}
		});
	}
}

这里我们声明了三个字符串常量,分别和AndroidManifest.xml中的Action属性相对应,并在onClick()方法中实例化Intent对象,为其设置Action属性。

2)、Category测试

Category属性也是作为 <intent-filter>子元素来声明的。例如:

<intent-filter>
	<category android:name="android.intent.category.DEFAULT" />
         <category android:name="android.intent.category.BROWSABLE" />
</intent-filter> 

在Intent对象中出现的Category属性在InterFilter中必须出现,否则不能通过测试,在上面的实例基础上,我们在Activity中为Intent添加了一个Category(见上面实例),在AndroidManifest.xml<intent-filter>中添加了三个<category>。

	       <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="mx.android.ch06.CATEGORY1" />

注意:“android.intent.category.DEFAULT”属性是启动Activity默认的属性,这个必须添加,否则Category测试失败。

3)、Data测试

Data属性是Android要访问的数据,和Action和Category声明方式相同,也是在 <intent-filter>中。

Data属性的生命值中要指定访问数据的URI和MIME类型。也可以在<category>元素中通过一些属性(android:scheme、android:path、android:port、android:host等)来设置,通过这些属性来对应一个典型的URI格式:scheme://host:port/path,例如:http://www.google.com

Data测试规则说明如下:

  • 如果Intent对象中没有包含Data,<intent-filter>列表中也没有包含Data,则通过测试,这种情况一般是通过Action属性来过滤的。
  • 如果Intent对象包含URI但是没有包含类型,并且类型不能从URI中自动识别,那么<intent-filter>列表中也只能包含URI,这样才能通过测试。
  • 相反,如果Intent对象只包含类型,没有包含URI,那么在<intent-filter>中也只能包含类型,不能包含URI。
  • 如果Intent对象中既包含URI又包含Type,那么<intent-filter>中也必须二者都包含才能通过测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值