Bmob的使用

一.Bmob云服务简介

Bomb是一个移动后端云服务平台,提供了后端服务器的数据服务,文件服务,推送服务等,让开发者可以专注客户端的开发,从而达到快速构建一个APP的目的。

二.入门与BmobSDK集成

1.快速入门

①首先注册Bmob帐号
在网址栏输入www.bmob.cn或者在百度输入Bmob进行搜索,打开Bmob官网后,点击右上角的“注册”,在跳转页面填入你的姓名、邮箱、设置密码,确认后到你的邮箱激活Bmob账户,你就可以用Bmob轻松开发应用了。
②网站后台创建应用
登录账号进入bmob后台后,点击后台界面左上角“创建应用”,在弹出框输入你应用的名称,然后确认,你就拥有了一个等待开发的应用。
在这里插入图片描述
③获取应用密钥和下载SDK
创建应用
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在应用key中可以获取所需要的密钥

Application ID:SDK初始化必须用到此密钥
REST API Key:REST API请求中HTTP头部信息必须附带密钥之一
Secret Key:是SDK安全密钥,不可泄漏,在云函数测试云函数时需要用到
Master Key:超级权限Key。应用开发或调试的时候可以使用该密钥进行各种权限的操作,此密钥不可泄漏

④SDK的下载与导入
1)下载SDK(下载地址:http://www.bmob.cn/site/sdk#android_sdk)
2)推荐使用自动导入,手动导入会出现jar冲突等
首先在 Project 的 build.gradle 文件中添加 Bmob的maven仓库地址

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }
}

allprojects {
    repositories {
        jcenter()
        //Bmob的maven仓库地址--必填
        maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
    }
}

然后在app的build.gradle文件中添加依赖文件

android {
useLibrary 'org.apache.http.legacy'
}
	
dependencies {
    implementation 'cn.bmob.android:bmob-sdk:3.7.3-rc1'
    implementation "io.reactivex.rxjava2:rxjava:2.2.2"
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
    implementation 'com.squareup.okio:okio:2.1.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
}

注:

[1]、v3.6.8-rc2开始,远程仓库中数据SDK包含了libbmob.so及自动更新组件所需要的资源文件。

[2]、每个版本的im依赖特定版本的bmob-sdk:

bmob-im:1.1.8--->bmob-sdk:3.3.5
bmob-im:1.1.9--->bmob-sdk:3.4.3
bmob-im:2.0.1--->bmob-sdk:3.4.6-0304
bmob-im:2.0.2--->bmob-sdk:3.4.6-0304
bmob-im:2.0.3--->bmob-sdk:3.4.6
bmob-im:2.0.4--->bmob-sdk:3.4.6
bmob-im:2.0.5--->bmob-sdk:3.4.7-aar
bmob-im:2.0.6--->bmob-sdk:3.5.0

其中

bmob-sdk:3.4.6-0304是Bmob Android SDK的过渡版本,主要用于NewIM_v2.0.1及v2.0.2
bmob-sdk:3.4.6的相关依赖包可见注释[3]
[3]、bmob-sdk:3.4.6依赖以下包:

implementation 'cn.bmob.android:bmob-sdk:3.4.6'
implementation 'com.squareup.okhttp:okhttp:2.4.0'//CDN文件服务使用okhttp相关包进行文件的上传和下载(必填)
implementation 'com.squareup.okio:okio:1.4.0'

[4]、bmob-sms适用于只需要使用Bmob短信功能的开发者,而bmob-sdk内部包含了bmob-sms的短信功能,请不要重复添加。

[5]、BmobSDK的官方仓库:bmob-android-sdk,开发者可到此仓库查看最新发布的各版本SDK,我们会尽量与官网发布的SDK保持同步更新。

2.SDK集成

所需权限说明

