Identity Kit - Obtaining a User Address - Huawei Developers

Obtaining a User Address
Function
This API is used to display the address selection page when you app needs to use the user's address related information, such as name, contact, and detailed address. After the user selects an address on the page, it returns the address to the app.
Development Procedure
Step 1 Instantiate the request object by using the new UserAddressRequest method. Then, call the getUserAddress API.
Code:
UserAddressRequest req = new UserAddressRequest();
Task<GetUserAddressResult> task = Address.getAddressClient(this).getUserAddress(req);
task.addOnSuccessListener(new OnSuccessListener<GetUserAddressResult>() {
@Override
public void onSuccess(GetUserAddressResult result) {
Log.i(TAG, "onSuccess result code:" + result.getReturnCode());
try {
startActivityForResult(result);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.i(TAG, "on Failed result code:" + e.getMessage());
}
});
Step 2 Display the address selection page by calling the startResolutionForResult method of Status.
Code:
private void startActivityForResult(GetUserAddressResult result) throws IntentSender.SendIntentException {
Status status = result.getStatus();
if (result.getReturnCode() == 0 && status.hasResolution()) {
Log.i(TAG, "the result had resolution.");
status.startResolutionForResult(this, 1000);
} else {
Log.i(TAG, "the result hasn't resolution.");
}
}
Step 3 After the user selects an address, call the parseIntent method of UserAddress in onActivityResult of the page and obtain the address from the returned result.
Code:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.i(TAG, "requestCode=" + requestCode + ", resultCode=" + resultCode);
if (resultCode == Activity.RESULT_OK) {
UserAddress userAddress = UserAddress.parseIntent(data);
// Business process
} else {
// Error Handling
}
}

Related

Android 4.0 SSL Mutual Authentication

Hi,
I've been developing a rss reader which needs to make a mutal ssl authentication. Ive managed to get the user certificate using the Keychain API and have got what seems to a mostly working SSLSocketFactory. But whenever i try to make a connection to the server i get a 401 Unauthorized error, i feel its probably something to do with the way i am setting up my SSL Connection and my general code. If anyone can help point out what im doing wrong and what i need to do i would be very appreciative.
Main Activity:
public class AliasLoader extends AsyncTask<Void, Void, X509Certificate[]>
{
X509Certificate[] chain = null;
@Override protected X509Certificate[] doInBackground(Void... params) {
android.os.Debug.waitForDebugger();
if(!SavedAlias.isEmpty())
{
try {
PrivateKey key2 = KeyChain.getPrivateKey(getApplicationContext(), SavedAlias);
setPrivateKey(key2);
chain = KeyChain.getCertificateChain(getApplicationContext(),SavedAlias);
setCertificate(chain);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
else
{
this.cancel(true);
}
return chain;
}
@Override
protected void onPostExecute(X509Certificate[] chain)
{
if(chain != null)
{
HttpClient client = CustomSSLSocketFactory.getNewHttpClient(context, getAlias(), chain, key);
String formDataServiceUrl = "https://android.diif.r.mil.uk";
WebView wv = (WebView) findViewById(R.id.rssFeedItemView);
HttpPost post = new HttpPost(formDataServiceUrl);
final HttpGet request = new HttpGet(formDataServiceUrl);
HttpResponse result = null;
try {
result = client.execute(post);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
wv.loadUrl(formDataServiceUrl);
}
else
{
Toast.makeText(getApplicationContext(), "Certificate is Empty", Toast.LENGTH_LONG).show();
}
}
}
CustomSSLSocketFactory:
public class CustomSSLSocketFactory extends SSLSocketFactory {
public static KeyStore rootCAtrustStore = null;
public static KeyStore clientKeyStore = null;
SSLContext sslContext = SSLContext.getInstance("TLS");
Context context;
/**
* Constructor.
*/
public CustomSSLSocketFactory(Context context, KeyStore keystore, String keyStorePassword, KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(keystore, keyStorePassword, truststore);
this.context = context;
// custom TrustManager,trusts all servers
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
Log.i("CLIENT CERTIFICATES", "Loaded client certificates: " + keystore.size());
// initialize key manager factory with the client certificate
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keystore,null);
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[] { tm }, null);
//sslContext.init(null, new TrustManager[]{tm}, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
/**
* Create new HttpClient with CustomSSLSocketFactory.
*/
public static HttpClient getNewHttpClient(Context context, String alias, X509Certificate[] chain, PrivateKey key) {
try {
// This is method from tutorial ----------------------------------------------------
//The root CA Trust Store
rootCAtrustStore = KeyStore.getInstance("BKS");
rootCAtrustStore.load(null);
//InputStream in = context.getResources().openRawResource(com.DII.RSS_Viewer.R.raw.rootca);
//rootCAtrustStore.load(in, "PASSWORD".toCharArray());
//The Keystore with client certificates.
//clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
clientKeyStore = KeyStore.getInstance("pkcs12");
clientKeyStore.load(null);
// client certificate is stored in android's keystore
if((alias != null) && (chain != null))
{
Key pKey = key;
clientKeyStore.setKeyEntry(alias, pKey, "password".toCharArray(), chain);
}
//SSLSocketFactory sf = new CustomSSLSocketFactory(context, clientKeyStore, "password", rootCAtrustStore);
SSLSocketFactory sf = new SSLSocketFactory(clientKeyStore, "password");
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", (SocketFactory) sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
}
catch (Exception e)
{
return new DefaultHttpClient();
}
}
}
Hello,
This is a 2 year old post, but I've just had to work with this subject, and I used Apache HTTP Client new version for Android. I think ti's HttpClient 4.3.5.
public void sendRequestToServer(Context context, HttpUriRequest httpUriRequest,
ResponseExecution responseExecution, boolean clientCertAuthenticated)
{
KeyStore trustStore = clientAuthAuthenticator.initializeTrustStore(context);
SSLContext sslcontext = null;
CloseableHttpClient httpclient = null;
try
{
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy());
if(clientCertAuthenticated)
{
KeyStore keyStore = clientAuthAuthenticator
.initializeKeyStore(context, ClientAuthAuthenticator.CLIENT_KEYSTORE_DATA_FILE);
sslContextBuilder.loadKeyMaterial(keyStore, "password".toCharArray());
}
sslcontext = sslContextBuilder.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext, new String[] {"TLSv1"}, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
);
httpclient = HttpClients
.custom()
.setHostnameVerifier(
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
)
.setSSLSocketFactory(sslsf).build();
CloseableHttpResponse response = httpclient.execute(httpUriRequest);
try
{
responseExecution.execute(context, response);
HttpEntity entity = response.getEntity();
if(entity != null)
{
entity.consumeContent();
}
}
finally
{
response.close();
}
}
catch(IOException e)
{
Log.d(ClientCertWebRequestor.class.getName(), "Error in network communication.", e);
}
catch(NoSuchAlgorithmException e)
{
Log.d(ClientCertWebRequestor.class.getName(), "Error in loading keystore.", e);
}
catch(KeyManagementException e)
{
Log.d(ClientCertWebRequestor.class.getName(), "Error in loading keystore.", e);
}
catch(KeyStoreException e)
{
Log.d(ClientCertWebRequestor.class.getName(), "Error in loading keystore.", e);
}
catch(UnrecoverableKeyException e)
{
Log.d(ClientCertWebRequestor.class.getName(), "Error in loading keystore.", e);
}
finally
{
try
{
if(httpclient != null)
{
httpclient.close();
}
}
catch(IOException e)
{
Log.d(ClientCertWebRequestor.class.getName(), "Error in closing network communication.", e);
}
}
}
public static interface ResponseExecution
{
void execute(Context context, CloseableHttpResponse httpResponse) throws IOException;
}
This might help someone in the future. The keystore has the client certificate, it is a PKCS12 keystore (private key + certificate). The trust store is a BKS which stores the server certificate. I did not use the Keychain API though.

Developing A Game for the Android Platform with Huawei Game service-Part 1

More information like this, you can visit HUAWEI Developer Forum
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
What is it?
Huawei Games is a group of APIs from Huawei to simplify some games basic features like leaderboards, achievements, Events and online matches.
Gaming technologies are constantly evolving. Nevertheless, a lot of core gameplay elements have remained unchanged for decades. High scores, leaderboards, quests, achievements, and multiplayer support are examples. If you are developing a game for the Android platform, you don't have to implement any of those elements manually. You can simply use the Huawei Game services APIs instead.
Features of Huawei Game services
· HUAWEI ID sign-in
· Real-name authentication
· Bulletins
· Achievements
· Events
· Leaderboard
· Saved games
· Player statistics
Let’s start!
You should follow the steps
1) Create an android project in android studio.
2) Get the SHA Key. Create SHA key
3) Create a Game App in the Huawei app galley connect (AGC)
4) Provide the SHA key in the information section.
5) Provide storage location.
6) Enable Game service.
7) After all the steps need to download the agconnect-services.json from the app information section. Copy and paste the json file in the app folder of the android project.
8) Copy and paste the below maven url inside the repositories of buildscript and allprojects ( project build.gradle file )
maven { url 'http://developer.huawei.com/repo/'
Add the classpath in the dependencies path
classpath 'com.huawei.agconnect:agcp:1.2.1.300'
9) Copy and paste the below plugin in the app build.gradle file dependencies section.
   apply plugin: 'com.huawei.agconnect'
  Add the below dependencies.
