极光推送

链接

发送通知
极光推送注册登录
详细信息

添加依赖defaultConfig下

 ndk {
        //选择要添加的对应 cpu 类型的 .so 库。
        abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
        // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
    }

    manifestPlaceholders = [
            JPUSH_PKGNAME : applicationId,
            JPUSH_APPKEY : "你的 Appkey", //JPush 上注册的包名对应的 Appkey.
            JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
    ]

添加依赖dependencies下

 implementation 'cn.jiguang.sdk:jpush:3.3.4'  // 此处以JPush 3.3.4 版本为例。
    implementation 'cn.jiguang.sdk:jcore:2.1.0'  // 此处以JCore 2.1.0 版本为例。

清单文件

权限

<uses-permission android:name="com.example.a123.day12lianxi2.permission.JPUSH_MESSAGE"/>
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
 <uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.GET_TASKS"/>

application里

 <service android:name=".PushService" android:exported="false" android:process=":pushcore">
        <intent-filter>
            <action android:name="cn.jpush.android.intent.REGISTER"/>
            <action android:name="cn.jpush.android.intent.REPORT"/>
            <action android:name="cn.jpush.android.intent.PushService"/>
            <action android:name="cn.jpush.android.intent.PUSH_TIME"/>
        </intent-filter>
   </service>
   <receiver android:name=".MyReceiver" android:exported="false" android:enabled="true">
        <intent-filter>
            <action android:name="cn.jpush.android.intent.REGISTRATION"/>
            <!--Required 用户注册SDK的intent-->
            <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED"/>
            <!--Required 用户接收SDK消息的intent-->
            <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED"/>
            <!--Required 用户接收SDK通知栏信息的intent-->
            <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED"/>
            <!--Required 用户打开自定义通知栏的intent-->
            <action android:name="cn.jpush.android.intent.CONNECTION"/>
            <!-- 接收网络变化 连接/断开 since 1.6.3 -->
            <category android:name="你的包名"/>
        </intent-filter>
    </receiver>

 <receiver android:name=".MyJPushMessageReceiver">
   <intent-filter>
    <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE"/>
    <category android:name="com.example.a123.day12lianxi2"/>
</intent-filter>
</receiver>

    <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
    <meta-data android:name="JPUSH_APPKEY" android:value="您应用的 Appkey"/>

Activity

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    registerMessageReceiver();
}


//for receive customer msg from jpush server
private MessageReceiver mMessageReceiver;
public static final String MESSAGE_RECEIVED_ACTION = "com.example.jpushdemo.MESSAGE_RECEIVED_ACTION";
public static final String KEY_TITLE = "title";
public static final String KEY_MESSAGE = "message";
public static final String KEY_EXTRAS = "extras";

public void registerMessageReceiver() {
    mMessageReceiver = new MessageReceiver();
    IntentFilter filter = new IntentFilter();
    filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    filter.addAction(MESSAGE_RECEIVED_ACTION);
    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter);
}

public class MessageReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) {
                String messge = intent.getStringExtra(KEY_MESSAGE);
                String extras = intent.getStringExtra(KEY_EXTRAS);
                StringBuilder showMsg = new StringBuilder();
                showMsg.append(KEY_MESSAGE + " : " + messge + "\n");
//                    if (!ExampleUtil.isEmpty(extras)) {
//                        showMsg.append(KEY_EXTRAS + " : " + extras + "\n");
//                    }
//                    setCostomMsg(showMsg.toString());
                }
            } catch (Exception e){
            }
        }
    }

//    private void setCostomMsg(String msg){
//        if (null != msgText) {
//            msgText.setText(msg);
//            msgText.setVisibility(View.VISIBLE);
//        }
//    }
}

ExampleUtil

public class ExampleUtil {


public static void showToast(final String toast, final Context context)
{
	new Thread(new Runnable() {

		@Override
		public void run() {
			Looper.prepare();
			Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
			Looper.loop();
		}
	}).start();
}

public static boolean isConnected(Context context) {
    ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo info = conn.getActiveNetworkInfo();
    return (info != null && info.isConnected());
}
}

自定义类继承Application

public class MyApplication  extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        JPushInterface.setDebugMode(true);//调试模式。
        JPushInterface.init(this);
    }
}

JPushMessageReceiver

public class MyJPushMessageReceiver extends JPushMessageReceiver {

@Override
public void onTagOperatorResult(Context context,JPushMessage jPushMessage) {
    TagAliasOperatorHelper.getInstance().onTagOperatorResult(context,jPushMessage);
    super.onTagOperatorResult(context, jPushMessage);
}
@Override
public void onCheckTagOperatorResult(Context context,JPushMessage jPushMessage){
    TagAliasOperatorHelper.getInstance().onCheckTagOperatorResult(context,jPushMessage);
    super.onCheckTagOperatorResult(context, jPushMessage);
}
@Override
public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) {
    TagAliasOperatorHelper.getInstance().onAliasOperatorResult(context,jPushMessage);
    super.onAliasOperatorResult(context, jPushMessage);
}

