Android ContentProvider共享数据

ContentProvider的基本概念
a.ContentProvider为存储和读取数据提供了统一的接口
b.使用ContentProvider,应用程序可以实现数据共享
c.android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

1.数据模型
Content Provider 将其存储的数据以数据表的形式提供给访问者,在数据表中每一行为一条记录,每一列为具有特定类型和意义的数据。每一条数据记录都包括一个 "_ID" 数值字段,改字段唯一标识一条数据。

2.Uri
Uri,每一个Content Provider 都对外提供一个能够唯一标识自己数据集(dataset)的公开URI, 如果一个Content Provider管理多个数据集,其将会为每个数据集分配一个独立的URI。所有的Content Provider 的URI 都以"content://" 开头,其中"content:"是用来标识数据是由Content Provider管理的 schema。

在几乎所有的Content Provider 的操作中都会用到Uri,因此一般来讲,如果是自己开发的Content Provider,最好将URI定义为常量,这样在简化开发的同时也提高了代码的可维护性。

我们将Uri分为A,B,C,D 4个部分:

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的"content://"

B:Uri的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的,小写的类名。这个标识在元素的authorities属性中说明:一般是定义该ContentProvider的包.类的名称,如"content://com.lamp.provider.personprovider"

C:路径,Uri下的某一个Item,就像网站一样,主网页下包含很多小网页。这里通俗的讲就是你要操作的数据库中表的名字(比如我操作的表为person),或者你也可以自己定义,记得在使用的时候保持一致就ok了,如"content://com.lamp.provider.personprovider/person"

D:如果Uri中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示对全部记录进行操作,例如content://com.lamp.provider.personprovider/person 针对表中所有记录
content://com.lamp.provider.personprovider/person/5 针对id为5的记录

UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上。

1.常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

2.注册匹配的Uri
//content://com.lamp.provider.personprovider/person 针对表中所有记录,如果匹配该路径,返回1
uriMatcher.addURI(authority, "person", 1);

//content://com.lamp.provider.personprovider/person/# 针对符合条件的记录,如果匹配该路径,返回2
uriMatcher.addURI(authority, "person/#",2);


3.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹 配就返回匹配码,匹配码是调用 addURI()方法传入的第三个参数,假设匹配 content://com.lamp.provider.personprovider/person 路径,返回的匹配码为1。

ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分
parseId(uri)方法用于从路径中获取ID部分


下面是一个小例子来说明ContentProvider的使用
1.新建一个类来继承ContentProvider

package com.lamp.db;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;

import com.lamp.service.DataBaseOpenHelper;

public class PersonContentProvider extends ContentProvider {

private DataBaseOpenHelper dbHelper = null;
private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int ALLPERSON = 1;
private static final int PERSON = 2;
private static final String authority = "com.lamp.provider.personprovider";
private static String TABLENAME = "person";
static{
//content://com.lamp.provider.personprovider/person 针对表中所有记录,如果匹配该路径,返回1
uriMatcher.addURI(authority, TABLENAME, ALLPERSON);

//content://com.lamp.provider.personprovider/person/# 针对符合条件的记录,如果匹配该路径,返回2
uriMatcher.addURI(authority, TABLENAME + "/#", PERSON);
}

@Override
public boolean onCreate() {
dbHelper = new DataBaseOpenHelper(this.getContext());
return true;
}

//删除数据
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
int count = 0;
switch (uriMatcher.match(uri)) {
case ALLPERSON:
count = database.delete(TABLENAME, selection, selectionArgs);
break;
case PERSON:
long personid = ContentUris.parseId(uri);
String where = TextUtils.isEmpty(selection)?"personid=?":selection + " personid=?";
String[] params = new String[]{String.valueOf(personid)};
if(!TextUtils.isEmpty(selection) && selectionArgs!=null){
params = new String[selectionArgs.length+1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length] = String.valueOf(personid);
}
count = database.delete(TABLENAME, where, params);
break;
default:
throw new IllegalArgumentException("参数错误" + uri);
}
return count;
}

@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case ALLPERSON:
return "vnd.android.cursor.dir/personprovider.person";
case PERSON:
return "vnd.android.cursor.item/personprovider.person";
default:
throw new IllegalArgumentException("参数错误" + uri);
}
}

