本文是学习过程记录,这一篇主要包含HMS的配置、APPGallery连接和广告服务、机器学习服务等内容。
几个小技巧
对于红色警告的单词,鼠标放到单词字母中间,然后Alt+Enter一般可以自动导入。
对于数字参数,可以选中它,然后Ctrl+Shift+C,会把它变为一个大写的变量。
要把哪个Activ作为启动页,只要打开AndroidManifest.xml文件,把其中的<intent-filter>...
部分剪切到目标Activity内即可,例如:
<activity android:name=".TextActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
准备工作
HMS,即Huawei Mobile Service华为移动服务,是和谷歌的GMS(Google Mobile Service)对标的另外一套安卓服务框架。
安卓是开源的,但其上的服务框架GMS则是完全的谷歌产品。HMS是华为搭建自有终端软件生态系统的关键产品,也是未来鸿蒙系统生态的重要前提。
要在安卓APP开发中使用HMS的各种强大功能,首先需要注册成为火花纹开发者联盟开发者,并完成用户身份认证,推荐使用银行卡自动认证,基本上可以实时完成。
创建在线项目和应用
在开发APP之前,应该先在华为开发者联盟网站的【管理中心】创建一个项目,并在项目内创建APP应用。
华为的应用商店叫做AppGallery,所以我们进入【AppGallery Connect(AGC)】来管理项目和应用。
进入【我的项目】,添加项目,名称任意。然后【添加应用】,如下图所示。注意应用包名建议用.huawei,如果遇到包名已经被占用,建议包名结合用户名类似user.demo.huawei或demo.user.huawei。
然后我们回到【我的项目】首页,进入这个新建的项目,可以看到这里有开发者ID(Developer ID)和APP ID、API Key等信息。
进入【API管理】可以设定这个项目能够使用哪些HMS的服务功能。下面是一些常用服务的简介。
服务 | 说明
-|-|-
Analytics Kit | 分析服务,帮助开发者分析用户使用数据。
Auth Service | 第三方身份认证服务,比如苹果账号、微信账号、QQ账号等。
Remote Configuration | 远程配置服务,利用云端配置自动更改APP行为或外观。
App Linking | 跨应用的连接跳转,也帮助开发者跟踪用户连接点击行为。
APMS | 应用性能管理和监控。
App Messaging | 用于内信息,各种弹窗和提示。
Cloud Hosting | 云主机服务。
Cloud Storage | 云存储服务。
In-App Purchases | 应用内购买付费服务。
Account Kit | 华为账号服务,用华为账号登陆APP。
Game Service | 游戏服务,玩家成就、排行榜和存档。
Push Kit | 消息推送服务,向用户推送通知。
Wallet Kit | 钱包服务,卡、证、券、票、钥匙等各类凭证电子化。
Map Kit | 地图服务。
Drive Kit | 云空间服务。
ML Kit | 机器学习服务,涉及文字识别、图像识别、语音识别、人脸识别等。
Safety Detect | 安全检测服务,防病毒和恶意程序。
Site kit | 位置服务,基于地理定位的服务。
Nearby Service | 近距离通信服务,与附加的手机传数据。
FIDO | 线上快速身份验证服务,生物特征认证和快速线上身份验证。
Awareness Kit | 情景感知服务,包括位置、天气、用户状态、环境光等。
如果搞不清这个些服务的状况,那么可以先都打开。
配置开发项目
打开AndroidStudio新建项目。注意包名Package name要和在线的一致,如下图所示,注意不要有多余的空格,否则无法下一步。建议Minimum最小SDK不要故意选太低,建议20以上。
1. agc配置文件
从网站【我的项目】找到对应项目,下载应用对应的agconnect-services.json文件,将AndroidStudio文件列表切换到Project模式,把这个json文件拖拽到app文件夹下,与src文件夹同一级别,弹窗move提示直接OK。
然后在网站项目页面点击【添加SDK】,根据下面提示进行配置。
2. 项目级构建设置
然后再切换Project回到Android,找到【Gradle Scripts/build.gradle(Project…)】项目级构建配置,编辑添加两个maven仓库和一个classpath路径,完成后类似如下所示:
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath 'com.huawei.agconnect:agcp:1.3.1.300'
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
修改之后点击顶部弹出的Sync Now
更新设置。也可以点击Sync with Gradle Files按钮,如下图所示。
3. 模块级构建设置
然后找到找到【Gradle Scripts/build.gradle(Module…)】模块级构建配置,顶部添加一个app plugin
插件,dependencies
中添加一个implementation
依赖,代码如下所示:
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
android {
compileSdkVersion 30
buildToolsVersion "30.0.0"
defaultConfig {
...
}
buildTypes {
...
}
}
dependencies {
...
implementation 'com.huawei.agconnect:agconnect-core:1.3.1.300'
}
修改之后点击顶部弹出的Sync Now
更新设置。
添加广告服务
华为广告服务HUAWEI Ads可以让我们直接在APP页面内放入一个广告条,这个广告条内容是华为提供的,如果APP用户大量观看这个广告,华为就会向开发者支付一定的广告酬劳。
几乎所有的应用或游戏都可以放入广告条,广告条形式有很多种,常用的有banner广告位和应用启动画面广告位(开屏广告)。
从广告服务首页点【查看文档】进入文档页面。然后左侧浏览到【广告服务/流量变现服务/应用开发/集成HMS Core SDK】,参照下面提示进行配置。
1. Project模式添加json配置
参见上面内容,在project模式下,确保agconnect-services.json
文件被放到了src同级目录。
2 项目级build添加2个仓库和1个路径
参见上面内容,在【Gradle Scripts/build.gradle(Project…)】中:
- 检查两处仓库
maven {url 'https://developer.huawei.com/repo/'}
是否有添加(jcenter()
下面)。 - 检查
classpath 'com.huawei.agconnect:agcp:1.3.1.300'
是否正确添加。
3. 模块级build添加2个实现和1个插件
参见上面内容,在【Gradle Scripts/build.gradle(Module…)】中:
- 检查
dependencies
中是否添加implementation 'com.huawei.agconnect:agconnect-core:1.3.1.300'
- 添加新的
implementation 'com.huawei.hms:ads-lite:13.4.33.300'
- 检查是否添加
apply plugin: 'com.huawei.agconnect'
4. 创建AdSampleApplication类
在应用目录上右击,创建java类class,命名为AdSampleApplication
。
然后编辑内容为下面内容,注意第一行应该不同。
package hms.demo02.zhyuzh;
import android.app.Application;
import com.huawei.hms.ads.HwAds;
public class AdSampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HwAds.init(this);
}
}
同时修改目录文件【mainifests/AndroidManifests.xml】,向<application...>
中添加以下两行:
<application
android:usesCleartextTraffic="true"
android:name=".AdSampleApplication"
...
>
...
</application>
Banner广告
我们要在MainActivity
界面上显示一个华为广告图片。
1. 修改activity_main.xml
改为LinearLayout
,添加一个BannerView
,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:hwads="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<com.huawei.hms.ads.banner.BannerView
android:id="@+id/hw_banner_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
hwads:adId="testw6vs28auh3"
hwads:bannerSize="BANNER_SIZE_360_144"/>
</LinearLayout>
注意上面LinearLayout
中新增的xmlns:hwads="http://schemas.android.co
,没有它的话下面hwads
会报错。
注意最后的BANNER_SIZE_360_144
,如果是BANNER_SIZE_360_57
可能就不显示图像。
2. 修改MainActivity.java
主要修改onCreate
方法的内容,使用loadAd()
来获取广告,修改后的代码主要代码如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BannerView bannerView = findViewById(R.id.hw_banner_view);
bannerView.setAdId("testw6vs28auh3");
bannerView.setBannerAdSize(BannerAdSize.BANNER_SIZE_360_57);
AdParam adParam = new AdParam.Builder().build();
bannerView.loadAd(adParam);
}
}
最后,你需要有一台华为的手机,打开开发者模式,授权USB调试,并连接到AndroidStudio,安装调试才能看到华为广告出现在画面上。
非华为手机都不能正常显示这个广告内容。
文本识别
如何开发一个能够识别拍照照片中文字的APP?这要用到HMS的机器学习服务ML Kit。
从HMS文档页面浏览到【机器学习服务/Android/应用开发/开发准备/集成HMS Core SDK】页面,参照以下步骤进行。
1. 添加AGC配置文件
如前所述,确保agconnect-services.json
被正常下载和添加。
2. 配置Maven仓库
如前所述,确保在项目级构建设置【Gradle Scripts/build.gradle(Project…)】中的两个jcenter()
后面添加了新的仓库地址。
3. 添加依赖实现
往下层浏览【集成HMS Core SDK/添加编译依赖/集成文本识别服务SDK】,参照下面说明继续。
如前所述,在模块级构建设置【Gradle Scripts/build.gradle(Module…)】
中添加几行新代码:
implementation 'com.huawei.hms:ml-computer-vision-ocr:2.0.1.300'
implementation 'com.huawei.hms:ml-computer-vision-ocr-latin-model:2.0.1.300'
implementation 'com.huawei.hms:ml-computer-vision-ocr-jk-model:2.0.1.300'
implementation 'com.huawei.hms:ml-computer-vision-ocr-cn-model:2.0.1.300'
这里包含了拉丁日韩中英文识别工具包。
别忘了检查插件行apply plugin: 'com.huawei.agconnect'
被添加在结尾。
4. 云端识别开发
切换页面到【应用开发/文本类服务开发/文本识别】页面,参照下面内容继续。
HMS的文本识别基本步骤是:
- 创建一个分析器
MLTextAnalyzer
,并设置分析器参数 - 创建一个机器学习框架
MLFrame
- 将
MLFrame
传递给分析器MLTextAnalyzer
进行识别,利用onSuccess
回调执行操作 - 识别完成后停止分析器,释放资源。
我们创建一个新的Activity,把这个逻辑写入java代码。由于MLFrame需要使用到位图进行识别,所以我们利用照相机获取拍摄的图片。
界面xml部分:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center"
android:orientation="vertical"
tools:context=".textActivity">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:hint="请先拍照"
android:minHeight="100dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="100dp"
android:onClick="shot"
android:text="SHOT!" />
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="100dp"
android:onClick="recog"
android:text="RECOG!"
/>
</LinearLayout>
</LinearLayout>
逻辑代码java部分:
public class textActivity extends AppCompatActivity {
public static final int REQUEST_CODE = 5;
Bitmap bitmap=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text);
}
public void shot(View view) {
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==REQUEST_CODE && resultCode==RESULT_OK){
assert data != null;
bitmap=(Bitmap) Objects.requireNonNull(data.getExtras()).get("data");
ImageView imageView=findViewById(R.id.image_shot);
imageView.setImageBitmap(bitmap);
}
}
public void read2(View view) {
final MLTextAnalyzer analyzer = MLAnalyzerFactory.getInstance().getRemoteTextAnalyzer();
MLFrame frame = MLFrame.fromBitmap(bitmap);
Task<MLText> task = analyzer.asyncAnalyseFrame(frame);
task.addOnSuccessListener(new OnSuccessListener<MLText>() {
@Override
public void onSuccess(MLText text) {
TextView textView=findViewById(R.id.text_Recog);
textView.setText(text.getStringValue());
Toast.makeText(textActivity.this, text.getStringValue(), Toast.LENGTH_LONG).show();
try {
analyzer.stop();
} catch (IOException e) {
Toast.makeText(textActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
}
运行后点击SHOT按钮拍照,照片会显示在画面上;然后点击RECOG按钮进行识别。
非华为手机都不能正常运行这个内容。
实时语音识别
如何利用HMS服务实现实时的语音转文字?仍然是机器学习服务的功能。
在文档中浏览到【应用开发/语音语言类服务开发/实时语音识别/开发步骤-实时语音识别(有界面)】,参照下面提示进行。
我们仍然先创建新的Activity用来测试。
1. 集成语音服务
在【Gradle Scripts/build.gradle(Module…)】中添加两个依赖。
implementation 'com.huawei.hms:ml-computer-voice-asr-plugin:2.0.3.300'
implementation 'com.huawei.hms:ml-computer-voice-asr:2.0.3.300'
2. 添加授权
因为语音识别要用到很多权限,所以要在AndroidManifest.xml中添加授权,如果分不清的话就把下面的授权都添加。详细说明地址在【应用开发/开发准备/制定权限】中有详细说明。
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
但只在这里授权还不够,后面还要使用动态授权。
3. 界面代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".LangActivity">
<TextView
android:id="@+id/text_lang"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:hint="请先拍照"
android:minHeight="200dp" />
<Button
android:layout_width="200dp"
android:layout_height="100dp"
android:text="GO"
android:onClick="go"/>
</LinearLayout>
4. 逻辑代码
public class LangActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lang);
MLApplication.getInstance().setApiKey("CgB6e3x9gLm4...aaxYEnxvjg9");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
}
public void go(View view) {
// 通过intent进行识别设置。
Intent intent = new Intent(this, MLAsrCaptureActivity.class)
.putExtra(MLAsrCaptureConstants.LANGUAGE, "en-US")
.putExtra(MLAsrCaptureConstants.FEATURE, MLAsrCaptureConstants.FEATURE_WORDFLUX);
startActivityForResult(intent, 100);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String text = "";
if (requestCode == 100) {
switch (resultCode) {
case MLAsrCaptureConstants.ASR_SUCCESS:
if (data != null) {
Bundle bundle = data.getExtras();
if (bundle != null && bundle.containsKey(MLAsrCaptureConstants.ASR_RESULT)) {
text = bundle.getString(MLAsrCaptureConstants.ASR_RESULT);
TextView textView=findViewById(R.id.text_lang);
textView.setText(text);
}
}
break;
case MLAsrCaptureConstants.ASR_FAILURE:
if(data != null) {
String msg="";
Bundle bundle = data.getExtras();
if(bundle != null && bundle.containsKey(MLAsrCaptureConstants.ASR_ERROR_CODE)) {
int errorCode = bundle.getInt(MLAsrCaptureConstants.ASR_ERROR_CODE);
}
if(bundle != null && bundle.containsKey(MLAsrCaptureConstants.ASR_ERROR_MESSAGE)){
String errorMsg = bundle.getString(MLAsrCaptureConstants.ASR_ERROR_MESSAGE);
msg=errorMsg;
}
if(bundle != null && bundle.containsKey(MLAsrCaptureConstants.ASR_SUB_ERROR_CODE)) {
int subErrorCode = bundle.getInt(MLAsrCaptureConstants.ASR_SUB_ERROR_CODE);
}
Toast.makeText(LangActivity.this,msg,Toast.LENGTH_LONG).show();
}
default:
break;
}
}
}
}
注意这里的ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
是动态添加录音权限。MLApplication.getInstance().setApiKey("CgB6e3x9gLm4...aaxYEnxvjg9");
是添加ApiKey验证。
运行后点击GO按钮启动语音识别。
非华为手机都不能正常运行这个内容。
内容汇总
使用HMS配置很麻烦,既要遵循官方文档,又要随时解决各种奇怪问题,而且几乎所有功能都是必须在华为手机上才能进行测试。一般要注意下面几点:
- 本地项目的包名要和线上应用完全一致。
- 要下载AGC配置文件,放到project模式app根目录。
- 最好先设置好AGC的几个配置,再配置一遍具体服务。
- 要修改项目级构建文件,添加classpath和2个maven仓库。
- 要修改模块级构建文件,添加plugin行,添加各种dependencies。
- 可能需要给Mainifest配置中添加用户权限,还可能要在每个Activity里重复动态添加权限。
- 可能需要在Activity里面添加API key信息。
未完待续。
欢迎批评指正,交流学习。