@Override
public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) {
    TagAliasOperatorHelper.getInstance().onMobileNumberOperatorResult(context,jPushMessage);
    super.onMobileNumberOperatorResult(context, jPushMessage);
}
}

MyReceiver

public class MyReceiver extends BroadcastReceiver {
	private static final String TAG = "JIGUANG-Example";

@Override
public void onReceive(Context context, Intent intent) {
	try {
		Bundle bundle = intent.getExtras();
		Logger.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));

		if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
			String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
			Logger.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);
			//send the Registration Id to your server...

		} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
			Logger.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
//				processCustomMessage(context, bundle);

		} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
			Logger.d(TAG, "[MyReceiver] 接收到推送下来的通知");
			int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
			Logger.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId);

		} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
			Logger.d(TAG, "[MyReceiver] 用户点击打开了通知");

			//打开自定义的Activity
			Intent i = new Intent(context, MainActivity.class);
			i.putExtras(bundle);
			//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP );
			context.startActivity(i);

		} else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
			Logger.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
			//在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等..

		} else if(JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
			boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
			Logger.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected);
		} else {
			Logger.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());
		}
	} catch (Exception e){

	}

}

// 打印所有的 intent extra 数据
private static String printBundle(Bundle bundle) {
	StringBuilder sb = new StringBuilder();
	for (String key : bundle.keySet()) {
		if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
			sb.append("\nkey:" + key + ", value:" + bundle.getInt(key));
		}else if(key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)){
			sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key));
		} else if (key.equals(JPushInterface.EXTRA_EXTRA)) {
			if (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) {
				Logger.i(TAG, "This message has no Extra data");
				continue;
			}

			try {
				JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA));
				Iterator<String> it =  json.keys();

				while (it.hasNext()) {
					String myKey = it.next();
					sb.append("key:" + key + ", value: [" +
							myKey + " - " +json.optString(myKey) + "]");
				}
			} catch (JSONException e) {
				Logger.e(TAG, "Get message extra JSON error!");
			}

		} else {
			sb.append("key:" + key + ", value:" + bundle.get(key));
		}
	}
	return sb.toString();
}


}

JCommonService

public class PushService extends JCommonService {

}

TagAliasOperatorHelper

public class TagAliasOperatorHelper {
    private static final String TAG = "JIGUANG-TagAliasHelper";
    public static int sequence = 1;
    /**增加*/
    public static final int ACTION_ADD = 1;
    /**覆盖*/
    public static final int ACTION_SET = 2;
    /**删除部分*/
    public static final int ACTION_DELETE = 3;
    /**删除所有*/
    public static final int ACTION_CLEAN = 4;
    /**查询*/
    public static final int ACTION_GET = 5;

public static final int ACTION_CHECK = 6;

public static final int DELAY_SEND_ACTION = 1;

public static final int DELAY_SET_MOBILE_NUMBER_ACTION = 2;

private Context context;

private static TagAliasOperatorHelper mInstance;
private TagAliasOperatorHelper(){
}
public static TagAliasOperatorHelper getInstance(){
    if(mInstance == null){
        synchronized (TagAliasOperatorHelper.class){
            if(mInstance == null){
                mInstance = new TagAliasOperatorHelper();
            }
        }
    }
    return mInstance;
}
public void init(Context context){
    if(context != null) {
        this.context = context.getApplicationContext();
    }
}
private SparseArray<Object> setActionCache = new SparseArray<Object>();

public Object get(int sequence){
    return setActionCache.get(sequence);
}
public Object remove(int sequence){
    return setActionCache.get(sequence);
}
public void put(int sequence,Object tagAliasBean){
    setActionCache.put(sequence,tagAliasBean);
}
private Handler delaySendHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what){
            case DELAY_SEND_ACTION:
                if(msg.obj !=null && msg.obj instanceof  TagAliasBean){
                    Logger.i(TAG,"on delay time");
                    sequence++;
                    TagAliasBean tagAliasBean = (TagAliasBean) msg.obj;
                    setActionCache.put(sequence, tagAliasBean);
                    if(context!=null) {
                        handleAction(context, sequence, tagAliasBean);
                    }else{
                        Logger.e(TAG,"#unexcepted - context was null");
                    }
                }else{
                    Logger.w(TAG,"#unexcepted - msg obj was incorrect");
                }
                break;
            case DELAY_SET_MOBILE_NUMBER_ACTION:
                if(msg.obj !=null && msg.obj instanceof  String) {
                    Logger.i(TAG, "retry set mobile number");
                    sequence++;
                    String mobileNumber = (String) msg.obj;
                    setActionCache.put(sequence, mobileNumber);
                    if(context !=null) {
                        handleAction(context, sequence, mobileNumber);
                    }else {
                        Logger.e(TAG, "#unexcepted - context was null");
                    }
                }else{
                    Logger.w(TAG,"#unexcepted - msg obj was incorrect");
                }
                break;
        }
    }
};
public void handleAction(Context context,int sequence,String mobileNumber){
    put(sequence,mobileNumber);
    Logger.d(TAG,"sequence:"+sequence+",mobileNumber:"+mobileNumber);
    JPushInterface.setMobileNumber(context,sequence,mobileNumber);
}
/**
 * 处理设置tag
 * */