implementation 'com.huawei.hms:base:4.0.4.301'
implementation 'com.huawei.hms:hwid:4.0.4.300'
implementation 'com.huawei.hms:iap:4.0.4.300'
implementation 'com.huawei.hms:game:4.0.3.301'
Note: if you are not using the In-App purchase then no need add the following dependency.
1. implementation 'com.huawei.hms:iap:4.0.4.300'
10) Sync App.
In this series of article we will build Tic Tac Toe game. In this article will see the following features.
· Sign In.
· Initialization.
· Getting player info.
· Saving player info.
Sign In
User can sign-in with Huawei account. They can play game.
Code:
public void signIn() {
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.getService(this, getHuaweiIdParams()).silentSignIn();
authHuaweiIdTask.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
showLog("signIn success");
showLog("display:" + authHuaweiId.getDisplayName());
welcomeTv.setVisibility(View.VISIBLE);
welcomeTv.setText("Welcome back " + authHuaweiId.getDisplayName());
signIn.setVisibility(View.INVISIBLE);
showLog("AT:" + authHuaweiId.getAccessToken());
mAuthid = authHuaweiId;
SignInCenter.get().updateAuthHuaweiId(authHuaweiId);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
signIn.setVisibility(View.VISIBLE);
welcomeTv.setVisibility(View.INVISIBLE);
ApiException apiException = (ApiException) e;
showLog("signIn failed:" + apiException.getStatusCode());
showLog("start getSignInIntent");
signInNewWay();
}
}
});
}
public HuaweiIdAuthParams getHuaweiIdParams() {
return new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME).createParams();
}
public void signInNewWay() {
Intent intent = HuaweiIdAuthManager.getService(SignInActivity.this, getHuaweiIdParams()).getSignInIntent();
startActivityForResult(intent, SIGN_IN_INTENT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (SIGN_IN_INTENT == requestCode) {
handleSignInResult(data);
} else {
showLog("unknown requestCode in onActivityResult");
}
}
private void handleSignInResult(Intent data) {
if (null == data) {
showLog("signIn inetnt is null");
return;
}
// HuaweiIdSignIn.getSignedInAccountFromIntent(data);
String jsonSignInResult = data.getStringExtra("HUAWEIID_SIGNIN_RESULT");
if (TextUtils.isEmpty(jsonSignInResult)) {
showLog("SignIn result is empty");
return;
}
try {
HuaweiIdAuthResult signInResult = new HuaweiIdAuthResult().fromJson(jsonSignInResult);
if (0 == signInResult.getStatus().getStatusCode()) {
showLog("Sign in success.");
showLog("Sign in result: " + signInResult.toJson());
SignInCenter.get().updateAuthHuaweiId(signInResult.getHuaweiId());
} else {
showLog("Sign in failed: " + signInResult.getStatus().getStatusCode());
}
} catch (JSONException var7) {
showLog("Failed to convert json from signInResult.");
}
}
The above show the sign in with Huawei account.
Initialization
Key steps to launch the game
Add the following code to the onCreate method of the Application to register the callback listening function of the activity.
Code:
package com.android.huawei.tictactoe;
import android.app.Application;
import com.huawei.hms.api.HuaweiMobileServicesUtil;
public class TicTacToeApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}
}
Call JosApps.getJosAppsClient to initialize the JosAppsClient object and JosAppsClient.init to initialize the game.
Code:
private void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this, null);
appsClient.init();
Log.i(TAG, "init success");
}
Getting player info
Code:
public void getCurrentPlayer() {
PlayersClientImpl client = (PlayersClientImpl) Games.getPlayersClient(this, getAuthHuaweiId());
Task<Player> task = client.getCurrentPlayer();
task.addOnSuccessListener(new OnSuccessListener<Player>() {
@Override
public void onSuccess(Player player) {
String result = "display:" + player.getDisplayName() + "\n"
+ "playerId:" + player.getPlayerId() + "\n"
+ "playerLevel:" + player.getLevel() + "\n"
+ "timestamp:" + player.getSignTs() + "\n"
+ "playerSign:" + player.getPlayerSign();
showLog(result);
playerId = player.getPlayerId();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
showLog(result);
}
}
});
}
The above code gives the player info like playerId, Player name, player level, in which level he/she is playing.
Saving player info.
Player info can be updated using AppPlayerInfo. Player level, role, rank etc. The following code show the saving player info.
To save player info playerId is mandatory.
Code:
public void savePlayerInfo() {
if (TextUtils.isEmpty(playerId)) {
Toast.makeText(this, "Get the current user first", Toast.LENGTH_SHORT).show();
return;
}
PlayersClient client = Games.getPlayersClient(this, getAuthHuaweiId());
AppPlayerInfo appPlayerInfo = new AppPlayerInfo();
appPlayerInfo.area = "2";
appPlayerInfo.rank = "56";
appPlayerInfo.role = "Pro";
appPlayerInfo.sociaty = "Red Cliff III";
appPlayerInfo.playerId = playerId;
Task<Void> task = client.savePlayerInfo(appPlayerInfo);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
Toast.makeText(SignInActivity.this, "Player info saved successfully ", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Toast.makeText(SignInActivity.this, result, Toast.LENGTH_SHORT).show();
}
}
});
}
Result
Nice, thank you
Can be useful for online games.
Freemind R said:
More information like this, you can visit HUAWEI Developer Forum
​
What is it?
Huawei Games is a group of APIs from Huawei to simplify some games basic features like leaderboards, achievements, Events and online matches.
Gaming technologies are constantly evolving. Nevertheless, a lot of core gameplay elements have remained unchanged for decades. High scores, leaderboards, quests, achievements, and multiplayer support are examples. If you are developing a game for the Android platform, you don't have to implement any of those elements manually. You can simply use the Huawei Game services APIs instead.
Features of Huawei Game services
· HUAWEI ID sign-in
· Real-name authentication
· Bulletins
· Achievements
· Events
· Leaderboard
· Saved games
· Player statistics
Let’s start!
You should follow the steps
1) Create an android project in android studio.
2) Get the SHA Key. Create SHA key
3) Create a Game App in the Huawei app galley connect (AGC)
​
4) Provide the SHA key in the information section.
5) Provide storage location.
6) Enable Game service.
​
7) After all the steps need to download the agconnect-services.json from the app information section. Copy and paste the json file in the app folder of the android project.
​
8) Copy and paste the below maven url inside the repositories of buildscript and allprojects ( project build.gradle file )
maven { url 'http://developer.huawei.com/repo/'
Add the classpath in the dependencies path
classpath 'com.huawei.agconnect:agcp:1.2.1.300'
9) Copy and paste the below plugin in the app build.gradle file dependencies section.
   apply plugin: 'com.huawei.agconnect'
  Add the below dependencies.
implementation 'com.huawei.hms:base:4.0.4.301'
implementation 'com.huawei.hms:hwid:4.0.4.300'
implementation 'com.huawei.hms:iap:4.0.4.300'
implementation 'com.huawei.hms:game:4.0.3.301'
Note: if you are not using the In-App purchase then no need add the following dependency.
1. implementation 'com.huawei.hms:iap:4.0.4.300'
10) Sync App.
In this series of article we will build Tic Tac Toe game. In this article will see the following features.
· Sign In.
· Initialization.
· Getting player info.
· Saving player info.
Sign In
User can sign-in with Huawei account. They can play game.
Code:
public void signIn() {
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.getService(this, getHuaweiIdParams()).silentSignIn();
authHuaweiIdTask.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
showLog("signIn success");
showLog("display:" + authHuaweiId.getDisplayName());
welcomeTv.setVisibility(View.VISIBLE);
welcomeTv.setText("Welcome back " + authHuaweiId.getDisplayName());
signIn.setVisibility(View.INVISIBLE);
showLog("AT:" + authHuaweiId.getAccessToken());
mAuthid = authHuaweiId;
SignInCenter.get().updateAuthHuaweiId(authHuaweiId);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
signIn.setVisibility(View.VISIBLE);
welcomeTv.setVisibility(View.INVISIBLE);
ApiException apiException = (ApiException) e;
showLog("signIn failed:" + apiException.getStatusCode());
showLog("start getSignInIntent");
signInNewWay();
}
}
});
}
public HuaweiIdAuthParams getHuaweiIdParams() {
return new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME).createParams();
}
public void signInNewWay() {
Intent intent = HuaweiIdAuthManager.getService(SignInActivity.this, getHuaweiIdParams()).getSignInIntent();
startActivityForResult(intent, SIGN_IN_INTENT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (SIGN_IN_INTENT == requestCode) {
handleSignInResult(data);
} else {
showLog("unknown requestCode in onActivityResult");
}
}
private void handleSignInResult(Intent data) {
if (null == data) {
showLog("signIn inetnt is null");
return;
}
// HuaweiIdSignIn.getSignedInAccountFromIntent(data);
String jsonSignInResult = data.getStringExtra("HUAWEIID_SIGNIN_RESULT");
if (TextUtils.isEmpty(jsonSignInResult)) {
showLog("SignIn result is empty");
return;
}
try {
HuaweiIdAuthResult signInResult = new HuaweiIdAuthResult().fromJson(jsonSignInResult);
if (0 == signInResult.getStatus().getStatusCode()) {
showLog("Sign in success.");
showLog("Sign in result: " + signInResult.toJson());
SignInCenter.get().updateAuthHuaweiId(signInResult.getHuaweiId());
} else {
showLog("Sign in failed: " + signInResult.getStatus().getStatusCode());
}
} catch (JSONException var7) {
showLog("Failed to convert json from signInResult.");
}
}
The above show the sign in with Huawei account.
Initialization
Key steps to launch the game
Add the following code to the onCreate method of the Application to register the callback listening function of the activity.
Code:
package com.android.huawei.tictactoe;
import android.app.Application;
import com.huawei.hms.api.HuaweiMobileServicesUtil;
public class TicTacToeApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}
}
Call JosApps.getJosAppsClient to initialize the JosAppsClient object and JosAppsClient.init to initialize the game.
Code:
private void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this, null);
appsClient.init();
Log.i(TAG, "init success");
}
Getting player info
Code:
public void getCurrentPlayer() {
PlayersClientImpl client = (PlayersClientImpl) Games.getPlayersClient(this, getAuthHuaweiId());
Task<Player> task = client.getCurrentPlayer();
task.addOnSuccessListener(new OnSuccessListener<Player>() {
@Override
public void onSuccess(Player player) {
String result = "display:" + player.getDisplayName() + "\n"
+ "playerId:" + player.getPlayerId() + "\n"
+ "playerLevel:" + player.getLevel() + "\n"
+ "timestamp:" + player.getSignTs() + "\n"
+ "playerSign:" + player.getPlayerSign();
showLog(result);
playerId = player.getPlayerId();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
showLog(result);
}
}
});
}
The above code gives the player info like playerId, Player name, player level, in which level he/she is playing.
Saving player info.
Player info can be updated using AppPlayerInfo. Player level, role, rank etc. The following code show the saving player info.
To save player info playerId is mandatory.
Code:
public void savePlayerInfo() {
if (TextUtils.isEmpty(playerId)) {
Toast.makeText(this, "Get the current user first", Toast.LENGTH_SHORT).show();
return;
}
PlayersClient client = Games.getPlayersClient(this, getAuthHuaweiId());
AppPlayerInfo appPlayerInfo = new AppPlayerInfo();
appPlayerInfo.area = "2";
appPlayerInfo.rank = "56";
appPlayerInfo.role = "Pro";
appPlayerInfo.sociaty = "Red Cliff III";
appPlayerInfo.playerId = playerId;
Task<Void> task = client.savePlayerInfo(appPlayerInfo);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
Toast.makeText(SignInActivity.this, "Player info saved successfully ", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Toast.makeText(SignInActivity.this, result, Toast.LENGTH_SHORT).show();
}
}
});
}
Result
​
Click to expand...
Click to collapse
Whtat is the difference between sign in and Silent Sign in