<!--允许联网 --> 
<uses-permission android:name="android.permission.INTERNET" /> 
<!--获取GSM(2g)、WCDMA(联通3g)等网络状态的信息  --> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<!--获取wifi网络状态的信息 --> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<!--保持CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
<uses-permission android:name="android.permission.WAKE_LOCK" /> 
<!--获取sd卡写的权限,用于文件上传和下载-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许读取手机状态 用于创建BmobInstallation--> 
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

配置AndroidManifest.xml

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

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

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<uses-permission android:name="android.permission.WAKE_LOCK" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    <activity
        android:name="cn.bmob.example.MainActivity"
        android:screenOrientation="portrait"
        android:label="@string/app_name">

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


    <activity
        android:name=".CreateActivity"
        android:screenOrientation="portrait">
    <activity
        android:name=".DeleteActivity"
        android:screenOrientation="portrait">
    <activity
        android:name=".UpdateActivity"
        android:screenOrientation="portrait">
    <activity
        android:name=".FindActivity"
        android:screenOrientation="portrait">
</application>
</manifest>

配置ContentProvider

<application>
···
<provider
    android:name="cn.bmob.v3.util.BmobContentProvider"
    android:authorities="你的应用包名.BmobContentProvider">
</provider>
···
</application>

初始化BmobSDK
在你应用程序启动的Application的onCreate()方法中初始化Bmob功能

Bmob.initialize(this, "Your Application ID");

三.Bmob数据库的增删查改

1.添加数据

创建JavaBean

public class Person extends BmobObject {
private String name;
private String address;

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;
}
}

添加数据

Person p2 = new Person();
p2.setName("lucky");
p2.setAddress("北京海淀");
p2.save(new SaveListener<String>() {
@Override
public void done(String objectId,BmobException e) {
    if(e==null){
        toast("添加数据成功,返回objectId为:"+objectId);
    }else{
        toast("创建数据失败:" + e.getMessage());
    }
}
});

2.删除数据

Person p2 = new Person();
p2.setObjectId("6b6c11c537");
p2.delete(new UpdateListener() {

@Override
public void done(BmobException e) {
    if(e==null){
        toast("删除成功:"+p2.getUpdatedAt());
    }else{
        toast("删除失败:" + e.getMessage());
    }
}

});

3.查询数据

//查找Person表里面id为6b6c11c537的数据
BmobQuery<Person> bmobQuery = new BmobQuery<Person>();
bmobQuery.getObject("6b6c11c537", new >QueryListener<Person>() {
@Override
public void done(Person object,BmobException e) {
    if(e==null){
        toast("查询成功");
    }else{
        toast("查询失败:" + e.getMessage());
    }
}
});

4.修改数据

//更新Person表里面id为6b6c11c537的数据,address内容更新为“北京朝阳”
Person p2 = new Person();
p2.setAddress("北京朝阳");
p2.update("6b6c11c537", new UpdateListener() {

@Override
public void done(BmobException e) {
    if(e==null){
        toast("更新成功:"+p2.getUpdatedAt());
    }else{
        toast("更新失败:" + e.getMessage());
    }
}

});

四.简单的登录注册案例

在这里插入图片描述
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lenovo.bmobc">
<!-- 允许联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 获取GSM(2g)、WCDMA(联通3g)等网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 获取wifi网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 保持CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 获取sd卡写的权限,用于文件上传和下载 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 允许读取手机状态 用于创建BmobInstallation -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">

    </activity>
    <activity android:name=".LoginActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".RegActivity"/>
    <provider
        android:name="cn.bmob.v3.util.BmobContentProvider"
        android:authorities="com.example.lenovo.bmobc.BmobContentProvider">
    </provider>
</application>
</manifest>

Person.java

import cn.bmob.v3.BmobObject;


public class Person extends BmobObject {
private String name;
private String address;

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;
}

@Override
public String toString() {
    return "Person{" +
            "address='" + address + '\'' +
            ", name='" + name + '\'' +
            '}';
 }
}

User.java

import cn.bmob.v3.BmobUser;
import cn.bmob.v3.datatype.BmobFile;