public void handleAction(Context context,int sequence, TagAliasBean tagAliasBean){
    init(context);
    if(tagAliasBean == null){
        Logger.w(TAG,"tagAliasBean was null");
        return;
    }
    put(sequence,tagAliasBean);
    if(tagAliasBean.isAliasAction){
        switch (tagAliasBean.action){
            case ACTION_GET:
                JPushInterface.getAlias(context,sequence);
                break;
            case ACTION_DELETE:
                JPushInterface.deleteAlias(context,sequence);
                break;
            case ACTION_SET:
                JPushInterface.setAlias(context,sequence,tagAliasBean.alias);
                break;
            default:
                Logger.w(TAG,"unsupport alias action type");
                return;
        }
    }else {
        switch (tagAliasBean.action) {
            case ACTION_ADD:
                JPushInterface.addTags(context, sequence, tagAliasBean.tags);
                break;
            case ACTION_SET:
                JPushInterface.setTags(context, sequence, tagAliasBean.tags);
                break;
            case ACTION_DELETE:
                JPushInterface.deleteTags(context, sequence, tagAliasBean.tags);
                break;
            case ACTION_CHECK:
                //一次只能check一个tag
                String tag = (String)tagAliasBean.tags.toArray()[0];
                JPushInterface.checkTagBindState(context,sequence,tag);
                break;
            case ACTION_GET:
                JPushInterface.getAllTags(context, sequence);
                break;
            case ACTION_CLEAN:
                JPushInterface.cleanTags(context, sequence);
                break;
            default:
                Logger.w(TAG,"unsupport tag action type");
                return;
        }
    }
}
private boolean RetryActionIfNeeded(int errorCode,TagAliasBean tagAliasBean){
    if(!ExampleUtil.isConnected(context)){
        Logger.w(TAG,"no network");
        return false;
    }
    //返回的错误码为6002 超时,6014 服务器繁忙,都建议延迟重试
    if(errorCode == 6002 || errorCode == 6014){
        Logger.d(TAG,"need retry");
        if(tagAliasBean!=null){
            Message message = new Message();
            message.what = DELAY_SEND_ACTION;
            message.obj = tagAliasBean;
            delaySendHandler.sendMessageDelayed(message,1000*60);
            String logs =getRetryStr(tagAliasBean.isAliasAction, tagAliasBean.action,errorCode);
            ExampleUtil.showToast(logs, context);
            return true;
        }
    }
    return false;
}
private boolean RetrySetMObileNumberActionIfNeeded(int errorCode,String mobileNumber){
    if(!ExampleUtil.isConnected(context)){
        Logger.w(TAG,"no network");
        return false;
    }
    //返回的错误码为6002 超时,6024 服务器内部错误,建议稍后重试
    if(errorCode == 6002 || errorCode == 6024){
        Logger.d(TAG,"need retry");
        Message message = new Message();
        message.what = DELAY_SET_MOBILE_NUMBER_ACTION;
        message.obj = mobileNumber;
        delaySendHandler.sendMessageDelayed(message,1000*60);
        String str = "Failed to set mobile number due to %s. Try again after 60s.";
        str = String.format(Locale.ENGLISH,str,(errorCode == 6002 ? "timeout" : "server internal error”"));
        ExampleUtil.showToast(str, context);
        return true;
    }
    return false;

}
private String getRetryStr(boolean isAliasAction,int actionType,int errorCode){
    String str = "Failed to %s %s due to %s. Try again after 60s.";
    str = String.format(Locale.ENGLISH,str,getActionStr(actionType),(isAliasAction? "alias" : " tags") ,(errorCode == 6002 ? "timeout" : "server too busy"));
    return str;
}