Geofence Notification with Push Kit

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
Hello everyone, In this article, I will talk about how we can use together Geofence and Push Kit. When the device enters a set location, we will send a notification to the user using Push Kit.
Geofence : It is an important feature in the Location Kit. Geofence is actually used to draw a geographic virtual boundary.
Push Kit : Push kit is essentially a messaging service. There are two different message types. These are notification and data messages. We will use the notification messages in this article.
1- Huawei Core Integration
To use Geofence and Push kit services, you must first integrate the necessary kits into your project. You can use the document in the link to easily integrate the Location and Push kit into your project.
2- Add Permissions
After the HMS Core integration is finished, we need to add permissions to the AndroidManifest.xml file in order to access the user’s location and internet.
XML:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
3- Developing the Push Kit Part
To send a notification to the device using a push kit, firstly the device must receive a push token.
Java:
private void getPushToken() {
new Thread() {
@Override
public void run() {
super.run();
try {
String appId = AGConnectServicesConfig.fromContext(MainActivity.this).getString("client/app_id");
String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM");
if (!TextUtils.isEmpty(token)) {
DataStore.pushToken = token;
}
} catch (ApiException e) {
Log.e("TokenFailed", "get token failed" + e);
}
}
}.start();
}
We have received a push token, now we need to reach the access token, and we will do this through the service. We will obtain access token through the service, you must also complete the Retrofit implementations. Add Retrofit libraries app level build.gradle
Code:
implementation "com.squareup.retrofit2:retrofit:2.3.0"
implementation "com.squareup.retrofit2:converter-gson:2.3.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
In order to send access token, first we should prepare our request. This request should have grant_type ,client_id ,client_secret and will return AccessToken. Then, we will use this AccessToken for out further requests.
Java:
public interface AccessTokenInterface {
@FormUrlEncoded
@POST("v2/token")
Call<AccessToken> GetAccessToken(
@Field("grant_type") String grantType,
@Field("client_id") int clientId,
@Field("client_secret") String clientSecret);
}
Now let’s handle the method by which we will obtain the access token. We need a Base URL to use in this method. The variable defined as OAUTH_BASE_URL represents our base URL. Do not forget to fill in client_credentials, YOUR_CLIENT_ID, YOUR_CLIENT_SECRET parts according to your project. This getAccessToken() was created using Synchronous Call. You can do this with Asynchronous Call according to the needs of your own project.
Java:
public void getAccessToken() {
String YOUR_CLIENT_SECRET =" ";
int YOUR_CLIENT_ID = ;
AccessInterface apiInterface = RetrofitClient.getClient(OAUTH_BASE_URL).create(AccessInterface.class);
Call<AccessToken> call = apiInterface.GetAccessToken("client_credentials",YOUR_CLIENT_ID , YOUR_CLIENT_SECRET);
try{
Response<AccessToken> response = call.execute();
accessToken = String.format("Bearer %s",response.body().getAccessToken());
}catch (IOException e){
e.printStackTrace();
}
}
After obtaining the access token, we create an interface to send a notification with the push kit. Do not forget to fill the {YOUR_APP_ID} part of your project app ID.
Java:
public interface NotificationInterface {
@Headers("Content-Type:application/json")
@POST("{YOUR_APP_ID}/messages:send")
Call<PushParameter> sendNotification(
@Header("Authorization") String authorization,
@Body NotificationMessage notificationMessage);
}
Java:
public void sendNotification(String accesstoken, String geofenceDetail) {
NotificationInterface notiInterface = RetrofitClient.getClient(PUSH_API_URL).create(NotificationInterface.class);
NotificationMessage notificationMessage = (new NotificationMessage
.Builder("Title of Notification", geofenceDetail, DataStore.pushToken, "1"))
.build();
Call<PushParameter> callNoti = notiInterface.sendNotification(accesstoken, notificationMessage);
callNoti.enqueue(new Callback<PushParameter>() {
@Override
public void onResponse(Call<PushParameter> call, Response<PushParameter> response) {
Log.i("SendNotification", response.body().getMsg());
}
@Override
public void onFailure(Call<PushParameter> call, Throwable t) {
Log.i("SendNotification Failure", t.toString());
}
});
}
4- Developing the Geofence Part
We have set up the push kit to send notifications, now let’s see how we will send these notifications for geofence. First we create a broadcast receiver for geofence.
Java:
public class GeofenceBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
GeofenceNotification.enqueueWork(context,intent);
}
}
When the Broadcast Receiver is triggered, our geofence notifications will be sent through this class. You can see the accessToken and sendNotification methods we use for push kit in this class.
Java:
public class GeofenceNotification extends JobIntentService {
public static final String PUSH_API_URL = "https://push-api.cloud.huawei.com/v1/";
public static final String OAUTH_BASE_URL = "https://login.cloud.huawei.com/oauth2/";
private String accessToken;
public static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, GeofenceNotification.class, 573, intent);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
GeofenceData geofenceData = GeofenceData.getDataFromIntent(intent);
if (geofenceData != null) {
int conversion = geofenceData.getConversion();
ArrayList<Geofence> geofenceTransition = (ArrayList<Geofence>) geofenceData.getConvertingGeofenceList();
String geofenceTransitionDetails = getGeofenceTransitionDetails(conversion,
geofenceTransition);
getAccessToken();
sendNotification(accessToken, geofenceTransitionDetails);
}
}
private String getGeofenceTransitionDetails(int conversion, ArrayList<Geofence> triggeringGeofences) {
String geofenceConversion = getConversionString(conversion);
ArrayList<String> triggeringGeofencesIdsList = new ArrayList<>();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getUniqueId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);
return String.format("%s: %s",geofenceConversion,triggeringGeofencesIdsString);
}
private String getConversionString(int conversionType) {
switch (conversionType) {
case Geofence.ENTER_GEOFENCE_CONVERSION:
return getString(R.string.geofence_transition_entered);
case Geofence.EXIT_GEOFENCE_CONVERSION:
return getString(R.string.geofence_transition_exited);
case Geofence.DWELL_GEOFENCE_CONVERSION:
return getString(R.string.geofence_transition_dwell);
default:
return getString(R.string.unknown_geofence_transition);
}
}
public void sendNotification(String accesstoken, String geofenceDetail) {
NotificationInterface notiInterface = RetrofitClient.getClient(PUSH_API_URL).create(NotificationInterface.class);
NotificationMessage notificationMessage = (new NotificationMessage.Builder("Title of Notification", geofenceDetail, DataClass.pushToken, "1")).build();
Call<PushParameter> callNoti = notiInterface.sendNotification(accesstoken, notificationMessage);
callNoti.enqueue(new Callback<PushParameter>() {
@Override
public void onResponse(Call<PushParameter> call, Response<PushParameter> response) {
Log.i("SendNotification", response.body().getMsg());
}
@Override
public void onFailure(Call<PushParameter> call, Throwable t) {
Log.i("SendNotification Failure", t.toString());
}
});
}
public void getAccessToken() {
String YOUR_CLIENT_SECRET =" ";
int YOUR_CLIENT_ID = ;
AccessInterface apiInterface = RetrofitClient.getClient(OAUTH_BASE_URL).create(AccessInterface.class);
Call<AccessToken> call = apiInterface.GetAccessToken("client_credentials",YOUR_CLIENT_ID , YOUR_CLIENT_SECRET);
try{
Response<AccessToken> response = call.execute();
accessToken = String.format("Bearer %s",response.body().getAccessToken());
}catch (IOException e){
e.printStackTrace();
}
}
}
Then we add the methods we use to create a geofence list. In this project, I have defined geofences as static. You can adjust these geofence information according to the needs of your application. For example, if your location information is kept in the database, you can use geofence locations from the database. When adding geofences in the completeGeofenceList method, pay attention to the unique id part. If you try to add geofences with the same ids, you will get an error.
Java:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String TAG = "MainActivity";
private FusedLocationProviderClient fusedLocationProviderClient;
private PendingIntent geofencePendingIntent;
private ArrayList<Geofence> geofenceList;
private GeofenceService geofenceService;
private SettingsClient settingsClient;
LocationCallback locationCallback;
LocationRequest locationRequest;
private String pushToken;
private Marker mMarker;
private MapView mapView;
private HuaweiMap hMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
permissionCheck();
mapView = findViewById(R.id.mapView);
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle("MapViewBundleKey");
}
mapView.onCreate(mapViewBundle);
mapView.getMapAsync(this);
geofenceService = LocationServices.getGeofenceService(getApplicationContext());
getPushToken();
completeGeofenceList();
createGeofence();
}
public void onMapReady(HuaweiMap huaweiMap) {
hMap = huaweiMap;
hMap.setMyLocationEnabled(true);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1){
if (grantResults.length > 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION successful");
} else {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSSION failed");
}
}
else if (requestCode == 2) {
if (grantResults.length > 2 && grantResults[2] == PackageManager.PERMISSION_GRANTED
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION successful");
} else {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION failed");
}
}
}
private void permissionCheck(){
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "sdk < 28 Q");
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings =
{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
ActivityCompat.requestPermissions(this, strings, 1);
}
} else {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION};
ActivityCompat.requestPermissions(this, strings, 2);
}
}
}
private GeofenceRequest getGeofencingRequest() {
return new GeofenceRequest.Builder()
.setInitConversions(GeofenceRequest.ENTER_INIT_CONVERSION)
.createGeofenceList(geofenceList)
.build();
}
private PendingIntent getGeofencePendingIntent() {
Intent intent = new Intent(MainActivity.this, GeofenceBroadcast.class);
geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return geofencePendingIntent;
}
private void completeGeofenceList() {
Geofence.Builder geoBuild = new Geofence.Builder();
geofenceList = new ArrayList<>();
geofenceList.add(geoBuild.setUniqueId("Home").setRoundArea(39.617841289998736,27.429383486070098,200).setValidContinueTime(Geofence.GEOFENCE_NEVER_EXPIRE).setConversions(Geofence.ENTER_GEOFENCE_CONVERSION).setDwellDelayTime(1000).build());
geofenceList.add(geoBuild.setUniqueId("Office").setRoundArea(38.14893633264862,26.82832426954628,200).setValidContinueTime(Geofence.GEOFENCE_NEVER_EXPIRE).setConversions(Geofence.ENTER_GEOFENCE_CONVERSION).setDwellDelayTime(1000).build());
}
private void createGeofence() {
geofenceService.createGeofenceList(getGeofencingRequest(), getGeofencePendingIntent());
}
private void getPushToken() {
new Thread() {
@Override
public void run() {
super.run();
try {
String appId = AGConnectServicesConfig.fromContext(MainActivity.this).getString("client/app_id");
String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM");
if (!TextUtils.isEmpty(token)) {
DataStore.pushToken1 = token;
}
} catch (ApiException e) {
Log.e("TokenFailed", "get token failed" + e);
}
}
}.start();
}
}
Sample application outputs for the use of push kit with geofence are as follows;
Conclusion
By using the push kit features, you can personalize your notifications according to the needs of your application. In this article I explained how to use the Push kit for Geofence notifications. I hope you will like it. Thank you for reading. If you have any questions, you can leave a comment.
References
Geofence Service
Push Kit