public class User extends BmobUser {

private BmobFile icon;

public BmobFile getIcon() {
    return icon;
}

public void setIcon(BmobFile icon) {
    this.icon = icon;
   }
}

LoginActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import android.content.Intent;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;

public class LoginActivity extends AppCompatActivity {

private EditText editText_username, editText_password;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    // 初始化 Bmob SDK
    // 使用时请将第二个参数Application ID替换成你在Bmob服务器端创建的Application ID
    Bmob.initialize(this, "8f6ee1e358d294d3fed2fe3b338c178b");
    editText_username = (EditText) findViewById(R.id.editText_username);
    editText_password = (EditText) findViewById(R.id.editText_password);
}

//用户登录
public void loginClick(View v) {
    String username = editText_username.getText().toString();
    String password = editText_password.getText().toString();
    final BmobUser bmobUser = new BmobUser();
    bmobUser.setUsername(username);
    bmobUser.setPassword(password);
    bmobUser.login(new SaveListener<User>() {
        @Override
        public void done(User bmobUser, BmobException e) {
            if (e == null) {
                User user = BmobUser.getCurrentUser(User.class);
                Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_LONG).show();
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                intent.putExtra("user", user);
                startActivity(intent);
            } else {
                Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_LONG).show();
            }
        }
    });
}

public void registerClick(View v) {
    Intent intent = new Intent(this, RegActivity.class);
    startActivity(intent);
   }
}

RegActivity.java

import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;

import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UploadFileListener;

public class RegActivity extends AppCompatActivity {

private EditText editText_name, editText_password, editText_email, editText_icon;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_reg);
    editText_name = (EditText) findViewById(R.id.editText_username);
    editText_password = (EditText) findViewById(R.id.editText_password);
    editText_email = (EditText) findViewById(R.id.editText_email);
    editText_icon = (EditText) findViewById(R.id.editText_icon);
}