//插入数据
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
long id = 0;
switch (uriMatcher.match(uri)) {
case ALLPERSON:
id = database.insert(TABLENAME, "name", values);
return ContentUris.withAppendedId(uri, id);
case PERSON:
id = database.insert(TABLENAME, "name", values);
String uriString = uri.toString();
uriString = uriString.substring(0, uriString.lastIndexOf("/")) + id;
return Uri.parse(uriString);
default:
throw new IllegalArgumentException("参数错误" + uri);
}
}


//查询数据
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case ALLPERSON:
return database.query(TABLENAME, projection, selection, selectionArgs, null, null, sortOrder);
case PERSON:
long personid = ContentUris.parseId(uri);
String where = TextUtils.isEmpty(selection)?"personid=?":selection + " personid=?";
String[] params = new String[]{String.valueOf(personid)};
if(!TextUtils.isEmpty(selection) && selectionArgs!=null){
params = new String[selectionArgs.length+1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length] = String.valueOf(personid);
}
return database.query(TABLENAME, projection, where, params, null, null, sortOrder);
default:
throw new IllegalArgumentException("参数错误" + uri);
}
}

//更新数据
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
int count = 0;
switch (uriMatcher.match(uri)) {
case ALLPERSON:
count = database.update(TABLENAME, values, selection, selectionArgs);
break;
case PERSON:
long personid = ContentUris.parseId(uri);
String where = TextUtils.isEmpty(selection)?"personid=?":selection + " personid=?";
String[] params = new String[]{String.valueOf(personid)};
if(!TextUtils.isEmpty(selection) && selectionArgs!=null){
params = new String[selectionArgs.length+1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length] = String.valueOf(personid);
}
count = database.update(TABLENAME, values, where, params);
break;
default:
throw new IllegalArgumentException("参数错误" + uri);
}
return count;
}

}



2.在AndroidManifest.xml对ContentProvider进行配置,为了能使其它应用能找到该ContentProvider,ContentProvider采用了android:authorities对它进行唯一标识,你可以把ContentProvider看成是一个网站,authorities就是它的域名

<application android:icon="@drawable/icon" android:label="@string/app_name">
<uses-library android:name="android.test.runner" />

<provider android:name=".PersonContentProvider" android:authorities="com.lamp.provider.personprovider"/>
.....


3.由于我操作的数据是针对数据库,新建一个类继承SQLiteOpenHelper

package com.lamp.service;

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

public class DataBaseOpenHelper extends SQLiteOpenHelper {
private static final String DBNAME = "android";
private static final int VERSION = 1;

public DataBaseOpenHelper(Context context) {
super(context, DBNAME, null, VERSION);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String sql = "create table person (personid integer primary key autoincrement,name varchar(20),age integer)";
sqLiteDatabase.execSQL(sql);
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
String sql = "drop table if exists person";
sqLiteDatabase.execSQL(sql);
onCreate(sqLiteDatabase);
}

}



4.用到的实体bean为Person

package com.lamp.domain;

public class Person {
private Integer personid = null;
private String name = null;
private Integer age = null;
public Person() {
}
public Person(String name,Integer age){
this.name = name;
this.age = age;
}
public Integer getPersonid() {
return personid;
}
public void setPersonid(Integer personid) {
this.personid = personid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "personid:" + this.personid + "name: " + this.name + ", age:" + this.age;
}

}



至此ContentProvider的配置完成,将项目部署到模拟器或者手机中,下面来编写一个新的应用来对上一个应用的数据进行测试

1.新建一个新的项目

package com.lamp.provider;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