Beginner: Integration of Lite Wearable security app with Huawei Wear Engine

Introduction
In this article, will explain how to develop a security application in Lite wearable. To achieve it we have to use the Wear Engine library. It will give us the solution for communication between Harmony wearable and android smartphone.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Requirements
1) DevEco IDE.
2) Lite wearable watch.
3) Android Smartphone.
4) Huawei developer account.
Integration process
The integration process contains two parts. Android smartphone side and Wear app side.
Android side
Step 1: Create the android project on Android studio.
Step 2: Generate Android signature files.
Step 3: Generate SHA -256 from the keystore generated. Please refer this link. https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0
Step 4: Navigate to Huawei developer console. Click on Huawei ID (https://developer.huawei.com/consumer/en/console#/productlist/32).
Step 5: Create new product. Add the SHA-256 as the first signed certificate.
Step 6: Click Wear Engine under App services.
Step 7: Click Apply for Wear Engine, agree to the agreement, and the screen for the data permission application is displayed.
Wait for the approval.
Step 8: Open the project-level build gradle of your Android project.
Step 9: Navigateto buildscript > repositories and add the Maven repository configurations.
Java:
maven {url 'https://developer.huawei.com/repo/'}
Step 10: Navigate to allprojects > repositories and add the Maven repository address
Java:
maven {url 'https://developer.huawei.com/repo/'}
Step 11: Add wear engine sdk on the build gradle.
Java:
implementation 'com.huawei.hms:wearengine:{version}'
Step 12: Add the proguard rules in proguard-rules.pro
Java:
<p>-keepattributes *Annotation*
-keepattributes Signature
-keepattributes InnerClasses
-keepattributes EnclosingMethod
-keep class com.huawei.wearengine.**{*;}
</p>
Step 13: Add code snippet to Search for the available device on the MainActivity.java
Java:
private void searchAvailableDevices() {
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.hasAvailableDevices().addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
checkPermissionGranted();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
Step 14: If the devices are available call for device permission granted or not.
Java:
private void checkPermissionGranted() {
AuthClient authClient = HiWear.getAuthClient(this);
authClient.checkPermission(Permission.DEVICE_MANAGER).addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
if (!aBoolean) {
askPermission();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
Step 15: If permission is not granted ask for permission.
Java:
private void askPermission() {
AuthClient authClient = HiWear.getAuthClient(this);
AuthCallback authCallback = new AuthCallback() {
@Override
public void onOk(Permission[] permissions) {
if (permissions.length != 0) {
checkCurrentConnectedDevice();
}
}
@Override
public void onCancel() {
}
};
authClient.requestPermission(authCallback, Permission.DEVICE_MANAGER)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
Step 16: Get the connected device object for the communication.
Java:
private void checkCurrentConnectedDevice() {
final List<Device> deviceList = new ArrayList<>();
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.getBondedDevices()
.addOnSuccessListener(new OnSuccessListener<List<Device>>() {
@Override
public void onSuccess(List<Device> devices) {
deviceList.addAll(devices);
if (!deviceList.isEmpty()) {
for (Device device : deviceList) {
if (device.isConnected()) {
connectedDevice = device;
}
}
}
if (connectedDevice != null) {
checkAppInstalledInWatch(connectedDevice);
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Process logic when the device list fails to be obtained
}
});
}
Step 17: Call pingfunction to check if the Wear app is installed on the watch.
Java:
private void checkAppInstalledInWatch(final Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
if (connectedDevice != null && connectedDevice.isConnected()) {
p2pClient.ping(connectedDevice, new PingCallback() {
@Override
public void onPingResult(int errCode) {
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
Step 18: If the ping is success your watch app will launch automatically.
Step 19: Add Password check method on click listener function.
Java:
@Override
public void onClick(View view) {
if (view.getId() == R.id.btLogin) {
if (etPin.getText().toString().equals("1234")) {
sendMessageToWatch("Success", connectedDevice);
} else {
sendMessageToWatch("Wrong password", connectedDevice);
}
}
}
Step 20: Send message to the watch.
Java:
private void sendMessageToWatch(String message, Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
String peerFingerPrint = "com.wearengine.huawei_BALgPWTbV2CKZ9swMfG1n9ReRlQFqiZrEGWyVQp/6UIgCUsgXn7PojLPA4iatPktya1pLAORwvHgHpv/Z5DfMK8=";
p2pClient.setPeerFingerPrint(peerFingerPrint);
Message.Builder builder = new Message.Builder();
builder.setPayload(message.getBytes(StandardCharsets.UTF_8));
Message sendMessage = builder.build();
SendCallback sendCallback = new SendCallback() {
@Override
public void onSendResult(int resultCode) {
}
@Override
public void onSendProgress(long progress) {
}
};
if (connectedDevice != null && connectedDevice.isConnected() && sendMessage != null && sendCallback != null) {
p2pClient.send(connectedDevice, sendMessage, sendCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//Related processing logic for your app after the send command runs
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Related processing logic for your app after the send command fails to run
}
});
}
Step 21: Generate the p2p fingerprint. Please follow this article - https://forums.developer.huawei.com/forumPortal/en/topic/0202466737940270075
The final code for your android application will be as given below.
Java:
package com.phone.wearengine;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.wearengine.HiWear;
import com.huawei.wearengine.auth.AuthCallback;
import com.huawei.wearengine.auth.AuthClient;
import com.huawei.wearengine.auth.Permission;
import com.huawei.wearengine.device.Device;
import com.huawei.wearengine.device.DeviceClient;
import com.huawei.wearengine.p2p.Message;
import com.huawei.wearengine.p2p.P2pClient;
import com.huawei.wearengine.p2p.PingCallback;
import com.huawei.wearengine.p2p.SendCallback;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Device connectedDevice;
private EditText etPin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUi();
searchAvailableDevices();
checkCurrentConnectedDevice();
}
private void initUi() {
etPin = findViewById(R.id.etPin);
findViewById(R.id.btLogin).setOnClickListener(this);
}
private void searchAvailableDevices() {
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.hasAvailableDevices().addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
checkPermissionGranted();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
private void checkPermissionGranted() {
AuthClient authClient = HiWear.getAuthClient(this);
authClient.checkPermission(Permission.DEVICE_MANAGER).addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
if (!aBoolean) {
askPermission();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
private void askPermission() {
AuthClient authClient = HiWear.getAuthClient(this);
AuthCallback authCallback = new AuthCallback() {
@Override
public void onOk(Permission[] permissions) {
if (permissions.length != 0) {
checkCurrentConnectedDevice();
}
}
@Override
public void onCancel() {
}
};
authClient.requestPermission(authCallback, Permission.DEVICE_MANAGER)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
private void checkCurrentConnectedDevice() {
final List<Device> deviceList = new ArrayList<>();
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.getBondedDevices()
.addOnSuccessListener(new OnSuccessListener<List<Device>>() {
@Override
public void onSuccess(List<Device> devices) {
deviceList.addAll(devices);
if (!deviceList.isEmpty()) {
for (Device device : deviceList) {
if (device.isConnected()) {
connectedDevice = device;
}
}
}
if (connectedDevice != null) {
checkAppInstalledInWatch(connectedDevice);
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Process logic when the device list fails to be obtained
}
});
}
private void checkAppInstalledInWatch(final Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
if (connectedDevice != null && connectedDevice.isConnected()) {
p2pClient.ping(connectedDevice, new PingCallback() {
@Override
public void onPingResult(int errCode) {
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
}
private void sendMessageToWatch(String message, Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
String peerFingerPrint = "com.wearengine.huawei_BALgPWTbV2CKZ9swMfG1n9ReRlQFqiZrEG*******";
p2pClient.setPeerFingerPrint(peerFingerPrint);
Message.Builder builder = new Message.Builder();
builder.setPayload(message.getBytes(StandardCharsets.UTF_8));
Message sendMessage = builder.build();
SendCallback sendCallback = new SendCallback() {
@Override
public void onSendResult(int resultCode) {
}
@Override
public void onSendProgress(long progress) {
}
};
if (connectedDevice != null && connectedDevice.isConnected() && sendMessage != null && sendCallback != null) {
p2pClient.send(connectedDevice, sendMessage, sendCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//Related processing logic for your app after the send command runs
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Related processing logic for your app after the send command fails to run
}
});
}
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btLogin) {
if (etPin.getText().toString().equals("1234")) {
sendMessageToWatch("Success", connectedDevice);
} else {
sendMessageToWatch("Wrong password", connectedDevice);
}
}
}
}
Watch side
Step 1: Create a Lite Wearable project on DevEco studio.
Step 2: Generate the required certificates to run the application. Please refer to this article https://forums.developer.huawei.com/forumPortal/en/topic/0202465210302250053
Step 3: Download and Add the Wear Engine library in the pages folder of the Harmony project. https://developer.huawei.com/consum...ity-Library/litewearable-sdk-0000001053562589
Step 4: Design the UI.
Index.hml
HTML:
<div class="container">
<text class="title">
{{title}}
</text>
</div>
Index.css
CSS:
.container {
display: flex;
justify-content: center;
align-items: center;
left: 0px;
top: 0px;
width: 454px;
height: 454px;
background-color: cadetblue;
}
.title {
font-size: 90px;
text-align: center;
width: 300px;
height: 150px;
}
Step 5: Open index.js file and import the wearengine SDK.
JavaScript:
import {P2pClient, Message, Builder} from '../wearengine';
Step 6: Add the receiver code snippet on index.js.
JavaScript:
onInit() {
var _that = this;
_that.setBrightnessKeepScreenOn();
//Step 1: Obtain the point-to-point communication object
var p2pClient = new P2pClient();
var peerPkgName = "com.phone.wearengine";
var peerFinger = "79C3B257672C32974283E712EF7FEC******";
//Step 2: Set your app package name that needs communications on the phone
p2pClient.setPeerPkgName(peerPkgName);
//Step 3: Set the fingerprint information of the app on the phone. (This API is unavailable currently. In this version, you need to set fingerprint mode in the config.json file in Step 5.)
p2pClient.setPeerFingerPrint(peerFinger);
//Step 4: Receive short messages or files from your app on the phone
//Define the receiver
var flash = this;
var receiver = {
onSuccess: function () {
console.info("Recieved message");
//Process the callback function returned when messages or files fail to be received from the phone during registration.
flash.receiveMessageOK = "Succeeded in receiving the message";
},
onFailure: function () {
console.info("Failed message");
//Registering a listener for the callback method of failing to receive messages or files from phone
flash.receiveMessageOK = "Failed to receive the message";
},
onReceiveMessage: function (data) {
if (data && data.isFileType) {
//Process the file sent by your app on the phone
flash.receiveMessgeOK = "file:" + data.name;
} else {
console.info("Got message - " + data);
//Process the message sent from your app on the phone.
flash.receiveMessageOK = "message:" + data;
_that.title = "" + data;
if (data != "Success") {
vibrator.vibrate({
mode: "long"
})
}
}
},
}
p2pClient.registerReceiver(receiver);
},
PeerFingerPrint on watch side is SHA-256 of Android application (Make sure you have removed the colons)
Step 7: Unregister the receiver on destroy of wearable app.
Java:
onDestroy() {
this.p2pClient.unregisterReceiver();
}
Step 8: Add metadata inside of module object of config.json.
JSON:
"metaData": {
"customizeData": [
{
"name": "supportLists",
"value": "com.phone.wearengine:79C3B257672C32974283E756535C86728BE4DF51E*******",
"extra": ""
}
]
}
The final code for your android application given below.
JavaScript:
import {P2pClient, Message, Builder} from '../wearengine';
import brightness from '@system.brightness';
import vibrator from '@system.vibrator';
export default {
data: {
title: 'Enter pin'
},
onInit() {
var _that = this;
_that.setBrightnessKeepScreenOn();
//Step 1: Obtain the point-to-point communication object
var p2pClient = new P2pClient();
var peerPkgName = "com.phone.wearengine";
var peerFinger = "79C3B257672C32974283E756535C*****************";
//Step 2: Set your app package name that needs communications on the phone
p2pClient.setPeerPkgName(peerPkgName);
//Step 3: Set the fingerprint information of the app on the phone. (This API is unavailable currently. In this version, you need to set fingerprint mode in the config.json file in Step 5.)
p2pClient.setPeerFingerPrint(peerFinger);
//Step 4: Receive short messages or files from your app on the phone
//Define the receiver
var flash = this;
var receiver = {
onSuccess: function () {
console.info("Recieved message");
//Process the callback function returned when messages or files fail to be received from the phone during registration.
flash.receiveMessageOK = "Succeeded in receiving the message";
},
onFailure: function () {
console.info("Failed message");
//Registering a listener for the callback method of failing to receive messages or files from phone
flash.receiveMessageOK = "Failed to receive the message";
},
onReceiveMessage: function (data) {
if (data && data.isFileType) {
//Process the file sent by your app on the phone
flash.receiveMessgeOK = "file:" + data.name;
} else {
console.info("Got message - " + data);
//Process the message sent from your app on the phone.
flash.receiveMessageOK = "message:" + data;
_that.title = "" + data;
if (data != "Success") {
vibrator.vibrate({
mode: "long"
})
}
}
},
}
p2pClient.registerReceiver(receiver);
},
setBrightnessKeepScreenOn: function () {
brightness.setKeepScreenOn({
keepScreenOn: true,
success: function () {
console.log("handling set keep screen on success")
},
fail: function (data, code) {
console.log("handling set keep screen on fail, code:" + code);
}
});
},
onDestroy() {
// FeatureAbility.unsubscribeMsg();
this.p2pClient.unregisterReceiver();
}
}
Results
Tips & Tricks
Make sure you are generated the SHA - 256 fingerprint of proper keystore.
Follow the P2P generation steps properly.
Conclusion
In this article, we are learned how to develop a security app using Wear Engine. The wear engine will allow us to communicate between the Android application and the Harmony Wear application.
Reference
Harmony Official document - https://developer.harmonyos.com/en/docs/documentation/doc-guides/harmonyos-overview-0000000000011903
Wear Engine documentation - https://developer.huawei.com/consumer/en/doc/development/connectivity-Guides/service-introduction-0000001050978399
Certificate generation article - https://forums.developer.huawei.com/forumPortal/en/topic/0202465210302250053
P2P generation article - https://forums.developer.huawei.com/forumPortal/en/topic/0202466737940270075
Interesting app.
Nice article
ask011 said:
Introduction
In this article, will explain how to develop a security application in Lite wearable. To achieve it we have to use the Wear Engine library. It will give us the solution for communication between Harmony wearable and android smartphone.
Requirements
1) DevEco IDE.
2) Lite wearable watch.
3) Android Smartphone.
4) Huawei developer account.
Integration process
The integration process contains two parts. Android smartphone side and Wear app side.
Android side
Step 1: Create the android project on Android studio.
Step 2: Generate Android signature files.
Step 3: Generate SHA -256 from the keystore generated. Please refer this link. https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0
Step 4: Navigate to Huawei developer console. Click on Huawei ID (https://developer.huawei.com/consumer/en/console#/productlist/32).
Step 5: Create new product. Add the SHA-256 as the first signed certificate.
Step 6: Click Wear Engine under App services.
Step 7: Click Apply for Wear Engine, agree to the agreement, and the screen for the data permission application is displayed.
Wait for the approval.
Step 8: Open the project-level build gradle of your Android project.
Step 9: Navigateto buildscript > repositories and add the Maven repository configurations.
Java:
maven {url 'https://developer.huawei.com/repo/'}
Step 10: Navigate to allprojects > repositories and add the Maven repository address
Java:
maven {url 'https://developer.huawei.com/repo/'}
Step 11: Add wear engine sdk on the build gradle.
Java:
implementation 'com.huawei.hms:wearengine:{version}'
Step 12: Add the proguard rules in proguard-rules.pro
Java:
<p>-keepattributes *Annotation*
-keepattributes Signature
-keepattributes InnerClasses
-keepattributes EnclosingMethod
-keep class com.huawei.wearengine.**{*;}
</p>
Step 13: Add code snippet to Search for the available device on the MainActivity.java
Java:
private void searchAvailableDevices() {
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.hasAvailableDevices().addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
checkPermissionGranted();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
Step 14: If the devices are available call for device permission granted or not.
Java:
private void checkPermissionGranted() {
AuthClient authClient = HiWear.getAuthClient(this);
authClient.checkPermission(Permission.DEVICE_MANAGER).addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
if (!aBoolean) {
askPermission();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
Step 15: If permission is not granted ask for permission.
Java:
private void askPermission() {
AuthClient authClient = HiWear.getAuthClient(this);
AuthCallback authCallback = new AuthCallback() {
@Override
public void onOk(Permission[] permissions) {
if (permissions.length != 0) {
checkCurrentConnectedDevice();
}
}
@Override
public void onCancel() {
}
};
authClient.requestPermission(authCallback, Permission.DEVICE_MANAGER)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
Step 16: Get the connected device object for the communication.
Java:
private void checkCurrentConnectedDevice() {
final List<Device> deviceList = new ArrayList<>();
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.getBondedDevices()
.addOnSuccessListener(new OnSuccessListener<List<Device>>() {
@Override
public void onSuccess(List<Device> devices) {
deviceList.addAll(devices);
if (!deviceList.isEmpty()) {
for (Device device : deviceList) {
if (device.isConnected()) {
connectedDevice = device;
}
}
}
if (connectedDevice != null) {
checkAppInstalledInWatch(connectedDevice);
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Process logic when the device list fails to be obtained
}
});
}
Step 17: Call pingfunction to check if the Wear app is installed on the watch.
Java:
private void checkAppInstalledInWatch(final Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
if (connectedDevice != null && connectedDevice.isConnected()) {
p2pClient.ping(connectedDevice, new PingCallback() {
@Override
public void onPingResult(int errCode) {
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
Step 18: If the ping is success your watch app will launch automatically.
Step 19: Add Password check method on click listener function.
Java:
@Override
public void onClick(View view) {
if (view.getId() == R.id.btLogin) {
if (etPin.getText().toString().equals("1234")) {
sendMessageToWatch("Success", connectedDevice);
} else {
sendMessageToWatch("Wrong password", connectedDevice);
}
}
}
Step 20: Send message to the watch.
Java:
private void sendMessageToWatch(String message, Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
String peerFingerPrint = "com.wearengine.huawei_BALgPWTbV2CKZ9swMfG1n9ReRlQFqiZrEGWyVQp/6UIgCUsgXn7PojLPA4iatPktya1pLAORwvHgHpv/Z5DfMK8=";
p2pClient.setPeerFingerPrint(peerFingerPrint);
Message.Builder builder = new Message.Builder();
builder.setPayload(message.getBytes(StandardCharsets.UTF_8));
Message sendMessage = builder.build();
SendCallback sendCallback = new SendCallback() {
@Override
public void onSendResult(int resultCode) {
}
@Override
public void onSendProgress(long progress) {
}
};
if (connectedDevice != null && connectedDevice.isConnected() && sendMessage != null && sendCallback != null) {
p2pClient.send(connectedDevice, sendMessage, sendCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//Related processing logic for your app after the send command runs
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Related processing logic for your app after the send command fails to run
}
});
}
Step 21: Generate the p2p fingerprint. Please follow this article - https://forums.developer.huawei.com/forumPortal/en/topic/0202466737940270075
The final code for your android application will be as given below.
Java:
package com.phone.wearengine;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.wearengine.HiWear;
import com.huawei.wearengine.auth.AuthCallback;
import com.huawei.wearengine.auth.AuthClient;
import com.huawei.wearengine.auth.Permission;
import com.huawei.wearengine.device.Device;
import com.huawei.wearengine.device.DeviceClient;
import com.huawei.wearengine.p2p.Message;
import com.huawei.wearengine.p2p.P2pClient;
import com.huawei.wearengine.p2p.PingCallback;
import com.huawei.wearengine.p2p.SendCallback;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Device connectedDevice;
private EditText etPin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUi();
searchAvailableDevices();
checkCurrentConnectedDevice();
}
private void initUi() {
etPin = findViewById(R.id.etPin);
findViewById(R.id.btLogin).setOnClickListener(this);
}
private void searchAvailableDevices() {
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.hasAvailableDevices().addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
checkPermissionGranted();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
private void checkPermissionGranted() {
AuthClient authClient = HiWear.getAuthClient(this);
authClient.checkPermission(Permission.DEVICE_MANAGER).addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
if (!aBoolean) {
askPermission();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
private void askPermission() {
AuthClient authClient = HiWear.getAuthClient(this);
AuthCallback authCallback = new AuthCallback() {
@Override
public void onOk(Permission[] permissions) {
if (permissions.length != 0) {
checkCurrentConnectedDevice();
}
}
@Override
public void onCancel() {
}
};
authClient.requestPermission(authCallback, Permission.DEVICE_MANAGER)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
private void checkCurrentConnectedDevice() {
final List<Device> deviceList = new ArrayList<>();
DeviceClient deviceClient = HiWear.getDeviceClient(this);
deviceClient.getBondedDevices()
.addOnSuccessListener(new OnSuccessListener<List<Device>>() {
@Override
public void onSuccess(List<Device> devices) {
deviceList.addAll(devices);
if (!deviceList.isEmpty()) {
for (Device device : deviceList) {
if (device.isConnected()) {
connectedDevice = device;
}
}
}
if (connectedDevice != null) {
checkAppInstalledInWatch(connectedDevice);
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Process logic when the device list fails to be obtained
}
});
}
private void checkAppInstalledInWatch(final Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
if (connectedDevice != null && connectedDevice.isConnected()) {
p2pClient.ping(connectedDevice, new PingCallback() {
@Override
public void onPingResult(int errCode) {
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void successVoid) {
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
}
});
}
}
private void sendMessageToWatch(String message, Device connectedDevice) {
P2pClient p2pClient = HiWear.getP2pClient(this);
String peerPkgName = "com.wearengine.huawei";
p2pClient.setPeerPkgName(peerPkgName);
String peerFingerPrint = "com.wearengine.huawei_BALgPWTbV2CKZ9swMfG1n9ReRlQFqiZrEG*******";
p2pClient.setPeerFingerPrint(peerFingerPrint);
Message.Builder builder = new Message.Builder();
builder.setPayload(message.getBytes(StandardCharsets.UTF_8));
Message sendMessage = builder.build();
SendCallback sendCallback = new SendCallback() {
@Override
public void onSendResult(int resultCode) {
}
@Override
public void onSendProgress(long progress) {
}
};
if (connectedDevice != null && connectedDevice.isConnected() && sendMessage != null && sendCallback != null) {
p2pClient.send(connectedDevice, sendMessage, sendCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//Related processing logic for your app after the send command runs
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//Related processing logic for your app after the send command fails to run
}
});
}
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btLogin) {
if (etPin.getText().toString().equals("1234")) {
sendMessageToWatch("Success", connectedDevice);
} else {
sendMessageToWatch("Wrong password", connectedDevice);
}
}
}
}
Watch side
Step 1: Create a Lite Wearable project on DevEco studio.
Step 2: Generate the required certificates to run the application. Please refer to this article https://forums.developer.huawei.com/forumPortal/en/topic/0202465210302250053
Step 3: Download and Add the Wear Engine library in the pages folder of the Harmony project. https://developer.huawei.com/consum...ity-Library/litewearable-sdk-0000001053562589
Step 4: Design the UI.
Index.hml
HTML:
<div class="container">
<text class="title">
{{title}}
</text>
</div>
Index.css
CSS:
.container {
display: flex;
justify-content: center;
align-items: center;
left: 0px;
top: 0px;
width: 454px;
height: 454px;
background-color: cadetblue;
}
.title {
font-size: 90px;
text-align: center;
width: 300px;
height: 150px;
}
Step 5: Open index.js file and import the wearengine SDK.
JavaScript:
import {P2pClient, Message, Builder} from '../wearengine';
Step 6: Add the receiver code snippet on index.js.
JavaScript:
onInit() {
var _that = this;
_that.setBrightnessKeepScreenOn();
//Step 1: Obtain the point-to-point communication object
var p2pClient = new P2pClient();
var peerPkgName = "com.phone.wearengine";
var peerFinger = "79C3B257672C32974283E712EF7FEC******";
//Step 2: Set your app package name that needs communications on the phone
p2pClient.setPeerPkgName(peerPkgName);
//Step 3: Set the fingerprint information of the app on the phone. (This API is unavailable currently. In this version, you need to set fingerprint mode in the config.json file in Step 5.)
p2pClient.setPeerFingerPrint(peerFinger);
//Step 4: Receive short messages or files from your app on the phone
//Define the receiver
var flash = this;
var receiver = {
onSuccess: function () {
console.info("Recieved message");
//Process the callback function returned when messages or files fail to be received from the phone during registration.
flash.receiveMessageOK = "Succeeded in receiving the message";
},
onFailure: function () {
console.info("Failed message");
//Registering a listener for the callback method of failing to receive messages or files from phone
flash.receiveMessageOK = "Failed to receive the message";
},
onReceiveMessage: function (data) {
if (data && data.isFileType) {
//Process the file sent by your app on the phone
flash.receiveMessgeOK = "file:" + data.name;
} else {
console.info("Got message - " + data);
//Process the message sent from your app on the phone.
flash.receiveMessageOK = "message:" + data;
_that.title = "" + data;
if (data != "Success") {
vibrator.vibrate({
mode: "long"
})
}
}
},
}
p2pClient.registerReceiver(receiver);
},
PeerFingerPrint on watch side is SHA-256 of Android application (Make sure you have removed the colons)
Step 7: Unregister the receiver on destroy of wearable app.
Java:
onDestroy() {
this.p2pClient.unregisterReceiver();
}
Step 8: Add metadata inside of module object of config.json.
JSON:
"metaData": {
"customizeData": [
{
"name": "supportLists",
"value": "com.phone.wearengine:79C3B257672C32974283E756535C86728BE4DF51E*******",
"extra": ""
}
]
}
The final code for your android application given below.
JavaScript:
import {P2pClient, Message, Builder} from '../wearengine';
import brightness from '@system.brightness';
import vibrator from '@system.vibrator';
export default {
data: {
title: 'Enter pin'
},
onInit() {
var _that = this;
_that.setBrightnessKeepScreenOn();
//Step 1: Obtain the point-to-point communication object
var p2pClient = new P2pClient();
var peerPkgName = "com.phone.wearengine";
var peerFinger = "79C3B257672C32974283E756535C*****************";
//Step 2: Set your app package name that needs communications on the phone
p2pClient.setPeerPkgName(peerPkgName);
//Step 3: Set the fingerprint information of the app on the phone. (This API is unavailable currently. In this version, you need to set fingerprint mode in the config.json file in Step 5.)
p2pClient.setPeerFingerPrint(peerFinger);
//Step 4: Receive short messages or files from your app on the phone
//Define the receiver
var flash = this;
var receiver = {
onSuccess: function () {
console.info("Recieved message");
//Process the callback function returned when messages or files fail to be received from the phone during registration.
flash.receiveMessageOK = "Succeeded in receiving the message";
},
onFailure: function () {
console.info("Failed message");
//Registering a listener for the callback method of failing to receive messages or files from phone
flash.receiveMessageOK = "Failed to receive the message";
},
onReceiveMessage: function (data) {
if (data && data.isFileType) {
//Process the file sent by your app on the phone
flash.receiveMessgeOK = "file:" + data.name;
} else {
console.info("Got message - " + data);
//Process the message sent from your app on the phone.
flash.receiveMessageOK = "message:" + data;
_that.title = "" + data;
if (data != "Success") {
vibrator.vibrate({
mode: "long"
})
}
}
},
}
p2pClient.registerReceiver(receiver);
},
setBrightnessKeepScreenOn: function () {
brightness.setKeepScreenOn({
keepScreenOn: true,
success: function () {
console.log("handling set keep screen on success")
},
fail: function (data, code) {
console.log("handling set keep screen on fail, code:" + code);
}
});
},
onDestroy() {
// FeatureAbility.unsubscribeMsg();
this.p2pClient.unregisterReceiver();
}
}
Results
Tips & Tricks
Make sure you are generated the SHA - 256 fingerprint of proper keystore.
Follow the P2P generation steps properly.
Conclusion
In this article, we are learned how to develop a security app using Wear Engine. The wear engine will allow us to communicate between the Android application and the Harmony Wear application.
Reference
Harmony Official document - https://developer.harmonyos.com/en/docs/documentation/doc-guides/harmonyos-overview-0000000000011903
Wear Engine documentation - https://developer.huawei.com/consumer/en/doc/development/connectivity-Guides/service-introduction-0000001050978399
Certificate generation article - https://forums.developer.huawei.com/forumPortal/en/topic/0202465210302250053
P2P generation article - https://forums.developer.huawei.com/forumPortal/en/topic/0202466737940270075
Click to expand...
Click to collapse

Integration of ML Kit in Android KnowMyBoard App using Navigation Components, MVVM, Data Binding

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
In this article, we will learn how to integrate Huawei ML kit, Account kit and Location kit in Android application KnowMyBoard. Account Kit provides seamless login functionality to the app with large user base.
ML Kit provides app to easily leverage Huawei’s long-term proven expertise in machine learning to support diverse artificial intelligence (AI) applications throughout a wide range of industries.
ML kit provides various services, in this application we will be integrating its text related service like text recognition, text detection and text translation services, which helps in achieve the gaol of the application.
Location kit SDK for Android offers location-related APIs for Android apps. These APIs mainly relate to 6 functions like fused location, activity identification, geofence, high-precision location, indoor location, and geocoding. This mode is applicable to mobile phones and Huawei tablets. We are using Location kit to get location of user.
Supported Devices
Supported Countries/Regions
Supported Countries/Regions
Development Overview
You need to install Android Studio IDE and I assume that you have prior knowledge of Android application development.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.8 or later.
Android Studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later
Integration steps
Step 1. Huawei developer account and complete identity verification in Huawei developer website, refer to register Huawei ID.
Step 2. Create project in AppGallery Connect
Step 3. Adding HMS Core SDK
Let’s start coding
MainActivity.java
public class MainActivity extends AppCompatActivity {
LoginViewModel loginViewModel;
private MLTextAnalyzer mTextAnalyzer;
public Uri imagePath;
Bitmap bitmap;
ArrayList<String> result = new ArrayList<>();
MLLocalLangDetector myLocalLangDetector;
MLLocalTranslator myLocalTranslator;
String textRecognized;
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loginViewModel = new ViewModelProvider(this).get(LoginViewModel.class);
MyApplication.setActivity(this);
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// Process the authorization result to obtain the authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 8888) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
AuthAccount authAccount = authAccountTask.getResult();
UserData userData = new UserData();
userData.setAccessToken(authAccount.getAccessToken());
userData.setCountryCode(authAccount.getCountryCode());
userData.setDisplayName(authAccount.getDisplayName());
userData.setEmail(authAccount.getEmail());
userData.setFamilyName(authAccount.getFamilyName());
userData.setGivenName(authAccount.getGivenName());
userData.setIdToken(authAccount.getIdToken());
userData.setOpenId(authAccount.getOpenId());
userData.setUid(authAccount.getUid());
userData.setPhotoUriString(authAccount.getAvatarUri().toString());
userData.setUnionId(authAccount.getUnionId());
Gson gson = new Gson();
Log.e("TAG", "sign in success : " + gson.toJson(authAccount));
loginViewModel = new ViewModelProvider(MainActivity.this).get(LoginViewModel.class);
loginViewModel.sendData(authAccount.getDisplayName());
progressDialog.dismiss();
} else {
// The sign-in failed.
Log.e("TAG", "sign in failed:" + ((ApiException) authAccountTask.getException()).getStatusCode());
progressDialog.dismiss();
}
}
if (requestCode == 2323 && resultCode == RESULT_OK && data != null) {
progressDialog.setMessage("Initializing text detection..");
progressDialog.show();
imagePath = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imagePath);
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", " BITMAP ERROR");
}
Log.d("TAG", "Path " + imagePath.getPath());
try {
Bitmap selectedBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imagePath);
asyncAnalyzeText(selectedBitmap);
} catch (IOException e) {
e.printStackTrace();
progressDialog.dismiss();
}
}
}
private void asyncAnalyzeText(Bitmap bitmap) {
if (mTextAnalyzer == null) {
createMLTextAnalyzer();
}
MLFrame frame = MLFrame.fromBitmap(bitmap);
Task<MLText> task = mTextAnalyzer.asyncAnalyseFrame(frame);
task.addOnSuccessListener(new OnSuccessListener<MLText>() {
@Override
public void onSuccess(MLText text) {
progressDialog.setMessage("Initializing language detection..");
Log.d("TAG", "#" + text.getStringValue());
textRecognized = text.getStringValue().trim();
if(!textRecognized.isEmpty()){
// Create a local language detector.
MLLangDetectorFactory factory = MLLangDetectorFactory.getInstance();
MLLocalLangDetectorSetting setting = new MLLocalLangDetectorSetting.Factory()
// Set the minimum confidence threshold for language detection.
.setTrustedThreshold(0.01f)
.create();
myLocalLangDetector = factory.getLocalLangDetector(setting);
Task<String> firstBestDetectTask = myLocalLangDetector.firstBestDetect(textRecognized);
firstBestDetectTask.addOnSuccessListener(new OnSuccessListener<String>() {
@Override
public void onSuccess(String languageDetected) {
progressDialog.setMessage("Initializing text translation..");
// Processing logic for detection success.
Log.d("TAG", "Lang detect :" + languageDetected);
textTranslate(languageDetected, textRecognized, bitmap);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Processing logic for detection failure.
Log.e("TAG", "Lang detect error:" + e.getMessage());
}
});
}else{
progressDialog.dismiss();
showErrorDialog("Failed to recognize text.");
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e("TAG", "Error " + e.getMessage());
}
});
}
private void showErrorDialog(String msg) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Error");
alertDialog.setMessage(msg);
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
private void textTranslate(String languageDetected, String textRecognized, Bitmap uri) {
MLApplication.initialize(getApplication());
MLApplication.getInstance().setApiKey("fDkimdjcdjjssshwQ==");
// Create an offline translator.
MLLocalTranslateSetting setting = new MLLocalTranslateSetting.Factory()
// Set the source language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setSourceLangCode(languageDetected)
// Set the target language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setTargetLangCode("en")
.create();
myLocalTranslator = MLTranslatorFactory.getInstance().getLocalTranslator(setting);
// Set the model download policy.
MLModelDownloadStrategy downloadStrategy = new MLModelDownloadStrategy.Factory()
.needWifi()// It is recommended that you download the package in a Wi-Fi environment.
.create();
// Create a download progress listener.
MLModelDownloadListener modelDownloadListener = new MLModelDownloadListener() {
@Override
public void onProcess(long alreadyDownLength, long totalLength) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Display the download progress or perform other operations.
}
});
}
};
myLocalTranslator.preparedModel(downloadStrategy, modelDownloadListener).
addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Called when the model package is successfully downloaded.
// input is a string of less than 5000 characters.
final Task<String> task = myLocalTranslator.asyncTranslate(textRecognized);
// Before translation, ensure that the models have been successfully downloaded.
task.addOnSuccessListener(new OnSuccessListener<String>() {
@Override
public void onSuccess(String translated) {
// Processing logic for detection success.
result.clear();
result.add(languageDetected.trim());
result.add(textRecognized.trim());
result.add(translated.trim());
loginViewModel.setImage(uri);
loginViewModel.setTextRecongnized(result);
progressDialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Processing logic for detection failure.
progressDialog.dismiss();
}
});
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Called when the model package fails to be downloaded.
progressDialog.dismiss();
}
});
}
private void createMLTextAnalyzer() {
MLLocalTextSetting setting = new MLLocalTextSetting.Factory()
.setOCRMode(MLLocalTextSetting.OCR_DETECT_MODE)
.create();
mTextAnalyzer = MLAnalyzerFactory.getInstance().getLocalTextAnalyzer(setting);
}
@Override
protected void onStop() {
if (myLocalLangDetector != null) {
myLocalLangDetector.stop();
}
if (myLocalTranslator!= null) {
myLocalTranslator.stop();
}
if(progressDialog!= null){
progressDialog.dismiss();
}
super.onStop();
}
}
LoginViewModel.java
public class LoginViewModel extends AndroidViewModel {
AccountAuthService service;
private MutableLiveData<String> message = new MutableLiveData<>();
private MutableLiveData<ArrayList<String>> textRecongnized = new MutableLiveData<>();
private MutableLiveData<Bitmap> image = new MutableLiveData<>();
private MutableLiveData<LocationResult> locationResult = new MutableLiveData<>();
public void sendData(String msg) {
message.setValue(msg);
}
public LiveData<String> getMessage() {
return message;
}
public MutableLiveData<ArrayList<String>> getTextRecongnized() {
return textRecongnized;
}
public void setImage(Bitmap imagePath) {
this.image.setValue(imagePath);
}
public MutableLiveData<LocationResult> getLocationResult() {
return locationResult;
}
public void setLocationResult(LocationResult locationResult) {
this.locationResult.setValue(locationResult);
}
public void setTextRecongnized(ArrayList<String> textRecongnized) {
this.textRecongnized.setValue(textRecongnized);
}
public MutableLiveData<Bitmap> getImagePath() {
return image;
}
public LoginViewModel(@NonNull Application application) {
super(application);
}
public void logoutHuaweiID() {
if (service != null) {
service.signOut();
sendData("KnowMyBoard");
Toast.makeText(getApplication(), "You are logged out from Huawei ID", Toast.LENGTH_LONG).show();
}
}
public void loginClicked(View view) {
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams();
service = AccountAuthManager.getService(MyApplication.getActivity(), authParams);
MyApplication.getActivity().startActivityForResult(service.getSignInIntent(), 8888);
}
public void cancelAuthorization() {
if (service != null) {
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service.cancelAuthorization().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// Processing after a successful authorization cancellation.
Log.i("TAG", "onSuccess: ");
sendData("KnowMyBoard");
Toast.makeText(getApplication(), "Cancelled authorization", Toast.LENGTH_LONG).show();
} else {
// Handle the exception.
Exception exception = task.getException();
if (exception instanceof ApiException) {
int statusCode = ((ApiException) exception).getStatusCode();
Log.i("TAG", "onFailure: " + statusCode);
Toast.makeText(getApplication(), "Failed to cancel authorization", Toast.LENGTH_LONG).show();
}
}
}
});
} else {
Toast.makeText(getApplication(), "Login required", Toast.LENGTH_LONG).show();
}
}
}
[B][B]
RequestLocationData.java
apublic class RequestLocationData {
static String TAG = "TAG";
SettingsClient settingsClient;
private int isLocationSettingSuccess = 0;
private LocationRequest myLocationRequest;
// Define a fusedLocationProviderClient object.
private FusedLocationProviderClient fusedLocationProviderClient;
LocationCallback myLocationCallback;
Context context;
Activity activity;
LocationResult locationResult;
LoginViewModel loginViewModel;
public RequestLocationData(Context context, FragmentActivity activity, LoginViewModel loginViewModel) {
setContext(context);
setActivity(activity);
setLoginViewModel(loginViewModel);
}
public LoginViewModel getLoginViewModel() {
return loginViewModel;
}
public void setLoginViewModel(LoginViewModel loginViewModel) {
this.loginViewModel = loginViewModel;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public Activity getActivity() {
return activity;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
public void initFusionLocationProviderClint(){
// Instantiate the fusedLocationProviderClient object.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());
settingsClient = LocationServices.getSettingsClient(getActivity());
}
public void checkDeviceLocationSettings() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
myLocationRequest = new LocationRequest();
builder.addLocationRequest(myLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check the device location settings.
settingsClient.checkLocationSettings(locationSettingsRequest)
// Define the listener for success in calling the API for checking device location settings.
.addOnSuccessListener(locationSettingsResponse -> {
LocationSettingsStates locationSettingsStates =
locationSettingsResponse.getLocationSettingsStates();
StringBuilder stringBuilder = new StringBuilder();
// Check whether the location function is enabled.
stringBuilder.append(",\nisLocationUsable=")
.append(locationSettingsStates.isLocationUsable());
// Check whether HMS Core (APK) is available.
stringBuilder.append(",\nisHMSLocationUsable=")
.append(locationSettingsStates.isHMSLocationUsable());
Log.i(TAG, "checkLocationSetting onComplete:" + stringBuilder.toString());
// Set the location type.
myLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the number of location updates to 1.
myLocationRequest.setNumUpdates(1);
isLocationSettingSuccess = 1;
})
// Define callback for failure in checking the device location settings.
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.i(TAG, "checkLocationSetting onFailure:" + e.getMessage());
}
});
}
public void checkPermission() {
// Dynamically apply for required permissions if the API level is 28 or lower.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "android sdk <= 28 Q");
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings =
{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.MANAGE_MEDIA,Manifest.permission.MEDIA_CONTENT_CONTROL,Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
ActivityCompat.requestPermissions(getActivity(), strings, 1);
}
} else {
// Dynamically apply for the android.permission.ACCESS_BACKGROUND_LOCATION permission in addition to the preceding permissions if the API level is higher than 28.
if (ActivityCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getContext(),
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.MEDIA_CONTENT_CONTROL,Manifest.permission.MANAGE_MEDIA,
"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(getActivity(), strings, 2);
}
}
}
public LocationResult refreshLocation() {
if (isLocationSettingSuccess == 1) {
myLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
getLoginViewModel().setLocationResult(locationResult);
}
}
};
fusedLocationProviderClient.requestLocationUpdates(myLocationRequest, myLocationCallback, Looper.getMainLooper());
} else {
Log.d(TAG, "Failed to get location settings");
}
return locationResult;
}
public void disableLocationData(){
fusedLocationProviderClient.disableBackgroundLocation();
fusedLocationProviderClient.removeLocationUpdates(myLocationCallback);
}
}
navigation_graph.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/navigation_graph"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/loginFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.LoginFragment"
android:label="LoginFragment">
<action
android:id="@+id/action_loginFragment_to_mainFragment"
app:destination="@id/mainFragment" />
</fragment>
<fragment
android:id="@+id/mainFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.MainFragment"
android:label="MainFragment">
<action
android:id="@+id/action_mainFragment_to_loginFragment"
app:destination="@id/loginFragment" />
</fragment>
</navigation>
LoginFragment.java
public class LoginFragment extends Fragment {
FragmentLoginBinding loginBinding;
LoginViewModel loginViewModel;
Menu menu;
SharedPreferences prefs;
SharedPreferences.Editor editor;
NavController navController;
private String MY_PREF_NAME = "my_pref_name";
private String TAG = "TAG";
public LoginFragment() {
// Required empty public constructor
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
navController = Navigation.findNavController(view);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
loginBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false);
loginViewModel = new ViewModelProvider(getActivity()).get(LoginViewModel.class);
loginBinding.setLoginViewModel(loginViewModel);
Log.d(TAG, " Pref " + getPreferenceValue());
if (getPreferenceValue().equals("user_name")) {
loginBinding.btnHuaweiIdAuth.setVisibility(View.VISIBLE);
} else {
enableMenu(menu);
getActivity().setTitle(getPreferenceValue());
loginBinding.btnHuaweiIdAuth.setVisibility(View.GONE);
}
loginBinding.imageLogo.setOnClickListener(v -> {
navController.navigate(R.id.action_loginFragment_to_mainFragment);
});
loginViewModel.getMessage().observeForever(new Observer<String>() {
@Override
public void onChanged(String message) {
updateMessage(message);
if (!message.equals(getResources().getString(R.string.app_name))) {
setPreferenceValue(message);
enableMenu(menu);
loginBinding.btnHuaweiIdAuth.setVisibility(View.GONE);
} else {
disableMenu(menu);
loginBinding.btnHuaweiIdAuth.setVisibility(View.VISIBLE);
setPreferenceValue("user_name");
}
}
});
return loginBinding.getRoot();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
menu.clear();
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.main, menu);
this.menu = menu;
disableMenu(menu);
}
private void disableMenu(Menu menu) {
try {
if (menu != null) {
if (getPreferenceValue().equals("user_name")) {
menu.findItem(R.id.menu_login_logout).setVisible(false);
menu.findItem(R.id.menu_cancel_auth).setVisible(false);
getActivity().setTitle(getResources().getString(R.string.app_name));
} else {
menu.findItem(R.id.menu_login_logout).setVisible(true);
menu.findItem(R.id.menu_cancel_auth).setVisible(true);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void enableMenu(Menu menu) {
try {
menu.findItem(R.id.menu_login_logout).setVisible(true);
menu.findItem(R.id.menu_cancel_auth).setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressLint("NonConstantResourceId")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_cancel_auth:
setPreferenceValue("user_name");
loginViewModel.cancelAuthorization();
loginBinding.btnHuaweiIdAuth.setVisibility(View.VISIBLE);
disableMenu(menu);
return true;
case R.id.menu_login_logout:
setPreferenceValue("user_name");
loginViewModel.logoutHuaweiID();
loginBinding.btnHuaweiIdAuth.setVisibility(View.VISIBLE);
disableMenu(menu);
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
public void updateMessage(String msg) {
getActivity().setTitle(msg);
}
void setPreferenceValue(String userName) {
editor = getActivity().getSharedPreferences(MY_PREF_NAME, MODE_PRIVATE).edit();
editor.putString("user_name", userName);
editor.apply();
}
String getPreferenceValue() {
prefs = getActivity().getSharedPreferences(MY_PREF_NAME, MODE_PRIVATE);
return prefs.getString("user_name", "user_name");
}
}
MainFragment.java
public class MainFragment extends Fragment {
static String TAG = "TAG";
FragmentMainFragmentBinding binding;
LoginViewModel loginViewModel;
RequestLocationData locationData;
public MainFragment() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main_fragment, container, false);
loginViewModel = new ViewModelProvider(getActivity()).get(LoginViewModel.class);
binding.setLoginViewModel(loginViewModel);
locationData = new RequestLocationData(getContext(),getActivity(),loginViewModel);
locationData.initFusionLocationProviderClint();
locationData.checkPermission();
locationData.checkDeviceLocationSettings();
binding.buttonScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
chooseImage();
}
});
loginViewModel.getImagePath().observeForever(new Observer<Bitmap>() {
@Override
public void onChanged(Bitmap bitmap) {
try{
binding.imageView.setImageBitmap(bitmap);
}catch (Exception e){
e.printStackTrace();
Log.e("TAG","Error : "+e.getMessage());
}
}
});
loginViewModel.getTextRecongnized().observeForever(new Observer<ArrayList<String>>() {
@Override
public void onChanged(ArrayList<String> res) {
Log.i("TAG","OBSERVER : "+"Language : "+getStringResourceByName(res.get(0).trim())+
" Detected text : "+res.get(1).trim()+
" Translated text : "+res.get(2).trim());
binding.textLanguage.setText("Language : "+getStringResourceByName(res.get(0)));
binding.textDetected.setText("Detected text : "+res.get(1));
binding.textTranslated.setText("Translated text : "+res.get(2));
}
});
loginViewModel.getLocationResult().observeForever(new Observer<LocationResult>() {
@Override
public void onChanged(LocationResult locationResult) {
binding.textDetected.setText("Latitude " + locationResult.getLastHWLocation().getLatitude() + " Longitude " + locationResult.getLastHWLocation().getLongitude());
}
});
return binding.getRoot();
}
private String getStringResourceByName(String aString) {
String packageName = getActivity().getPackageName();
int resId = getResources()
.getIdentifier(aString, "string", packageName);
if (resId == 0) {
return aString;
} else {
return getString(resId);
}
}
private void chooseImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
getActivity().startActivityForResult(intent, 2323);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
menu.clear();
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.main_fragment_menu, menu);
}
@SuppressLint("NonConstantResourceId")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.option_refresh_location:
//refreshLocation();
locationData.refreshLocation();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onStop() {
super.onStop();
locationData.disableLocationData();
}
}
Result
Tricks and Tips
Makes sure that agconnect-services.json file added.
Make sure required dependencies are added
Make sure that service is enabled in AGC
Images has clear visibility of text
Enable data binding in gradle.build file
Conclusion
In this article, we have learnt how to integrate Huawei Account kit, Location kit and ML kit in Android application KnowMyBoard. You can also go through previous article part-1 here. Hoping that the ML kit capabilities are helpful to you as well, like this sample, you can make use of ML kit to recognition of text and detection of language and translation of text, likewise you can make use of ML kit in tourism app which helps app users to understand different sign boards and get rid of the language barrier.
Thank you so much for reading. I hope this article helps you to understand the integration of Huawei ML kit, Account kit and Location kit in Android application KnowMyBoard.
Reference
ML Kit – Training video
Location Kit – Training video
Checkout in forum

Categories

Resources