有同学要Unity demo,于是写了一个
https://download.csdn.net/download/linxinfa/11939660


一、sdk下载

https://developer.huawei.com/consumer/cn/doc/overview/HMS-2-0

华为文档查询: https://developer.huawei.com/consumer/cn/doc/search
比如要查询login接口
在这里插入图片描述

下载HMSAgent_2.6.3.301.zip
在这里插入图片描述
我用的是Eclipse工程,所以下载hmssdk-eclipse-2.6.3.301.zip
在这里插入图片描述

二、编写java中间件,打成jar包

解压上面的两个zip,进入HMSAgent_2.6.3.301目录
在这里插入图片描述
看到文档里说要执行Buildcopysrc2jar.bat来生成jar,但是过程中一堆问题,放弃治疗,不走华为文档里说的那套
它其实就是把HMSAgentjava代码和sdkjar包打成一个jar包,跟着我说的步骤搞即可。
1 打开eclipse,新建Android工程,包名注意和Unity工程的包名相同,假设叫com.linxinfa.sdktest.huawei(注:华为要求必须以.huawei结尾)
2 右键工程,点击Properties,点击Java Build Path/Libraries/Add External JARS...,添加Unity的classes.jar

classes.jar所在位置:Unity安装目录\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar

3 添加hmssdk-eclipse-2.6.3.301中各个模块的libs中的jar
在这里插入图片描述
4 把HMSAgent_2.6.3.301/hmsagents/src/main/java/com目录拷贝到我们的Android工程的src
在这里插入图片描述
5 新建一个MyApplication.java

// 注意包名要以.huawei结尾
package com.linxinfa.sdktest.huawei;

import android.app.Application;

import com.huawei.android.hms.agent.HMSAgent;


/**
 * application类 | application class
 */
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        HMSAgent.init(this);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        HMSAgent.destroy();
    }
}

6 修改MainActivity.java,封装接口供c#调用,注意要继承UnityPlayerActivity

package com.linxinfa.sdktest.huawei;

import java.security.SecureRandom;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.json.JSONObject;

import android.content.SharedPreferences;
import android.os.Bundle;