public class PersonProviderTestActivity extends Activity {
private static final String TAG = "PersonProviderTestActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ContentResolver cr = this.getContentResolver();
//通过唯一的Uri对特定的应用进行数据的操作
Uri uri = Uri.parse("content://com.lamp.provider.personprovider/person");

//插入数据
/*
uri = Uri.parse("content://com.lamp.provider.personprovider/person");
ContentValues values = new ContentValues();
values.put("name", "kang");
values.put("age", 35);
Uri uris = cr.insert(uri, values);
*/

//查询数据,此处是查询personid=13的记录
/* Uri uri = Uri.parse("content://com.lamp.provider.personprovider/person/13");
Cursor cursor = cr.query(uri, new String[]{"personid","name","age"}, null, null, null);
while(cursor.moveToNext()){
Log.i(TAG, cursor.getInt(0) + " name:" + cursor.getString(1));
}
cursor.close();*/


//测试删除,此处是删除personid=10的记录
uri = Uri.parse("content://com.lamp.provider.personprovider/person/10");
int count = cr.delete(uri, null, null);
Log.i(TAG, String.valueOf(count));


//测试更新,此处是更新personid=14的记录
/*
uri = Uri.parse("content://com.lamp.provider.personprovider/person/14");
ContentValues values2 = new ContentValues();
values2.put("name", "aaaaa");
values2.put("age", 35);
int count = cr.update(uri, values2, null, null);
Log.i(TAG, String.valueOf(count));
*/
}
}


记得在AndroidManifest.xml中注册权限

<uses-permission android:name="android.permission.READ_CONTACTS" />
Android Studio中ContentProvider实现:数据共享机制 在Android系统中,不同的应用程序通常运行在各自独立的沙箱环境中,这意味着它们之间的数据访问受到限制。ContentProvider作为Android提供的一种重要组件,旨在解决不同应用程序之间的数据共享问题。本文的目的是详细介绍在Android Studio中如何使用ContentProvider实现数据共享机制,范围涵盖了ContentProvider的基本概念、实现步骤、实际应用场景以及相关的开发工具和资源。 阅读详情

相关推荐

掌握ContentProvider以实现Android应用间的数据共享

ContentProvider是Android平台上用于管理数据访问的一套机制,它封装了数据,使不同应用程序之间可以通过统一的接口来访问和操作数据。与传统数据库操作不同的是,ContentProvider通过URI(统一资源标识符)来定位数据类型,并允许应用程序通过特定的方法执行CRUD(创建、读取、更新、删除)操作。ContentProvider提供了一种进程间通信的方式,通过ContentResolver接口,应用程序可以无需直接与底层数据存储打交道,就实现数据的共享。

weixin_35677363的博客 355

Android 之 ContentProvider 共享数据库-通讯录

[size=small][color=olive][b]1、使用ContentProvider 共享数据: ContentProvider 类主要方法的作用如下: * public boolean onCreate(); -该方法在ContentProvider 创建后就会被调用,Android开机后,ContentProvider 在其它应用第一次访问时才会被创...

Sunzone 393

Android contentProvider 跨应用程序交换数据

为了演示如何在不同的应用程序中完成数据的访问,在这例子里需要两个不同的应用程序,都打包在里面。为了避免过多的代码,我能省的全省了,很简单的,请注意ReadMe.txt会给你带来惊喜^^。 专为新手而准备。通过编译的。放心下载。

第七章 跨程序数据共享 内容提供器

主要就是学习《第一行代码》内容提供器的笔记

m0_55740492的博客 407

android ContentProvider内容提供者

这个demo详细介绍了ContentProvider内容提供者的用法,详细介ContentProvider怎么进行数据处理,等一下用法,代码有注释,简明易懂

android 通过ContentProvider实现sqlite数据库共享

采用ContentProvider实现android sqlite数据库的共享,包含了本项目对数据库的访问和第三方项目(新建项目)对数据库的访问。

[安卓] 深度掌握Android ContentProvider:数据共享与安全管理