private String getActionStr(int actionType){
    switch (actionType){
        case ACTION_ADD:
            return "add";
        case ACTION_SET:
            return "set";
        case ACTION_DELETE:
            return "delete";
        case ACTION_GET:
            return "get";
        case ACTION_CLEAN:
            return "clean";
        case ACTION_CHECK:
            return "check";
    }
    return "unkonw operation";
}
public void onTagOperatorResult(Context context, JPushMessage jPushMessage) {
    int sequence = jPushMessage.getSequence();
    Logger.i(TAG,"action - onTagOperatorResult, sequence:"+sequence+",tags:"+jPushMessage.getTags());
    Logger.i(TAG,"tags size:"+jPushMessage.getTags().size());
    init(context);
    //根据sequence从之前操作缓存中获取缓存记录
    TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence);
    if(tagAliasBean == null){
        ExampleUtil.showToast("获取缓存记录失败", context);
        return;
    }
    if(jPushMessage.getErrorCode() == 0){
        Logger.i(TAG,"action - modify tag Success,sequence:"+sequence);
        setActionCache.remove(sequence);
        String logs = getActionStr(tagAliasBean.action)+" tags success";
        Logger.i(TAG,logs);
        ExampleUtil.showToast(logs, context);
    }else{
        String logs = "Failed to " + getActionStr(tagAliasBean.action)+" tags";
        if(jPushMessage.getErrorCode() == 6018){
            //tag数量超过限制,需要先清除一部分再add
            logs += ", tags is exceed limit need to clean";
        }
        logs += ", errorCode:" + jPushMessage.getErrorCode();
        Logger.e(TAG, logs);
        if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) {
            ExampleUtil.showToast(logs, context);
        }
    }
}
public void onCheckTagOperatorResult(Context context, JPushMessage jPushMessage){
    int sequence = jPushMessage.getSequence();
    Logger.i(TAG,"action - onCheckTagOperatorResult, sequence:"+sequence+",checktag:"+jPushMessage.getCheckTag());
    init(context);
    //根据sequence从之前操作缓存中获取缓存记录
    TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence);
    if(tagAliasBean == null){
        ExampleUtil.showToast("获取缓存记录失败", context);
        return;
    }
    if(jPushMessage.getErrorCode() == 0){
        Logger.i(TAG,"tagBean:"+tagAliasBean);
        setActionCache.remove(sequence);
        String logs = getActionStr(tagAliasBean.action)+" tag "+jPushMessage.getCheckTag() + " bind state success,state:"+jPushMessage.getTagCheckStateResult();
        Logger.i(TAG,logs);
        ExampleUtil.showToast(logs, context);
    }else{
        String logs = "Failed to " + getActionStr(tagAliasBean.action)+" tags, errorCode:" + jPushMessage.getErrorCode();
        Logger.e(TAG, logs);
        if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) {
            ExampleUtil.showToast(logs, context);
        }
    }
}
public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) {
    int sequence = jPushMessage.getSequence();
    Logger.i(TAG,"action - onAliasOperatorResult, sequence:"+sequence+",alias:"+jPushMessage.getAlias());
    init(context);
    //根据sequence从之前操作缓存中获取缓存记录
    TagAliasBean tagAliasBean = (TagAliasBean)setActionCache.get(sequence);
    if(tagAliasBean == null){
        ExampleUtil.showToast("获取缓存记录失败", context);
        return;
    }
    if(jPushMessage.getErrorCode() == 0){
        Logger.i(TAG,"action - modify alias Success,sequence:"+sequence);
        setActionCache.remove(sequence);
        String logs = getActionStr(tagAliasBean.action)+" alias success";
        Logger.i(TAG,logs);
        ExampleUtil.showToast(logs, context);
    }else{
        String logs = "Failed to " + getActionStr(tagAliasBean.action)+" alias, errorCode:" + jPushMessage.getErrorCode();
        Logger.e(TAG, logs);
        if(!RetryActionIfNeeded(jPushMessage.getErrorCode(),tagAliasBean)) {
            ExampleUtil.showToast(logs, context);
        }
    }
}
//设置手机号码回调
public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) {
    int sequence = jPushMessage.getSequence();
    Logger.i(TAG,"action - onMobileNumberOperatorResult, sequence:"+sequence+",mobileNumber:"+jPushMessage.getMobileNumber());
    init(context);
    if(jPushMessage.getErrorCode() == 0){
        Logger.i(TAG,"action - set mobile number Success,sequence:"+sequence);
        setActionCache.remove(sequence);
    }else{
        String logs = "Failed to set mobile number, errorCode:" + jPushMessage.getErrorCode();
        Logger.e(TAG, logs);
        if(!RetrySetMObileNumberActionIfNeeded(jPushMessage.getErrorCode(),jPushMessage.getMobileNumber())){
            ExampleUtil.showToast(logs, context);
        }
    }
}
public static class TagAliasBean{
    int action;
    Set<String> tags;
    String alias;
    boolean isAliasAction;

    @Override
    public String toString() {
        return "TagAliasBean{" +
                "action=" + action +
                ", tags=" + tags +
                ", alias='" + alias + '\'' +
                ", isAliasAction=" + isAliasAction +
                '}';
    }
}


}

点击进入发送
在这里插入图片描述
效果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值