import com.huawei.android.hms.agent.HMSAgent;
import com.huawei.android.hms.agent.common.handler.CheckUpdateHandler;
import com.huawei.android.hms.agent.common.handler.ConnectHandler;
import com.huawei.android.hms.agent.game.GameLoginSignUtil;
import com.huawei.android.hms.agent.game.handler.ICheckLoginSignHandler;
import com.huawei.android.hms.agent.game.handler.LoginHandler;
import com.huawei.android.hms.agent.game.handler.SaveInfoHandler;
import com.huawei.android.hms.agent.pay.PaySignUtil;
import com.huawei.android.hms.agent.pay.handler.GetOrderHandler;
import com.huawei.android.hms.agent.pay.handler.GetProductDetailsHandler;
import com.huawei.android.hms.agent.pay.handler.GetPurchaseInfoHandler;
import com.huawei.android.hms.agent.pay.handler.ProductPayHandler;
import com.huawei.hms.support.api.entity.game.GamePlayerInfo;
import com.huawei.hms.support.api.entity.game.GameUserData;
import com.huawei.hms.support.api.entity.pay.OrderRequest;
import com.huawei.hms.support.api.entity.pay.PayStatusCodes;
import com.huawei.hms.support.api.entity.pay.ProductDetail;
import com.huawei.hms.support.api.entity.pay.ProductDetailRequest;
import com.huawei.hms.support.api.entity.pay.ProductFailObject;
import com.huawei.hms.support.api.entity.pay.ProductPayRequest;
import com.huawei.hms.support.api.entity.pay.PurchaseInfo;
import com.huawei.hms.support.api.entity.pay.PurchaseInfoRequest;
import com.huawei.hms.support.api.pay.OrderResult;
import com.huawei.hms.support.api.pay.ProductDetailResult;
import com.huawei.hms.support.api.pay.ProductPayResultInfo;
import com.huawei.hms.support.api.pay.PurchaseInfoResult;
import com.huawei.android.hms.agent.HMSAgent;
import com.huawei.android.hms.agent.hwid.handler.SignInHandler;
import com.huawei.android.hms.agent.hwid.handler.SignOutHandler;
import com.huawei.hms.support.api.hwid.SignInHuaweiId;
import com.huawei.hms.support.api.hwid.SignOutResult;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {
	private static final String game_priv_key = IEvnValues.game_priv_key;
	private static final String game_public_key = IEvnValues.game_public_key;

	private static final String appId = IEvnValues.appId;
	private static final String cpId = IEvnValues.cpId;

	/**
	 * 未确认支付缓存,key:requestId value:False | Unacknowledged payment cache,
	 * Key:requestid Value:false
	 */
	private static final String UNCHECK_PAYREQUESTID_FILE = "pay_request_ids";

	// //

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Init();
	}

    // log传到c#端显示
	private void showLog(String text) {
		try {
			JSONObject jo = new JSONObject();
			jo.put("COMMAND", "LOG");
			jo.put("TEXT", text);
			UnityPlayer.UnitySendMessage("SdkCb", "OnSdkCb", jo.toString());
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	public void Init() {
		// 在首个界面,需要调用connect进行连接 | In the first page, you need to call connect
		HMSAgent.connect(this, new ConnectHandler() {
			@Override
			public void onConnect(int rst) {
				showLog("HMS connect end:" + rst);
			}
		});

		HMSAgent.checkUpdate(this, new CheckUpdateHandler() {
			@Override
			public void onResult(int rst) {
				showLog("check app update end:" + rst);
			}
		});
	}

	
	// 游戏登录接口,如果是游戏类型的应用接入华为帐号体系,则需要使用此游戏登录接口,该接口区别于HUAWEIId的signIn接口。
	public void Login() {
		showLog("game login: begin");
		HMSAgent.Game.login(new LoginHandler() {
			@Override
			public void onResult(int retCode, GameUserData userData) {
				if (retCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS
						&& userData != null) {
					showLog("game login: onResult: retCode=" + retCode
							+ "  user=" + userData.getDisplayName() + "|"
							+ userData.getPlayerId() + "|"
							+ userData.getGameAuthSign() + "|"
							+ userData.getTs() + "|"
							+ userData.getIsAuth() + "|"
							+ userData.getPlayerLevel());
					// 当登录成功时,此方法会回调2次, | This method recalls 2 times when the
					// login is successful.
					// 第1次:只回调了playerid;特点:速度快;在要求快速登录,并且对安全要求不高时可以用此playerid登录
					// | 1th time: Only callback playerID; features: fast speed;
					// You can log in with this playerID when you require fast
					// logon and are not high on security requirements
					// 第2次:回调了所有信息,userData.getIsAuth()为1;此时需要对登录结果进行验签 | 2nd
					// time: Callback All information, Userdata.getisauth () is
					// 1;
					if (userData.getIsAuth() == 1) {
						// 如果需要对登录结果进行验签,请发送请求到开发者服务器进行(安全起见,私钥要放在服务端保存)。| If
						// you need to check your login results, send a request
						// to the developer server (for security, the private
						// key is stored on the service side).
						// 下面工具方法仅为了展示验签请求的逻辑,实际实现应该放在开发者服务端。| The following
						// tool method is intended only to show the logic of the
						// verification request, and the actual implementation
						// should be on the developer server.
						GameLoginSignUtil.checkLoginSign(appId, cpId,
								game_priv_key, game_public_key, userData,
								new ICheckLoginSignHandler() {
									@Override
									public void onCheckResult(String code,
											String resultDesc,
											boolean isCheckSuccess) {
										showLog("game login check sign: onResult: retCode="
												+ code
												+ "  resultDesc="
												+ resultDesc
												+ "  isCheckSuccess="
												+ isCheckSuccess);
									}
								});
					}
				} else {
					showLog("game login: onResult: retCode=" + retCode);
				}
			}

			@Override
			public void onChange() {
				// 此处帐号登录发生变化,需要重新登录 | Account login changed here, login
				// required
				showLog("game login: login changed!");
				Login();
			}
		}, 1);
	}
	
	
	/**
	 * 登录授权 | Login Authorization
	 * @param forceLogin 如果已经授权登录则直接回调结果,否则:forceLogin为true时会拉起界面,为false时直接回调错误码 | If the login is authorized, the result is directly callback, otherwise: When Forcelogin is true, the activity is pulled and the error code is directly invoked when false
	 */
	public void SignIn(boolean forceLogin) {
	    HMSAgent.Hwid.signIn(forceLogin, new SignInHandler() {
	        @Override
	        public void onResult(int rtnCode, SignInHuaweiId signInResult) {
	            if (rtnCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS && signInResult != null) {
	                //可以获取帐号的 openid,昵称,头像 at信息 | You can get the OpenID, nickname, Avatar, at etc information of Huawei ID
	                showLog("signIn successful=========");
	                showLog("Nickname:" + signInResult.getDisplayName());
	                showLog("openid:" + signInResult.getOpenId());
	                showLog("accessToken:" + signInResult.getAccessToken());
	                showLog("Head pic URL:" + signInResult.getPhotoUrl());
	                showLog("unionID:" + signInResult.getUnionId());
	            } else {
	                showLog("signIn---error: " + rtnCode);
	            }
	        }
	    });
	}

	/**
	 * 退出。此接口调用后,下次再调用signIn会拉起界面,请谨慎调用。如果不确定就不要调用了。 | Exit。 After this method is called, the next time you call signIn will pull the activity, please call carefully. Do not call if you are unsure.
	 */
	public void SignOut(){
	    HMSAgent.Hwid.signOut(new SignOutHandler() {
	        @Override
	        public void onResult(int rtnCode, SignOutResult signOutResult) {
	            if (rtnCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS && signOutResult != null) {
	                showLog("SignOut successful");
	            } else {
	                showLog("SignOut fail:" + rtnCode);
	            }
	        }
	    });
	}	

	/**
	 * 游戏显示浮标示例 | Game Show Floating Indicator example
	 */
	public void showfloat() {
		showLog("game showfloat");
		HMSAgent.Game.showFloatWindow(this);
	}

	/**
	 * 游戏隐藏浮标示例 | Game Hidden Floating Indicator example
	 */
	public void hidefloat() {
		showLog("game hidefloat");
		HMSAgent.Game.hideFloatWindow(this);
	}

	/**
	 * 游戏保存玩家信息示例 | Game Save player Information sample
	 */
	public void savePlayerInfo() {
		showLog("game savePlayerInfo: begin");
		GamePlayerInfo gpi = new GamePlayerInfo();
		gpi.area = "20";
		gpi.rank = "level 56";
		gpi.role = "hunter";
		gpi.sociaty = "Red Cliff II";
		HMSAgent.Game.savePlayerInfo(gpi, new SaveInfoHandler() {
			@Override
			public void onResult(int retCode) {
				showLog("game savePlayerInfo: onResult=" + retCode);
			}
		});
	}

	// /支付
	/**
	 * PMS支付示例 | PMS Payment Example
	 * 参数由服务器传给客户端
	 */
	public void pmsPay(String productNo, 
                       String applicationID, 
                       String requestId, 
                       String merchantId,
                       String serviceCatalog,
                       String merchantName,
                       int sdkChannel,
                       String url,
                       String urlVer,
                       String sign,
                       String pay_pub_key)  {
		showLog("PMS pay: begin");
		final String tmp_pay_pub_key = pay_pub_key;
		ProductPayRequest payReq = createProductPayReq(productNo, applicationID, requestId, merchantId, serviceCatalog, merchantName, sdkChannel, url, urlVer, sign);
		HMSAgent.Pay.productPay(payReq, new ProductPayHandler() {
			@Override
			public void onResult(int retCode, ProductPayResultInfo payInfo) {
				if (retCode == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS
						&& payInfo != null) {
					boolean checkRst = PaySignUtil.checkSign(payInfo,
							tmp_pay_pub_key);
					showLog("PMS pay: onResult: pay success and checksign="
							+ checkRst + "\n");
					if (checkRst) {
						// 支付成功并且验签成功,发放商品 | Payment successful and successful
						// verification, distribution of goods
					} else {
						// 签名失败,需要查询订单状态:对于没有服务器的单机应用,调用查询订单接口查询;其他应用到开发者服务器查询订单状态。|
						// Signature failed, need to query order status: For
						// stand-alone applications without servers, call Query
						// order interface query, other application to the
						// Developer Server query order status.
					}
				} else if (retCode == HMSAgent.AgentResultCode.ON_ACTIVITY_RESULT_ERROR
						|| retCode == PayStatusCodes.PAY_STATE_TIME_OUT
						|| retCode == PayStatusCodes.PAY_STATE_NET_ERROR) {
					showLog("PMS pay: onResult: need wait for result, rstcode="
							+ retCode + "\n");
					// 需要查询订单状态:对于没有服务器的单机应用,调用查询订单接口查询;其他应用到开发者服务器查询订单状态。| Need
					// to query order status: For stand-alone applications
					// without servers, call Query order interface query, other
					// application to Developer Server query order status.
				} else {
					showLog("PMS pay: onResult: pay fail=" + retCode + "\n");
					// 其他错误码意义参照支付api参考 | Other error code meaning reference
					// payment API reference
				}
			}
		});

		// 将requestid缓存,供查询订单 | RequestID Cache for Query order
		addRequestIdToCache(payReq.getRequestId());
	}

	public void addRequestIdToCache(String requestId) {
		SharedPreferences sp = getSharedPreferences("pay_request_ids", 0);
		sp.edit().putBoolean(requestId, false).commit();
	}

	public void removeCacheRequestId(String reqId) {
		SharedPreferences sp = getSharedPreferences("pay_request_ids", 0);
		sp.edit().remove(reqId).commit();
	}

	/**
	 * 创建pms支付的请求对象 | Create a Request object for PMS payments
	 * @param 
	 *  productNo 商品编码
	 *  applicationID 应用ID
	 *  requestId 支付订单号
	 *  merchantId 商户ID
	 *  serviceCatalog 分类,游戏填"X6"
	 *  merchantName 商户名称
	 *  sdkChannel 渠道号,应用市场填1
	 *  url 支付回调地址
	 *  urlVer 回调接口版本号,固定填"2"
	 *  sign 签名
	 * @return pms支付请求对象 | PMS Payment Request Object
	 */
	private static ProductPayRequest createProductPayReq(String productNo, 
                                                        String applicationID, 
                                                        String requestId, 
                                                        String merchantId,
                                                        String serviceCatalog,
                                                        String merchantName,
                                                        int sdkChannel,
                                                        String url,
                                                        String urlVer,
                                                        String sign) 
	{
	    ProductPayRequest payReq = new ProductPayRequest();
	
	    // 商品编号 | productNo
	    payReq.productNo = productNo;
	    
	    // 应用ID,来源于开发者联盟 | Application ID, from the Developer Alliance
	    payReq.applicationID = applicationID;

	    // 支付订单号 | requestId
	    payReq.requestId = requestId;
	    
	    // 商户ID,来源于开发者联盟,也叫“支付id”、“cpid” | Merchant ID, from the Developer
	    // Alliance, also known as "Payment ID", "cpid"
	    payReq.merchantId = merchantId;
	    
	    // 分类,必填,不参与签名。该字段会影响风控策略 | Categories, required, do not participate in
	    // the signature. This field affects wind control policy
	    // X4:主题,X5:应用商店, X6:游戏,X7:天际通,X8:云空间,X9:电子书,X10:华为学习,X11:音乐,X12 视频, |
	    // X4: Theme, X5: App Store, X6: Games, X7: Sky Pass, X8: Cloud Space,
	    // X9: ebook, X10: Huawei Learning, X11: Music, X12 video,
	    // X31 话费充值,X32 机票/酒店,X33 电影票,X34 团购,X35 手机预购,X36 公共缴费,X39 流量充值 | X31,
	    // X32 air tickets/hotels, X33 movie tickets, X34 Group purchase, X35
	    // mobile phone advance, X36 public fees, X39 flow Recharge
	    payReq.serviceCatalog = serviceCatalog;
	
	    // 商户名称,必填,不参与签名。会显示在支付结果页面 | Merchant name, must be filled out, do not
	    // participate in the signature. will appear on the Pay results page
	    payReq.merchantName = merchantName;
	    
	    // 渠道号 | sdkChannel
	    payReq.sdkChannel = sdkChannel;
	
	    // 支付结果回调地址。服务器异步通知页面路径
	    // 华为服务器收到后检查该应用有无在开发者联盟配置回调URL,如果配置了则使用应用配置的URL,否则使用此url作为该次支付的回调URL
	    payReq.url = url;
	    
	    // 回调接口版本号 | Callback Interface Version number
	    payReq.urlVer = urlVer;
	
	    // 商户保留信息,选填不参与签名,支付成功后会华为支付平台会原样 回调CP服务端 | The merchant retains the
	    // information, chooses not to participate in the signature, the payment
	    // will be successful, the Huawei payment platform will be back to the
	    // CP service
	    //payReq.extReserved = "";
	
	    // 对单机应用可以直接调用此方法对请求信息签名,非单机应用一定要在服务器端储存签名私钥,并在服务器端进行签名操作。| For
	    // stand-alone applications, this method can be called directly to the
	    // request information signature, not stand-alone application must store
	    // the signature private key on the server side, and sign operation on
	    // the server side.
	    // 在服务端进行签名的cp可以将getStringForSign返回的待签名字符串传给服务端进行签名 | The CP, signed on
	    // the server side, can pass the pending signature string returned by
	    // Getstringforsign to the service side for signature
	    payReq.sign = sign;
	
	    return payReq;
	}
}

7 拷贝IEvnValues.java到工程中,记得改下appid、cpid
注:IEvnValues.java可以在华为sdk示例工程找到,示例工程的链接在文章的开头那里有

// IEvnValues.java
package com.huawei.hmsagent;

/**
 * 环境变量配置,私钥需要放在服务器端,这里只是给个处理示例 | environment variable configuration, the private key needs to be placed on the server side, here is just a sample processing
 */
public interface IEvnValues {
    String game_priv_key = "xxx very long game private key xxx";
    String game_public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD2zL2j7JsygP6k+0FX5ewrHmw1puikjhbdX1t2GWFAwjOiW4u+ycmvKvPs4ETjba1i7+M35nkiEI3wE2TP+GfMJLcE+5txkJ0sEOqIuvsYAgyZLwf64AoPcgQN50BZO8GFXuHmOG+8Z4nUa2A3/vvMHGWlVOo5ujkoTLj5j0tNIQIDAQAB";

    String pay_priv_key = "xxx very long pay private key xxx";
    String pay_pub_key = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIL/7zgG9KCjm5IeGFzq8oVaxCqFJ9+m/3rGMXU2p9K+bHLPR1m3c9TMZRGjkZbTZ0G/VLPO6BxiP+w+VM+Z3fECAwEAAQ==";

    String appId = "100204335";
    String cpId = "10086000000000293";
}

在这里插入图片描述
8 右键Android工程的srcExport,导出成jar,假设取名叫huawei_game_sdk.jar

三、Unity部分

1 把hmssdk的各个jar包和我们生成的huawei_game_sdk.jar拷贝到Unity工程中的Assets/Plugins/Android/libs目录中
在这里插入图片描述
2 拷贝res资源
在这里插入图片描述
3 配置AndroidManifest.xml
AndroidManifest建议拷贝Unity的模板进行修改,在Unity安装目录\Editor\Data\PlaybackEngines\AndroidPlayer\Apk\目录中

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools"
    android:installLocation="preferExternal"
    android:versionCode="1"
    android:versionName="1.0">
    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true"
        android:anyDensity="true"/>

    <application
        android:theme="@style/UnityThemeSelector"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name"
        android:debuggable="true">
        <activity android:name="com.unity3d.player.UnityPlayerActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>
</manifest>

参考sdk demoAndroidManifest.xml,注意几个值的修改:
${PACKAGE_NAME}替换成你的包名,比如com.linxinfa.sdktest.huawei
${HMSVERSION}替换成sdk版本号,比如2.6.3.301
${APPID}替换成你在开发者账号上申请的应用的appid
${CPID}替换成你在开发者账号上申请的支付的cpid

最后改成如下这样子:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="${PACKAGE_NAME}"
    xmlns:tools="http://schemas.android.com/tools"
    android:installLocation="preferExternal"
    android:versionCode="1"
    android:versionName="1.0">
    
    <!--HMS-SDK引导升级HMS功能,访问OTA服务器需要网络权限 | HMS-SDK upgrade HMS Feature, access to OTA server requires network privileges-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--HMS-SDK引导升级HMS功能,保存下载的升级包需要SD卡写权限 | HMS-SDK upgrade HMS Feature, save downloaded upgrade pack requires SD card Write permission-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--检测网络状态 | Detecting Network status-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--检测wifi状态 | Detecting WiFi status-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!--获取用户手机的IMEI,用来唯一的标识设备。 | Gets the IMEI of the user's phone, used to uniquely identify the device.-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <!--如果是安卓8.0,应用编译配置的targetSdkVersion>=26,请务必添加以下权限 -->
    <!--<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />-->
    
    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true"
        android:anyDensity="true"/>

    <application
        android:name=".MyApplication"
        android:theme="@style/UnityThemeSelector"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name"
        android:debuggable="true">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
        
         <!-- 接入 HMSSDK 配置依赖的HMS版本号 | Access HMSSDK configuration dependent HMS Version number-->
        <meta-data
            android:name="com.huawei.hms.version"
            android:value="${HMSVERSION}"/>

        <!-- 接入HMSSDK 需要注册的appid参数。value的值中“${APPID}”用实际申请的appid替换,来源于开发者联盟网站应用的权益详情。
            格式 android:value="appid=xxxxxx"
            Access HMSSDK need to register AppID parameters. Value "${APPID}" is replaced with the actual application APPID, derived from the Developer affiliate website application.
            Format android:value= "appid=xxxxxx"-->
        <meta-data
            android:name="com.huawei.hms.client.appid"
            android:value="appid=${APPID}"/>

        <!-- 接入HMSSDK 游戏或支付时需要注册的cpid参数。value的值中“${CPID}”用实际申请的应用cpID替换,来源于开发者联盟网站应用的权益详情。
            格式 android:value="cpid=xxxxxx"
            Cpid parameters that need to be registered to access HMSSDK games or payments. Value "${CPID}" is replaced with the application Cpid of the actual application, from the Developer affiliate website application.
            Format android:value="cpid=xxxxxx"-->
        <meta-data
            android:name="com.huawei.hms.client.cpid"
            android:value="cpid=${CPID}"/>

        <!-- 接入HMSSDK 需要注册的provider,authorities 一定不能与其他应用一样,所以这边 ${PACKAGE_NAME} 要替换上您应用的包名
            Access HMSSDK need to register provider,authorities must not be the same as other applications, so this side ${package_name} to replace the package name you applied-->
        <provider
            android:name="com.huawei.hms.update.provider.UpdateProvider"
            android:authorities="${PACKAGE_NAME}.hms.update.provider"
            android:exported="false"
            android:grantUriPermissions="true"/>
        
	    <!-- 接入HMSSDK 需要注册的provider,authorities 一定不能与其他应用一样,所以这边 ${PACKAGE_NAME} 要替换上您应用的包名
	        Access HMSSDK need to register provider,authorities must not be the same as other applications, so this side ${package_name} to replace the package name you applied-->
        <provider
            android:name="com.huawei.updatesdk.fileprovider.UpdateSdkFileProvider"
            android:authorities="${PACKAGE_NAME}.updateSdk.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
        </provider>

        <!-- 使用 HMSAgent 代码接入HMSSDK 需要注册的activity | Use hmsagent code to access HMSSDK activity that requires registration-->
        <activity
            android:name="com.huawei.android.hms.agent.common.HMSAgentActivity"
            android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
            android:excludeFromRecents="true"
            android:exported="false"
            android:hardwareAccelerated="true"
            android:theme="@android:style/Theme.Translucent" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent" />
        </activity>

        <!-- 使用 HMSAgent 代码接入HMSSDK 游戏或支付模块时需要注册的activity | Activity to register when accessing HMSSDK game or payment module using hmsagent code-->
        <activity
            android:name="com.huawei.android.hms.agent.pay.HMSPayAgentActivity"
            android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
            android:excludeFromRecents="true"
            android:exported="false"
            android:hardwareAccelerated="true"
            android:theme="@android:style/Theme.Translucent" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent" />
        </activity>

        <!-- 使用 HMSAgent 代码接入HMSSDK 游戏或支付模块时需要注册的activity | Activity to register when accessing HMSSDK game or payment module using hmsagent code-->
        <activity
            android:name="com.huawei.android.hms.agent.pay.HMSPMSPayAgentActivity"
            android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
            android:excludeFromRecents="true"
            android:exported="false"
            android:hardwareAccelerated="true"
            android:theme="@android:style/Theme.Translucent" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent" />
        </activity>

        <!-- 使用 HMSAgent 代码接入HMSSDK 帐号模块时需要注册的activity | Activity to register when accessing HMSSDK account module using hmsagent code-->
        <activity
            android:name="com.huawei.android.hms.agent.hwid.HMSSignInAgentActivity"
            android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
            android:excludeFromRecents="true"
            android:exported="false"
            android:hardwareAccelerated="true"
            android:theme="@android:style/Theme.Translucent" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent" />
        </activity>

        <!-- 接入HMSSDK 需要注册的activity | Access HMSSDK activity to be registered-->
        <activity
            android:name="com.huawei.hms.activity.BridgeActivity"
            android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale"
            android:excludeFromRecents="true"
            android:exported="false"
            android:hardwareAccelerated="true"
            android:theme="@android:style/Theme.Translucent" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent" />
        </activity>

        <!-- 接入HMSSDK 需要注册的activity | Access HMSSDK activity to be registered-->
        <activity
            android:name="com.huawei.updatesdk.service.otaupdate.AppUpdateActivity"
            android:configChanges="orientation|screenSize"
            android:exported="false"
            android:theme="@style/upsdkDlDialog" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent.NoTitleBar" />
        </activity>

        <!-- 接入HMSSDK 需要注册的activity | Access HMSSDK activity to be registered-->
        <activity
            android:name="com.huawei.updatesdk.support.pm.PackageInstallerActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:exported="false"
            android:theme="@style/upsdkDlDialog" >
            <meta-data
                android:name="hwc-theme"
                android:value="androidhwext:style/Theme.Emui.Translucent" />
        </activity>

        <!-- 接入HMSSDK PUSH模块需要注册,第三方相关 :接收Push消息(注册、Push消息、Push连接状态)广播,
                此receiver类需要开发者自己创建并继承com.huawei.hms.support.api.push.PushReceiver类,
                参考示例代码中的类:com.huawei.hmsagent.HuaweiPushRevicer
            Access to the HMSSDK push module requires registration:
	            Receive push message (registration, push message, push connection state) broadcast.
	            This receiver class requires the developer to create and inherit the com.huawei.hms.support.api.push.PushReceiver class.
	            Reference to class in sample code: Com.huawei.hmsagent.HuaweiPushRevicer-->
        <receiver android:name="com.huawei.hmsagent.HuaweiPushRevicer" >
            <intent-filter>
                <!-- 必须,用于接收token | Must, for receiving token -->
                <action android:name="com.huawei.android.push.intent.REGISTRATION" />
                <!-- 必须,用于接收消息 | Must, used to receive messages-->
                <action android:name="com.huawei.android.push.intent.RECEIVE" />
                <!-- 可选,用于点击通知栏或通知栏上的按钮后触发onEvent回调 | Optional, click the button on the notification bar or the notification bar to trigger the onevent callback -->
                <action android:name="com.huawei.android.push.intent.CLICK" />
                <!-- 可选,查看push通道是否连接,不查看则不需要 | Optional, query whether the push channel is connected or not -->
                <action android:name="com.huawei.intent.action.PUSH_STATE" />
            </intent-filter>
        </receiver>

        <!-- 接入HMSSDK PUSH模块需要注册 :接收通道发来的通知栏消息 | The access HMSSDK push module needs to be registered: the notification bar message sent from the receiving channel -->
        <receiver android:name="com.huawei.hms.support.api.push.PushEventReceiver" >
            <intent-filter>
                <action android:name="com.huawei.intent.action.PUSH" />
            </intent-filter>
        </receiver>

        <!-- 接入HMSSDK 需要注册的应用下载服务 | Access HMSSDK need to register app download service-->
        <service android:name="com.huawei.updatesdk.service.deamon.download.DownloadService"
            android:exported="false"/>
    </application>
</manifest>

4 创建HuaweiSdk.cs脚本,封装c#接口调用java

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HuaweiSdk
{
    public static void Init()
    {
        jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    }

	// 应用授权
	public static void Login()
    {
        jo.Call("Login");
    }

	// 应用注销授权
    public static void SignOut()
    {
        jo.Call("SignOut");
    }

    public static void pmsPay(string productNo)
    {
        jo.Call("pmsPay", productNo);
    }

    /// <summary>
    /// 游戏保存玩家信息
    /// </summary>
    public static void SavePlayerInfo()
    {
        jo.Call("savePlayerInfo");
    }

    /// <summary>
    /// 获取pms商品信息
    /// </summary>
    /// <param name="productNos">pms商品编码,多个以“|”分割,最多支持20个</param>
    public static void GetProductDetail(string productNos)
    {
        jo.Call("getProductDetail", productNos);
    }

    public static void checkPay()
    {
        jo.Call("checkPay");
    }

    public static void showfloat()
    {
        jo.Call("showfloat");
    }

    public static void hidefloat()
    {
        jo.Call("hidefloat");
    }

    private static AndroidJavaClass jc;
    private static AndroidJavaObject jo;
}

5 新建SdkCb.cs脚本,监听java回调

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SdkCb : MonoBehaviour
{
    public void OnSdkCb(string args)
    {
        Debug.Log(args);
    }
}

6 场景中创建一个空物体,取名叫SdkCb,并挂上SdkCb.cs脚本
7 创建Runner.cs脚本,挂在主摄像机上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Runner: MonoBehaviour
{
    void Awake()
    {
    	HuaweiSdk.Init();
	}
	
	
	void OnGUI()
	{
		if(GUILayout.Button("SignIn"))
		{
			HuaweiSdk.Login();
		}
		// TODO 绑定ui按钮的点击事件,去调用sdk的接口进行测试,不列举了...
		
	}
}

四、登录错误码

https://developer.huawei.com/consumer/cn/doc/development/HMS-2-References/hmssdk_jointOper_api_reference_c9
在这里插入图片描述

五、支付错误码

https://developer.huawei.com/consumer/cn/doc/development/HMS-2-References/hmssdk_jointOper_api_reference_c20
在这里插入图片描述


六、问题与解答

1、sdk初始化的时候提示安装 “华为移动服务”,点安装按钮,提示检查华为移动服务更新失败
在这里插入图片描述
在这里插入图片描述
解答:非华为 手机,需要下载华为服务,如果提示更新失败,很可能是因为下载的res(包括layout、value、drawable)没有放到工程里,请检查

2、浮标无显示、浮标隐藏不了等
见我另一篇关于华为浮标的文章 https://blog.csdn.net/linxinfa/article/details/102727686

3、cipd在哪里看
在华为开发者联盟网站上,在支付服务里,看这里 https://developer.huawei.com/consumer/cn/service/hms/doc/hmssdk_jointOper_querypayinfo.html

4、启动一直白屏,没有任何反应
很可能是权限问题,可以在设置里把权限全部勾上重启app

5、用户的AccessToken有效期是多长时间?
用户的AccessToken为1个小时的有效期。

6、用户的AccessToken过期后怎么处理?
重新调用login接口,不需要用户重新授权。

7、应用开发者是否需要对登录接口获取的ACCESSTOKEN进行验签?
应用通过登录接口返回值中获取的ACCESSTOKEN由华为移动服务客户端进行有效性验证,只有合法有效的ACCESSTOKEN才会返回给应用,所以应用不需要对ACCESSTOKEN进行验签,可以直接使用。

8、接入华为帐号,是否可以获取UID
不可以,由于需要隐私保护,接入华为帐号后只能获取openid

9、不同的应用接入华为帐号登录,是否返回同一openid
不是,不同应用登录同一华为帐号获取的openid不一样,openid是应用内的唯一标识。

10、HMS SDK 2.0升级变更说明(目前最新版4.0)
https://developer.huawei.com/consumer/cn/doc/development/AppGallery-connect-Guides/appgallerykit-hms-2-change

11、华为游戏市场中,部分游戏游客登录可以直接拉起支付,他们是怎么做到的?
联运游戏,支付(接口productPay)必须先授权登录,如果自行开发了游客登录模式,在2.0版的SDK版本,有个HMSAgent.Pay.pay接口,这个接口不需要先登录,可用于游客模式的支付,但此接口在4.0版的SDK已经废弃,请慎用。

12、关于游戏图标的要求
可以不用角标,图片不能圆角,必须正方形,尺寸为216x216px,格式png。

13、华为SDK有区分联运版和单机版吗?
华为SDK全球一套,不会区分单机还是非单机的

七、华为自检工具检查易见情况

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

八、开发者账号相关

1、如何查看APPID、APPKEY、APP SECRET等参数

登录华为开发者联盟https://developer.huawei.com/consumer/cn/
进入 管理中心,可以看到有个AppGallery Connect,点击进入
在这里插入图片描述
再点 我的项目
在这里插入图片描述
选择具体的项目,即可查看到对应项目的APPID等参数了
在这里插入图片描述

2、如何查看CPID、支付公钥、支付私钥等参数

登录华为开发者联盟https://developer.huawei.com/consumer/cn/
进入 管理中心,可以看到有个支付,点击进入
在这里插入图片描述
点击具体的应用
在这里插入图片描述
即可看到CPID、支付公钥、支付私钥等参数
在这里插入图片描述

3、如何查看应用的游戏公钥和游戏私钥

在这里插入图片描述
在这里插入图片描述

4、如何配置应用内商品

https://developer.huawei.com/consumer/cn/doc/distribution/app/agc-create_product

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