//注册功能
public void registerClick(View v) {
    final String name = editText_name.getText().toString();
    final String password = editText_password.getText().toString();
    final String email = editText_email.getText().toString();
    /**
     * 账号密码注册
     */
        User user = new User();
        user.setUsername("" + System.currentTimeMillis());
        user.setPassword("" + System.currentTimeMillis());
        user = new User();
        user.setUsername(name);
        user.setPassword(password);
        user.setEmail(email);
        user.signUp(new SaveListener<User>() {
            @Override
            public void done(User user, BmobException e) {
                if (e == null) {
                    Toast.makeText(RegActivity.this, "注册成功", Toast.LENGTH_LONG).show();
                    Intent intent = new Intent(RegActivity.this, LoginActivity.class);
                    startActivity(intent);
                } else {
                    Toast.makeText(RegActivity.this, "注册失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
   	 }       

}

MainActivity.java

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.DownloadFileListener;
import cn.bmob.v3.listener.QueryListener;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UpdateListener;

public class MainActivity extends AppCompatActivity {

private TextView textView;
private ImageView iv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 初始化 Bmob SDK
    // 使用时请将第二个参数Application ID替换成你在Bmob服务器端创建的Application ID
    //Bmob.initialize(this, "获取到的Application ID");

    textView = (TextView) findViewById(R.id.textView);
    iv = (ImageView) findViewById(R.id.imageView_icon);

    Intent intent = getIntent();
    User user = (User) intent.getSerializableExtra("user");
    textView.setText(user.getUsername() + "," + user.getEmail());


    }




//添加数据
public void addClick(View view) {
    Person p2 = new Person();
    p2.setName("小明");
    p2.setAddress("浙江");
    p2.save(new SaveListener<String>() {
        @Override
        public void done(String objectId,BmobException e) {
            if(e==null){
                Toast.makeText(MainActivity.this, "添加数据成功,返回objectId为:"+objectId, Toast.LENGTH_LONG).show();

            }else{
                Toast.makeText(MainActivity.this, "创建数据失败:" + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }

    });
}

//删除数据
public void delClick(View view) {
    Person p2 = new Person();
    p2.setObjectId("填写从Bmob数据库中获取的objectId");
    p2.delete(new UpdateListener() {

        @Override
        public void done(BmobException e) {
            if(e==null){
                Toast.makeText(MainActivity.this,"删除成功", Toast.LENGTH_LONG).show();
            }else{
                Toast.makeText(MainActivity.this,"删除失败:" + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }

    });
}

//更新数据
public void updateClick(View view) {
    Person p2 = new Person();
    p2.setAddress("北京");
    p2.update("填写从Bmob数据库中获取的objectId", new UpdateListener() {

        @Override
        public void done(BmobException e) {
            if(e==null){
                Toast.makeText(MainActivity.this,"更新成功", Toast.LENGTH_LONG).show();
            }else{
                Toast.makeText(MainActivity.this,"更新失败:" + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }

    });
}

//查询数据
public void queryClick(View view) {
    BmobQuery<Person> bmobQuery = new BmobQuery<Person>();
    bmobQuery.getObject("a96e6beea8", new QueryListener<Person> (){
        @Override
        public void done(Person object,BmobException e) {
            if(e==null){
                Toast.makeText(MainActivity.this,"查询成功", Toast.LENGTH_LONG).show();
            }else{
                Toast.makeText(MainActivity.this,"查询失败:" + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
    });
}
}

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<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=".LoginActivity">

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="textPersonName"
    android:ems="10"
    android:hint="用户名"
    android:id="@+id/editText_username"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="textPassword"
    android:ems="10"
    android:hint="密码"
    android:id="@+id/editText_password"
    android:layout_below="@+id/editText_username"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/editText_username"
    android:layout_alignEnd="@+id/editText_username" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="登录"
    android:id="@+id/button_login"
    android:onClick="loginClick"
    android:layout_marginLeft="105dp"
    android:layout_marginStart="105dp"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="注册"
    android:onClick="registerClick"
    android:id="@+id/button_register"
    android:layout_alignTop="@+id/button_login"
    android:layout_toRightOf="@+id/button_login"
    android:layout_toEndOf="@+id/button_login" />
</RelativeLayout>

activity_reg.xml

<?xml version="1.0" encoding="utf-8"?>
<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=".RegActivity">


<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="textPersonName"
    android:text=""
    android:hint="请输入名称"
    android:ems="10"
    android:id="@+id/editText_username"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="textPassword"
    android:ems="10"
    android:hint="请输入密码"
    android:id="@+id/editText_password"
    android:layout_below="@+id/editText_username"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/editText_username"
    android:layout_alignEnd="@+id/editText_username" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="textEmailAddress"
    android:ems="10"
    android:hint="请输入邮箱"
    android:id="@+id/editText_email"
    android:layout_below="@+id/editText_password"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/editText_password"
    android:layout_alignEnd="@+id/editText_password" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/editText_icon"
    android:layout_below="@+id/editText_email"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/editText_email"
    android:layout_alignEnd="@+id/editText_email" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="注册"
    android:id="@+id/button_register"
    android:onClick="registerClick"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="128dp" />
</RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:layout_height="wrap_content"
    android:text="Bmob云服务测试"
    android:id="@+id/textView"
    android:textSize="36px"/>

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="添加数据"
    android:onClick="addClick"
    android:id="@+id/button_add"
    android:layout_below="@+id/textView"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="删除数据"
    android:onClick="delClick"
    android:id="@+id/button_del"
    android:layout_below="@+id/button_add"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="修改数据"
    android:onClick="updateClick"
    android:id="@+id/button_update"
    android:layout_below="@+id/button_del"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="查询数据"
    android:onClick="queryClick"
    android:id="@+id/button_query"
    android:layout_below="@+id/button_update"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageView_icon"
    android:layout_below="@+id/button_query"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />
</RelativeLayout>
  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值