ContentProvider是Android中用于在不同应用程序之间共享数据的组件,它提供了一套标准化的接口,允许应用安全地访问其他应用的数据,同时保护数据的隐私和安全。数据封装:隐藏底层数据存储细节统一接口:提供标准的CRUD操作接口权限控制:通过权限机制保护数据安全数据共享:实现跨应用数据访问观察者模式:支持数据变化通知1. 数据库帮助类context,null,) {// 表名// 列名// 创建联系人表。

2301_77946674的博客 1331

python爬取淘宝数据

python爬取淘宝数据淘宝评论 淘宝评论 打开淘宝,选择打开需要爬取的商品的评论。在谷歌浏览器选择开发者工具,选择network,找到list_detail_rate.htm?itemId=624466733121,点击headers、previews,可以看见相应的评论数据。 爬取一页屏评论代码如下 import re import requests headers = { 'Referer': '在headers中', 'User-Agent': '在

qq_36333776的博客 5797

深入探索Android应用数据共享之ContentProvider

这样可以确保数据的安全性。ContentProvider是Android系统提供的一种在应用之间共享数据的机制,也是 Android 的四大组件之一,可见它在 Android 中的作用非同小可。例如,开发者可以结合Room或SQLite,将ContentProvider作为应用内部数据库的对外接口,为上层的ViewModel和UI层提供标准化的数据访问方式。ContentProvider 可以理解为 Android 应用对外开放的接口,只要是符合它所定义的 URI 格式的请求,均可以正常访问执行操作。

w风雨无阻w的专栏 1851

【大唐杯学习超快速入门】5G技术原理仿真教学——5G网络开通调测与车联网

自用笔记,比较乱。

qq_41224270的博客 1万+

Linux内核4.14版本——drm框架分析(1)——drm简介

drm框架分析

yangguoyu8023的博客 1万+

安卓 ContentProvider 详解:跨应用数据共享的核心方案

ContentProvider 是 Android 系统提供的一种跨进程数据共享机制,它允许一个应用(数据提供方)通过统一的接口向其他应用(数据使用方)暴露自己的数据,同时保证数据访问的安全性。下面通过一个完整案例,实现一个提供用户数据(基于 SQLite)的 ContentProvider,并演示如何跨应用访问。// 1. 定义常量// 唯一标识// 用户表Uri// 2. 初始化UriMatcherstatic {// 匹配用户集合// 匹配单个用户// 3. 数据库帮助类实例。

2501_93564530的博客 1460

Keil5安装教程(保姆级)Keil5mdk安装步骤

6、复制生成的激活码,粘贴在New License ID Code处,点击Add LIC,即可成功激活mdk,显示mdk的使用期限。6、复制生成的激活码,粘贴在New License ID Code处,点击Add LIC,即可成功激活C51,显示mdk的使用期限;3、在安装文件中点击keygen.exe文件,粘贴复制过的CID,选择Target为C51,点击Generate,生成激活码;4、在弹出的界面中会自动安装在安装keil的路径,点击“Next”进行后续安装,安装完成后,点击“Finish”。

m6886258的博客 9万+

Android——使用ContentProvider共享数据

实验目的: (1)能使用ContentProvider共享数据 (2)能使用内容观察者观察其他程序的数据变化 实验内容及原理: 设计一个监测数据库的工程,要求: 能够操作数据库的数据 数据库发生变化时立即响应 创建工程,设计界面和功能,完成项目的调试,并将程序的代码和运行结果记录下来。 实验设备及实验步骤: 实验设备:Windows+Android Studio

Liwo4418的博客 2615

生信入门(六)——单细胞分析(Seurat)

生信入门(六)——单细胞分析(Seurat) 文章目录生信入门(六)——单细胞分析(Seurat)一、数据导入1、数据来源2、数据导入二、标准预处理1、QC和选择细胞进行进一步分析2、规范化数据3、识别高度可变的特征(特征选择)4、缩放数据三、主成分分析(PCA)1、线性降维2、确定数据集的“维度”四、聚类细胞五、非线性降维(UMAP/tSNE)六、寻找差异表达的特征(簇生物标志物) 一、数据导入 1、数据来源 点击此处下载数据 数据说明:分析10X Genomics提供的外周血单细胞(PBMC)数据集,有

羊羊的博客 6万+

手把手教你学基于 Linux 的 NPU 固件开发-第 10 讲:可靠性设计(RAS)——让系统坚如磐石错误检测、纠正与上报机制(ECC、Parity)

组件推荐保护机制备注HBM/DDRScrubbing必须开启,定期巡检片上 SRAMECC(权重/激活值),Parity(指令)权衡面积与可靠性计算单元ABFT或DMR(关键路径)防止计算逻辑错误片上网络CRC重传保证数据传输完整性系统软件AER 上报CE 监控自动恢复闭环管理,杜绝 SDC运维策略预测性维护Checkpoint变被动为主动核心心法(信任硬件,但必须验证。在纳米尺度下,错误是必然发生的物理现象。

MHD0815的博客 90

Android学习之 使用ContentProvider实现数据共享

ContentProvider的基本概念 : 1.ContentProvider为存储和读取数据提供了统一的接口 2.使用ContentProvider,使应用程序间可以实现数据共享 3.android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录,短信等) 一、 使用ContentProvider(内容

小吕丶Code阶区 2820

高渗透率光伏接入配电网的电压越限与谐波治理:基于VSG构网型控制与SVG+APF联合补偿的Simulink仿真研究

本文针对高渗透率光伏接入配电网引发的电压越限和谐波畸变问题,提出了一种分层递进的综合治理方案。通过建立IEEE 33节点配电网的Simulink仿真模型,首先验证了传统跟网型控制下光伏渗透率提高导致的电压越上限(最高达1.08 p.u.)和系统谐波畸变严重(THD达8.72%)问题。进而提出:1)将部分光伏逆变器改造为构网型VSG控制,利用其无功调压能力与虚拟阻抗技术实现本地治理;2)在关键节点加装SVG+APF联合补偿装置进行全局动态无功补偿与谐波滤除。仿真结果表明,该方案能将节点电压控制在0.94-1.

huanghm88的专栏 576

安卓应用间的数据共享:ContentProvider、ContentResolver全解

全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓应用间的数据共享:ContentProvider、ContentResolver全解 ContentProvider用于应用程序向系统公开数据,ContentResolver用于查询这些数据。 Uri代表要操作的数据源,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。 URI一般由三部分组成:访问

1176

MIKE 21 教程 2.2 Domain, Time, Module Selection设置教学

上一节讲解了水动力模型的基本概念与文件创建MIKE 21 教程 2.1水动力模型介绍​本节讲解水动力模型前三个模块的设置此模块需导入之前绘制好的网格文件,导入后可预览网格文件点击上方的Domain Specification可查看网格的数据统计与高程属性,快速检查网格文件有无明显错误 点击上方的Boundary names,可查看之前定义的出入水边界。在网格文件中,我们对边界只能以数字属性进行区分,这里可以对数字属性进行命名,在name中直接修改即可。本实例中我们的2代表入水边界,3代表出水边界。因为博主日

Hello Word 3865

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android中跨程序共享数据-ContentProvider

Android中跨程序共享数据-ContentProvider 之前介绍的持久化技术保存的数据只能在当前应用程序中访问,虽然也提供了操作模式如MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,但由于安全性问题被弃用。现在Android官方更推荐使用ContentProvider技术。 8.1 ContentProvider简介 ContentProvider主要用于不同应用程序之间实现数据共享功能。它提供了一套完整的机制,允许一个程序访问另一个程序的数据,且能保证安全性。不同

m0_56348460的博客 7318

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Android读书笔记之ContentProvider实现数据共享

Android读书笔记之ContentProvider实现数据共享 一.ContentProvider简介 让一个应用程序直接去操作另一个应用程序所记录的数据,比如操作它所记录的SharedPreferences, 文件或数据库等。这种方式不仅比较麻烦,而且还存在严重的安全漏洞。 如何完整开发一个ContentProvider: 1.定义自己的ContentProvider类,该类需要继承Android提供的ContentProvider基类。 2.在AndroidManifest.xml文件中注册这个Co

Danny_llp的博客 1710

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Android学习总结之ContentProvider跨应用数据共享

ContentProvider的面试题和代码实战

2301_80329517的博客 1520

Android学习19--使用ContentProvider实现数据共享

1、数据共享标准:ContentProvider简介 ContentProvider是不同应用程序之间进行数据交换的标准API,ContentProvider以某种Uri的形式对外提供数据,允许其他应用访问或修改数据:其它应用程序使用ContentResolver根据Uri去访问操作指定数据。 ContentProvider也是Android应用的四大组件之一,与Activity、Serv

lixj517990544的专栏 3516
上一篇: Android ListView详解
下一篇: Android POST方式提交数据
lk231_java
博客等级 码龄15年 0粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值