{
"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"
}
In this article, we will develop an app for Huawei + Non-Huawei Android phones using Huawei Map Kit and Site Kit Widget. As you know previously Huawei Map could only be used in an HMS device but after the Map update version 5.1.0.300 (2020-12-31) Map Kit can be used on non-Huawei Android phones and in other scenarios where HMS Core (APK) is not required. Meanwhile, to use HMS Core in non-Huawei Android phones we will install the HMS Core App programmatically.
Huawei Map Kit:
Huawei Map kit allows can easily integrate map-based functions into your apps and make location-based services work better for you.
Huawei Site Kit:
Directing users to the location-based service they need makes your app accessible to more people. Give your users the power to explore their world.
Pre-Requisites
1. Integrate HMS Core in project.
2. Enable Scan and Map Kit from AGC Console.
3. Add agconnet-service.json file in the app level directory.
1. Add Dependencies & Permission:
1.1: Add the following dependencies in the app level build.gradle file:
Code:
dependencies {
//Map
implementation 'com.huawei.hms:maps:5.2.0.301'
//Map callback dependencies for using Huawei Map on Non-Huawei Devices
implementation 'com.huawei.hms:maproute-fallback:5.2.0.301'
implementation 'com.huawei.hms:hwmaps-fallback:5.2.0.301'
//Site
implementation 'com.huawei.hms:site:5.2.0.300'
}
1.2: Add the following permissions in the AndroidManifest.xml:
Code:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
// To programmatically allow user to install HMS Core App
<meta-data
android:name="com.huawei.hms.client.channel.androidMarket"
android:value="false" />
2. Add Layout Files:
2.1: Add the activity_map.xml layout file in the layout folder of the res. This is the layout view of the MapActivity in the application, which contains the Site Kit Widget and a Mapview.
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--Site Kit Widget-->
<fragment
android:id="@+id/widget_fragment"
android:name="com.huawei.hms.site.widget.SearchFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--Map Kit -->
<com.huawei.hms.maps.MapView
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:mapType="normal"
map:uiCompass="true"
map:uiZoomControls="true"/>
</LinearLayout>
3. Add Classes
3.1: Add the MapActivity.java file in the App. This class extends AppCompayActivity and implements OnMapReadyCallback. Meanwhile, Site Fragment is added.
Code:
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String TAG = "MapViewDemoActivity";
private static final String MAPVIEW_BUNDLE_KEY = "MapViewBundleKey";
private static final int REQUEST_CODE = 100;
private static final LatLng LAT_LNG = new LatLng(31.5204, 74.3587);
private HuaweiMap hmap;
private MapView mMapView;
private static final String[] RUNTIME_PERMISSIONS = {Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET};
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "map onCreate:");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
//Check for required Permissions
if (!hasPermissions(this, RUNTIME_PERMISSIONS)) {
ActivityCompat.requestPermissions(this, RUNTIME_PERMISSIONS, REQUEST_CODE);
}
mMapView = findViewById(R.id.mapView);
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY);
}
AGConnectServicesConfig config = AGConnectServicesConfig.fromContext(this);
MapsInitializer.setApiKey(config.getString("client/api_key"));
mMapView.onCreate(mapViewBundle);
mMapView.getMapAsync(this);
SearchFragment fragment = (SearchFragment) getSupportFragmentManager().findFragmentById(R.id.widget_fragment);
try {
fragment.setApiKey(URLEncoder.encode(config.getString("client/api_key"), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
fragment.setOnSiteSelectedListener(new SiteSelectionListener() {
@Override
public void onSiteSelected(Site data) {
if (hmap != null) {
hmap.clear();
MarkerOptions markerOptions = new MarkerOptions()
.position(new LatLng(data.getLocation().getLat(), data.getLocation().getLng()))
.title(data.getName()).snippet(data.getFormatAddress());
hmap.addMarker(markerOptions);
hmap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(data.getLocation().getLat(), data.getLocation().getLng()), 11));
}
}
@Override
public void onError(SearchStatus status) {
Toast.makeText(getApplication(), status.getErrorCode() + "\n" + status.getErrorMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
@Override
protected void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
protected void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onMapReady(HuaweiMap map) {
Log.d(TAG, "onMapReady: ");
hmap = map;
hmap.setMyLocationEnabled(true);
// move camera by CameraPosition param ,latlag and zoom params can set here
CameraPosition build = new CameraPosition.Builder().target(LAT_LNG).zoom(11).build();
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(build);
hmap.animateCamera(cameraUpdate);
}
@Override
protected void onPause() {
mMapView.onPause();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
private static boolean hasPermissions(Context context, String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
}
4. Application Logic:
When the app is used in an HMS phone, the Map will be loaded and the Site Kit Widget will be used to search for the places and a marker will be added to the Map. Meanwhile, when the App will be used in a Non-Huawei Android phone, the Map will work fine as two of the callback dependencies have been added in the gradle file but Site Kit widget will not work therefore an HMS Core installation popup is displayed for the user to install the HMS Core App in the phone to enable the required Huawei Mobile Services.
** For Huawei Map, HMS Core App is not required in the Non-Huawei phone (Huawei Map User location doesn't work on Non-Huawei Device).
** For Site Kit Widget, HMS Core App is required in the Non-Huawei phone.
5: Run the Application:
Once all code has been added to the project, you can run the application on any Huawei or Non-Huawei android phone.
6: Demo:
7: Tips and Tricks:
1. hmap.setMyLocationEnabled(true); doesn't work in non-Huawei Android phone therefore respective Location services will be used to get the user's current location on Map.
2. Check for the permission on runtime to load the Map.
3. Map on non-Huawei Android phone will work in Map version 5.1.0.300 and onwards.
4. Encode the API Key before setting it for Site widget Fragment using URLEncoder.encode(config.getString("client/api_key"), "UTF-8")
8: Conclusion:
Huawei Map use on Non-Huawei Android phones will reduce the support cost, development efforts, and maintenance of using two different Map services for Huawei/Non-Huawei devices.
9: References:
9.1: Map Kit: click here
9.2: Site Kit: click here
Original Source
Related
More information like this, you can visit HUAWEI Developer Forum
Introduction
Huawei Flight booking application is to explore HMS kits in real time scenario. This app can be used as reference to CP during HMS integration.
Prerequisite
1) You must have Huawei developer account.
2) Huawei phone with HMS 4.0.0.300 or later
3) Android Studio, JDK 1.8, SDK platform 26 and Gradle 4.6 installed.
Permissions
Provide following permissions in manifest.
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
User Sign in
HUAWEI Account Kit offers easy, stable and fast login, and authorization functions to developers. Instead of entering accounts and passwords, you can simply tap the sign-in button with HUAWEI ID to log in your application easily and safely.
Setup:
1) Create a project in android studio.
2) Get the SHA-256 Key.
3) Create an app in the Huawei app gallery connect.
4) Enable account kit setting in Manage APIs Section.
5) Provide the SHA-256 Key in App Information Section.
6) Provide storage location.
7) Enable Huawei account under Auth Service in AGC.
{
"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"
}
8) After completing all the above points we need to download the agconnect-services.json from App Information Section. Place the json file in the app folder of the android project.
9) Enter the below maven URL inside the repositories of buildscript and allprojects respectively (project build.gradle file).
Code:
maven { url 'http://developer.huawei.com/repo/' }
10) Enter the below plugin in the app build.gradle file.
Code:
apply plugin: 'com.huawei.agconnect'
dependencies {
implementation 'com.huawei.hms:hwid:4.0.0.300'
11) Now Sync the gradle.
Implementation
1) In this app, we can implement Authorization code method.
Code:
HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams();
huaweiservice = HuaweiIdAuthManager.getService(MainActivity.this, authParams);
startActivityForResult(huaweiservice.getSignInIntent(), HUAWEI_SIGNIN);
2) To Process the sign-in result after the authorization is complete.
Code:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == HUAWEI_SIGNIN) {
com.huawei.hmf.tasks.Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
if (authHuaweiIdTask.isSuccessful()) {
//The sign-in is successful, and the user's HUAWEI ID information and authorization code are obtained.
AuthHuaweiId huaweiAccount = authHuaweiIdTask.getResult();
Log.i(TAG, "Authorization code:" + huaweiAccount.getAuthorizationCode());
Log.d(TAG, "name: " + huaweiAccount.getDisplayName());
Log.d(TAG, "email: " + huaweiAccount.getEmail());
Log.d(TAG , "avatar : "+huaweiAccount.getAvatarUriString());
launchLoggedinActivity(huaweiAccount.getFamilyName() , huaweiAccount.getGivenName() , huaweiAccount.getAvatarUriString(),"huawei");
} else {
// The sign-in failed.
Log.e(TAG, "sign in failed : " + ((com.huawei.hms.common.ApiException) authHuaweiIdTask.getException()).getStatusCode());
}
}
}
3) To handle silent Sign-in
The authorization is required only for first registration with the HUAWEI ID. Then no approval is required for subsequent registrations with the same HUAWEI ID.
Code:
private void handleHuaweiSilentSignIn() {
HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).createParams();
HuaweiIdAuthService service = HuaweiIdAuthManager.getService(MainActivity.this, authParams);
com.huawei.hmf.tasks.Task<AuthHuaweiId> task = service.silentSignIn();
task.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
// Obtain the user's HUAWEI ID information.
Log.i(TAG, "displayName:" + authHuaweiId.getDisplayName());
launchLoggedinActivity(authHuaweiId.getFamilyName() , authHuaweiId.getGivenName() , authHuaweiId.getAvatarUriString(),"huawei");
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// The sign-in failed. Try to sign in explicitly using getSignInIntent().
if (e instanceof ApiException) {
ApiException apiException = (ApiException)e;
Log.i(TAG, "sign failed status:" + apiException.getStatusCode());
}
}
});
}
4) To sign out from Huawei account.
Code:
Task<Void> signOutTask = service.signOut();
signOutTask.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
Log.i(TAG, "signOut complete");
}
});
5) To revoke authorization
Code:
service.cancelAuthorization().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// Processing after a successful authorization revoking.
Log.i(TAG, "onSuccess: ");
} else {
// Handle the exception.
Exception exception = task.getException();
if (exception instanceof ApiException){
int statusCode = ((ApiException) exception).getStatusCode();
Log.i(TAG, "onFailure: " + statusCode);
}
}
}
Integrating Huawei Banner Ads
Ad kit service makes easy for developers to raise money with high-quality advertising from mobile devices. It maximizes the value of every impression by combining global advertiser demand, innovative ad formats, and advanced app monetization technology.
Showing ads to app users helps you to create a reliable revenue stream to help your company grow while concentrating on creating and improving quality apps. Advertisers can attract new consumers and users can discover related goods and services while enjoying free apps. So it is a win for developers, users, and advertisers.
In this app, we will integrate Huawei banner ad. It is a Rectangular advertising on the top or bottom of the screen show. When users interact with the app, banner ads remain on the screen and it can be refreshed periodically for a period of time.
Usecase
We will show banner ad at the bottom of flight search screen.
Implementation
1) Enter the below maven URL inside the repositories of buildscript and allprojects (project build.gradle file).
Code:
implementation 'com.huawei.hms:ads-lite:13.4.30.307'
2) To integrate Huawei banner ad, add BannerView in xml.
Code:
<RelativeLayout xmlns:hwads="http://schemas.android.com/apk/res-auto" >
<com.huawei.hms.ads.banner.BannerView
android:id="@+id/huawei_banner_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:visibility="gone"
hwads:adId="testw6vs28auh3"
hwads:bannerSize="BANNER_SIZE_360_57"/>
Note: We are using test ad ID. "testw6vs28auh3" is a dedicated test ad slot ID.
3) To show Banner Ad.
Code:
if(Utility.isDeviceHuaweiManufacturer() && Utility.isHuaweiMobileServicesAvailable(this)) {
hwBannerView = findViewById(R.id.huawei_banner_view);
hwBannerView.setVisibility(View.VISIBLE);
// Create an ad request to load an ad.
AdParam adParam = new AdParam.Builder().build();
hwBannerView.loadAd(adParam);
hwBannerView.setAdListener(adListener);
} private AdListener adListener = new AdListener() {
@Override
public void onAdLoaded() {
// Called when an ad is loaded successfully.
Log.d(TAG , "onAdLoaded");
}
@Override
public void onAdFailed(int errorCode) {
// Called when an ad fails to be loaded.
Log.d(TAG , "onAdFailed");
}
@Override
public void onAdOpened() {
// Called when an ad is opened.
Log.d(TAG , "onAdOpened");
}
@Override
public void onAdClicked() {
// Called when a user taps an ad.
Log.d(TAG , "onAdClicked");
}
@Override
public void onAdLeave() {
// Called when a user has left the app.
Log.d(TAG , "onAdLeave");
}
@Override
public void onAdClosed() {
// Called when an ad is closed.
Log.d(TAG , "onAdClosed");
}
};
Conclusion:
We have learnt how easy it is to integrate Huawei account and ads kit in the flight booking application.
Stay tune for next article to see more Huawei kit integration in flight booking app.
Links:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050048870
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/publisher-service-introduction-0000001050064960
does huawei mobile services provide flight booking api?
Introduction
This article is based on Multiple HMS services application. I have created Hotel Booking application using HMS Kits. We need mobile app for reservation hotels when we are traveling from one place to another place.
In this article, I am going to implement HMS Location Kit & Shared Preferences.
{
"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"
}
Flutter setup
Refer this URL to setup Flutter.
Software Requirements
1. Android Studio 3.X
2. JDK 1.8 and later
3. SDK Platform 19 and later
4. Gradle 4.6 and later
Steps to integrate service
1. We need to register as a developer account in AppGallery Connect.
2. Create an app by referring to Creating a Project and Creating an App in the Project
3. Set the data storage location based on current location.
4. Enabling Required Services: Location Kit.
5. Generating a Signing Certificate Fingerprint.
6. Configuring the Signing Certificate Fingerprint.
7. Get your agconnect-services.json file to the app root directory.
Important: While adding app, the package name you enter should be the same as your Flutter project’s package name.
Note: Before you download agconnect-services.json file, make sure the required kits are enabled.
Development Process
Create Application in Android Studio.
1. Create Flutter project.
2. App level gradle dependencies. Choose inside project Android > app > build.gradle.
Code:
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
Root level gradle dependencies
Code:
maven {url 'https://developer.huawei.com/repo/'}
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
Add the below permissions in Android Manifest file.
Code:
<manifest xlmns:android...>
...
<uses-permission android:name="android.permission.INTERNET" />
<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_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION" />
<application ...
</manifest>
3. Refer below URL for cross-platform plugins. Download required plugins.
https://developer.huawei.com/consum...y-V1/flutter-sdk-download-0000001050304074-V1
4. After completing all the steps above, you need to add the required kits’ Flutter plugins as dependencies to pubspec.yaml file. You can find all the plugins in pub.dev with the latest versions.
Code:
dependencies:
flutter:
sdk: flutter
shared_preferences: ^0.5.12+4
bottom_navy_bar: ^5.6.0
cupertino_icons: ^1.0.0
provider: ^4.3.3
huawei_location:
path: ../huawei_location/
flutter:
uses-material-design: true
assets:
- assets/images/
5. After adding them, run flutter pub get command. Now all the plugins are ready to use.
6. Open main.dart file to create UI and business logics.
Location kit
HUAWEI Location Kit assists developers in enabling their apps to get quick and accurate user locations and expand global positioning capabilities using GPS, Wi-Fi, and base station locations.
Fused location: Provides a set of simple and easy-to-use APIs for you to quickly obtain the device location based on the GPS, Wi-Fi, and base station location data.
Activity identification: Identifies user motion status through the acceleration sensor, cellular network information, and magnetometer, helping you adjust your app based on user behaviour.
Geofence: Allows you to set an interested area through an API so that your app can receive a notification when a specified action (such as leaving, entering, or lingering in the area) occurs.
Integration
Permissions
First of all we need permissions to access location and physical data.
Create a PermissionHandler instance,add initState() for initialize.
Code:
final PermissionHandler permissionHandler;
@override
void initState() {
permissionHandler = PermissionHandler(); super.initState();
}
Check Permissions
We need to check device has permission or not using hasLocationPermission() method.
Code:
void hasPermission() async {
try {
final bool status = await permissionHandler.hasLocationPermission();
if(status == true){
showToast("Has permission: $status");
}else{
requestPermission();
}
} on PlatformException catch (e) {
showToast(e.toString());
}
}
If device don’t have permission,then request for Permission to use requestLocationPermission() method.
Code:
void requestPermission() async {
try {
final bool status = await permissionHandler.requestLocationPermission();
showToast("Is permission granted");
} on PlatformException catch (e) {
showToast(e.toString());
}
}
Fused Location
Create FusedLocationPrvoiderClient instance using the init() method and use the instance to call location APIs.
Code:
final FusedLocationProviderClient locationService
@override
void initState() {
locationService = FusedLocationProviderClient(); super.initState();
}
getLastLocation()
Code:
void getLastLocation() async {
try {
Location location = await locationService.getLastLocation();
setState(() {
lastlocation = location.toString();
print("print: " + lastlocation);
});
} catch (e) {
setState(() {
print("error: " + e.toString());
});
}
}
getLastLocationWithAddress()
Create LocationRequest instance and set required parameters.
Code:
final LocationRequest locationRequest;
locationRequest = LocationRequest()
..needAddress = true
..interval = 5000;
void _getLastLocationWithAddress() async {
try {
HWLocation location =
await locationService.getLastLocationWithAddress(locationRequest);
setState(() {
String street = location.street;
String city = location.city;
String countryname = location.countryName;
currentAddress = '$street' + ',' + '$city' + ' , ' + '$countryname';
print("res: $location");
});
showToast(currentAddress);
} on PlatformException catch (e) {
showToast(e.toString());
}
}
Location Update using Call back
Create LocationCallback instance and create callback functions in initstate().
Code:
LocationCallback locationCallback;
@override
void initState() {
locationCallback = LocationCallback(
onLocationResult: _onCallbackResult,
onLocationAvailability: _onCallbackResult,
);
super.initState();
}
void requestLocationUpdatesCallback() async {
if (_callbackId == null) {
try {
final int callbackId = await locationService.requestLocationUpdatesExCb(
locationRequest, locationCallback);
_callbackId = callbackId;
} on PlatformException catch (e) {
showToast(e.toString());
}
} else {
showToast("Already requested location updates.");
}
}
void onCallbackResult(result) {
print(result.toString());
showToast(result.toString());
}
I have created Helper class to store user login information in locally using shared Preferences class.
Code:
class StorageUtil {
static StorageUtil _storageUtil;
static SharedPreferences _preferences;
static Future<StorageUtil> getInstance() async {
if (_storageUtil == null) {
var secureStorage = StorageUtil._();
await secureStorage._init();
_storageUtil = secureStorage;
}
return _storageUtil;
}
StorageUtil._();
Future _init() async {
_preferences = await SharedPreferences.getInstance();
}
// get string
static String getString(String key) {
if (_preferences == null) return null;
String result = _preferences.getString(key) ?? null;
print('result,$result');
return result;
}
// put string
static Future<void> putString(String key, String value) {
if (_preferences == null) return null;
print('result $value');
return _preferences.setString(key, value);
}
}
Result
Tips & Tricks
1. Download latest HMS Flutter plugin.
2. To work with mock location we need to add permissions in Manifest.XML.
3. Whenever you updated plugins, click on pug get.
Conclusion
We implemented simple hotel booking application using Location kit in this article. We have learned how to get Lastlocation, getLocationWithAddress and how to use callback method, in flutter how to store data into Shared Preferences in applications.
Thank you for reading and if you have enjoyed this article, I would suggest you to implement this and provide your experience.
Reference
Location Kit URL
Shared Preferences URL
Read full article
Goodjob
Thank you
I thought huawei doesn't support flutter. I guess it should as it is Android only.
good
Wow
Nice.
I thought its not doable
Interesting.
Like
{
"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
I wanted to explain Huawei Map Kit with an app so I coded a sample Android app which name is ISS Detector. Users can instantly track the location of the ISS (International Space Station) on the map via Huawei Map Kit.
The main purpose of this article is to show how to use Huawei Map Kit, marker display operations on Huawei MapView, and polyline drawing operations.
So I will not mention parts such as MVP, binding and UI.
About the data?
used open-notify API for getting location information. You can reach the relevant API page from here.
ISS Detector Code Review
The application consists of a single Activity, this Activity has the MapView component via Huawei Map Kit. Also, I used the View Binding structure because it provides ease of access to the components.
I think it will be easier if I summarize the file structure.
data: There are response classes from the API.
service: The package containing the classes required for Retrofit2.
ui.main: UI-related classes are located here. MainContract and MainPresenter classes are included in this package because I use MVP Pattern.
util: Utility classes.
Create Project & HMS Integrations
First of all, you must integrate HMS into the project. I am not going to explain these steps You can check this article.
Code:
dependencies {
.
.
// Huawei Map Kit
implementation 'com.huawei.hms:maps:5.0.0.300'
.
.
}
After adding this implementation line to build.gradle file, we can now start using Huawei Map Kit.
Code:
<manifest ...>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA"/>
...
</manifest>
We have defined the necessary permissions in the AndroidManifest file.
Code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainActivity">
<com.huawei.hms.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraZoom="1"
map:mapType="normal"
map:uiCompass="true"
map:uiZoomControls="true" />
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_margin="14dp"
app:cardCornerRadius="2dp"
app:cardElevation="4dp">
<CheckBox
android:id="@+id/checkBoxTrack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:checked="true"
android:text="Track ISS" />
</androidx.cardview.widget.CardView>
</RelativeLayout>
In activity_main.xml, the MapView component offers a full-screen map. Users can follow the ISS on the map, as well as go to the places they want freely while the ISS data continues to arrive.
Code:
public class MainActivity extends AppCompatActivity implements MainContract.View, OnMapReadyCallback {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
presenter = new MainPresenter(this);
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(Constant.MAP_BUNDLE);
}
initHuaweiMap(mapViewBundle);
}
@Override
public void onMapReady(HuaweiMap huaweiMap) {
Log.w(Constant.TAG, "onMapReady : ");
this.huaweiMap = huaweiMap;
presenter.mapReady();
}
@Override
public void initHuaweiMap(Bundle bundle) {
Log.w(Constant.TAG, "initHuaweiMap : ");
MapsInitializer.setApiKey(Constant.MAP_KEY);
binding.mapView.onCreate(bundle);
binding.mapView.getMapAsync(this);
}
...
}
We call the initHuaweiMap() function in onCreate. When the process is completed asynchronously with the binding.mapView.getMapAsync(this) line, the override onMapReady(HuaweiMap huaweiMap) function is triggered via OnMapReadyCallback, which we implement to MainActivity.
As a result of these operations, the map is now available and the presenter.mapReady() function is called.
We’ll come back to the MainActivity class later, but let’s go to explain the Presenter class.
Code:
public class MainPresenter implements MainContract.Presenter {
...
@Override
public void mapReady() {
this.getISSLocation();
...
}
@Override
public void getISSLocation() {
Call<ResponseISSLocation> call = request.getISSLocation();
call.enqueue(new Callback<ResponseISSLocation>() {
@Override
public void onResponse(Call<ResponseISSLocation> call, Response<ResponseISSLocation> response) {
if (response.isSuccessful()) {
LatLng currentLatLng = response.body().getIssPosition().getLocationAsLatLng();
Log.w(Constant.TAG, "getISSLocation : " + currentLatLng.toString());
view.setMarker(currentLatLng);
view.drawRoute(currentLatLng);
if (isChecked)
view.moveCamera(currentLatLng);
waitAndCallRequest();
}
}
@Override
public void onFailure(Call<ResponseISSLocation> call, Throwable t) {
Log.w(Constant.TAG, "getISSLocation - onFailure : " + t.getMessage());
view.showErrorMessage(t.getMessage());
}
});
}
@Override
public void waitAndCallRequest() {
Log.d(Constant.TAG, "waitAndCallRequest ");
new android.os.Handler().postDelayed(() -> getISSLocation(), 2000
);
}
}
The getISSLocation() function is calling in mapReady() for the first time for the ISS current location.
We are going to call setMarker(), drawRoute() and moveCamera() functions in the getISSLocation() function. Finally, the waitAndCallRequest() function is calling so that we can resend the same request every 2 seconds and get new location data.
Now let’s come to the setMarker(), drawRoute(), and moveCamera() functions, which is the main purpose of the article.
Code:
@Override
public void setMarker(LatLng latLng) {
Log.w(Constant.TAG, "setMarker ");
if (marker != null)
marker.remove();
MarkerOptions options = new MarkerOptions()
.position(latLng)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_iss));
marker = huaweiMap.addMarker(options);
}
In the setMarker() function, we first check the marker, if there is a marker on the map, firstly delete this marker with the marker.remove() line. Next, we create a MarkerOptions object, here we set the position of the marker with .position(), the marker icon with .icon(), and finally, we show the marker created with the huaweiMap.addMarker(options) line on the map.
Code:
@Override
public void drawRoute(LatLng latLng) {
if (huaweiMap == null) return;
if (polyline == null) {
polyline = huaweiMap.addPolyline(new PolylineOptions()
.add(latLng)
.color(getColor(R.color.colorAccent))
.width(3));
polylineList = new ArrayList<>();
polylineList.add(latLng);
} else {
polylineList.add(latLng);
polyline.setPoints(polylineList);
}
}
We have to check if the huaweiMap is null in drawRoute() function, if the polyline object is null -the application will enter the if block when it first opens because our polyline object is still null- we set the polyline object to huaweiMap with the huaweiMap.addPolyline(new PolylineOptions()) line. We set the location data with.add(), we set the polyline color with .color(), we set the polyline width .width(). Since the polyline will not consist of a single point, we create a polylineList of type ArrayList and add the location data to this list. Let’s come to the else block, we add the location here to the list and use the polyline.setPoints() function to update the route on the map.
Code:
@Override
public void moveCamera(LatLng latLng) {
Log.w(Constant.TAG, "moveCamera ");
huaweiMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, huaweiMap.getCameraPosition().zoom));
}
moveCamera() is the last function called in these steps. We send the latLng variable returned from the request and the zoom level value we get with huaweiMap.getCameraPosition().zoom to the animateCamera() function, and as a result of this line, our map moves to the new location.
Tips & Tricks
MAP_KEY value generated from AGC for Huawei Mobile Services.
Also, you can access the source codes of the application from the Github and Huawei AppGallery links below.
Conclusion
In this article, I tried to explain how to use Huawei Map Kit, marker display operations on Huawei MapView, and polyline drawing operations. I hope it was a useful article for everyone. Thank you for taking the time to read.
References
App Gallery
Source Code
Huawei Map Kit
Original Source
{
"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 Site kit, Map kit and Location kit in Android application KnowMyBoard. Account Kit provides seamless login functionality to the app with large user base.
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.
Huawei Map SDK for Android is a set of APIs that can be called to develop maps. You can use this SDK to easily add map-related functions to your Android app, including map display, map interaction, map drawing, and map style customization.
Huawei Site kit provides place search services including keyword search, nearby place search, place detail search, and place search suggestion, helping your app provide convenient place-related services to attract more users and improve user loyalty. Site kit helps developers to quickly build place-based quality apps.
Following core capabilities in Site Kit to quickly build apps users can explore the world around them.
Keyword Search: Returns a place list based on keywords entered by the user.
Nearby Place Search: Searches for nearby places based on the current location of the user's device.
Place Detail Search: Searches for details about a place.
Place Search Suggestion: Returns a list of suggested places.
Autocomplete: Returns an autocomplete place and a list of suggested places based on the entered keyword.
Supported Devices
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
navigation_graph.xml
[B]<?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"
xmlns:tools="http://schemas.android.com/tools"
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"/>
<fragment
android:id="@+id/mainFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.MainFragment"
android:label="MainFragment"/>
<fragment
android:id="@+id/cameraFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.CameraFragment"
android:label="fragment_camera"
tools:layout="@layout/fragment_camera" />
<fragment
android:id="@+id/searchFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.SearchFragment"
android:label="fragment_search"
tools:layout="@layout/fragment_search" />
</navigation>[/B]
bottom_navigation_menu.xml
[/B][/B]
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/searchFragment"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/search" />
<item
android:id="@+id/loginFragment"
android:icon="@android:drawable/ic_menu_agenda"
android:title="Home" />
<item
android:id="@+id/mainFragment"
app:showAsAction="always"
android:icon="@android:drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/cameraFragment"
android:icon="@android:drawable/ic_menu_camera"
app:showAsAction="always"
android:title="Camera" />
</menu>
[B][B]
SearchFragment.java
[/B][/B][/B]
public class SearchFragment extends Fragment {
FragmentSearchBinding binding;
LoginViewModel loginViewModel;
View view;
NavController navController;
private SearchService searchService;
SitesAdapter adapter;
ArrayList<Site> siteArrayList = new ArrayList<>();
LocationResult locationResult = null;
public SearchFragment() {
// Required empty public constructor
}
ItemClickListener siteClicklistener = new ItemClickListener(){
@Override
public void onItemClicked(RecyclerView.ViewHolder vh, Site site, int pos){
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
loginViewModel.setSiteSelected(site);
navController.navigate(R.id.loginFragment);
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
//binding = DataBindingUtil.inflate(inflater, R.layout.activity_my_search, container, false);
view = inflater.inflate(R.layout.fragment_search, container, false);
loginViewModel = new ViewModelProvider(getActivity()).get(LoginViewModel.class);
SearchView searchView = view.findViewById(R.id.ed_search);
RecyclerView recyclerView = view.findViewById(R.id.suggestion_rv);
navController = Navigation.findNavController(getActivity(), R.id.nav_host_fragment);
searchView.setFocusable(true);
searchView.onActionViewExpanded();
adapter = new SitesAdapter(siteArrayList, getContext(),siteClicklistener);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
loginViewModel.getLocationResult().observeForever(new Observer<LocationResult>() {
@Override
public void onChanged(LocationResult locationResult1) {
locationResult = locationResult1;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if(newText.length() > 4){
//keywordSearch(newText);
nearByPlacesSearch(newText);
}
return false;
}
});
return view;
}
void keywordSearch(String search){
try {
String key = URLEncoder.encode(Constants.API_KEY, "UTF-8");
// Instantiate the SearchService object.
searchService = SearchServiceFactory.create(getContext(), key);
// Create a request body.
TextSearchRequest request = new TextSearchRequest();
request.setQuery(search);
if(locationResult!=null){
Coordinate location = new Coordinate(locationResult.getLastHWLocation().getLatitude(),locationResult.getLastHWLocation().getLongitude());
request.setLocation(location);
}
request.setRadius(1000);
//request.setHwPoiType(HwLocationType.HOTEL_MOTEL);
request.setCountryCode("IN");
request.setLanguage("en");
request.setPageIndex(1);
request.setPageSize(5);
request.setChildren(false);
// request.setCountries(Arrays.asList("en", "fr", "cn", "de", "ko","in"));
// Create a search result listener.
SearchResultListener<TextSearchResponse> resultListener = new SearchResultListener<TextSearchResponse>() {
// Return search results upon a successful search.
@Override
public void onSearchResult(TextSearchResponse results) {
if (results == null || results.getTotalCount() <= 0) {
return;
}
List<Site> sites = results.getSites();
if(sites == null || sites.size() == 0){
return;
}
siteArrayList.clear();
for (Site site : sites) {
siteArrayList.add(site);
}
siteArrayList.addAll(sites);
adapter.notifyDataSetChanged();
}
// Return the result code and description upon a search exception.
@Override
public void onSearchError(SearchStatus status) {
Log.i("TAG", "Error : " + status.getErrorCode() + " " + status.getErrorMessage());
}
};
// Call the keyword search API.
searchService.textSearch(request, resultListener);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
void nearByPlacesSearch(String newText){
try{
String key = URLEncoder.encode(Constants.API_KEY, "UTF-8");
// Instantiate the SearchService object.
searchService = SearchServiceFactory.create(getContext(), key);
// Create a request body.
NearbySearchRequest request = new NearbySearchRequest();
if(locationResult!=null){
Coordinate location = new Coordinate(locationResult.getLastHWLocation().getLatitude(),locationResult.getLastHWLocation().getLongitude());
request.setLocation(location);
}
request.setQuery(newText);
request.setRadius(1000);
request.setHwPoiType(HwLocationType.ADDRESS);
request.setLanguage("en");
request.setPageIndex(1);
request.setPageSize(5);
request.setStrictBounds(false);
// Create a search result listener.
SearchResultListener<NearbySearchResponse> resultListener = new SearchResultListener<NearbySearchResponse>() {
// Return search results upon a successful search.
@Override
public void onSearchResult(NearbySearchResponse results) {
if (results == null || results.getTotalCount() <= 0) {
return;
}
List<Site> sites = results.getSites();
if(sites == null || sites.size() == 0){
return;
}
siteArrayList.clear();
for (Site site : sites) {
siteArrayList.add(site);
}
siteArrayList.addAll(sites);
adapter.notifyDataSetChanged();
}
// Return the result code and description upon a search exception.
@Override
public void onSearchError(SearchStatus status) {
Log.i("TAG", "Error : " + status.getErrorCode() + " " + status.getErrorMessage());
}
};
// Call the nearby place search API.
searchService.nearbySearch(request, resultListener);
}catch (Exception e){
e.printStackTrace();
}
}
}
[B][B][B]
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
Enable data binding in gradle.build file
Make sure bottom navigation id’s should be same as fragment id’s in navigation graph
Make sure that set apk key before calling service.
Conclusion
In this article, we have learnt how to integrate Huawei Site kit, Map kit and Location kit in Android application KnowMyBoard. You can also go through previous article part-3 here. Hoping Site kit and Map kit capabilities are helpful to you as well, like this sample, you can make use as per your requirement.
Thank you so much for reading. I hope this article helps you to understand the integration of Huawei Site kit, Map kit and Location kit in Android application KnowMyBoard.
Reference
Map Kit – Training video
Site Kit – Training video
Checkout in 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"
}
Introduction
In this article, we can learn how to search the hospitals located by source and destination address with HMS Core Kits such as Map, Site, and Location Kits. Map kit is to display maps, it covers map data of more than 200 countries and regions for searching any location address. Location kit provides to get the current location and location updates, and it provides flexible location based services globally to the users. Site kit provides with convenient and secure access to diverse, place-related services to users.
So, I will provide a series of articles on this Patient Tracking App, in upcoming articles I will integrate other Huawei Kits.
If you are new to this application, follow my previous articles.
https://forums.developer.huawei.com/forumPortal/en/topic/0201902220661040078
https://forums.developer.huawei.com/forumPortal/en/topic/0201908355251870119
https://forums.developer.huawei.com/forumPortal/en/topic/0202914346246890032
https://forums.developer.huawei.com/forumPortal/en/topic/0202920411340450018
Map Kit
Map Kit covers map data of more than 200 countries and regions, and supports over 70 languages. User can easily integrate map-based functions into your apps using SDK. It optimizes and enriches the map detail display capability. Map Kit supports gestures including zoom, rotation, moving and tilt gestures to ensure smooth interaction experience.
Location Kit
Location Kit combines the GPS, Wi-Fi and base station location functionalities in your app to build up global positioning capabilities, allows to provide flexible location-based services targeted at users around globally. Currently, it provides three main capabilities: fused location, activity identification and geo-fence. You can call one or more of these capabilities as required.
Site Kit
Site Kit provides the place related services for apps. It provides that to search places with keywords, find nearby place, place suggestion for user search, and find the place details using the unique id.
Requirements
1. Any operating system (MacOS, Linux and Windows).
2. Must have a Huawei phone with HMS 4.0.0.300 or later.
3. Must have a laptop or desktop with Android Studio, Jdk 1.8, SDK platform 26 and Gradle 4.6 and above installed.
4. Minimum API Level 24 is required.
5. Required EMUI 9.0.0 and later version devices.
How to integrate HMS Dependencies
1. First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a Huawei ID.
2. Create a project in android studio, refer Creating an Android Studio Project.
3. Generate a SHA-256 certificate fingerprint.
4. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > Tasks > android, and then click signingReport, as follows.
Note: Project Name depends on the user created name.
5. Create an App in AppGallery Connect.
6. Download the agconnect-services.json file from App information, copy and paste in android Project under app directory, as follows.
7. Enter SHA-256 certificate fingerprint and click Save button, as follows.
Note: Above steps from Step 1 to 7 is common for all Huawei Kits.
8. Click Manage APIs tab and enable Map Kit, Site Kit and Location Kit.
9. Add the below maven URL in build.gradle(Project) file under the repositories of buildscript, dependencies and allprojects, refer Add Configuration.
Java:
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
10. Add the below plugin and dependencies in build.gradle(Module) file.
Java:
apply plugin: 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// Huawei Map
implementation 'com.huawei.hms:maps:6.2.0.301'
// Huawei Site Kit
implementation 'com.huawei.hms:site:6.2.0.301'
// Huawei Location Kit
implementation 'com.huawei.hms:location:6.2.0.300'
11. Now Sync the gradle.
12. Add the required permission to the AndroidManifest.xml file.
Java:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
// To obtain the coarse longitude and latitude of a user with Wi-Fi network or base station.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
// To receive location information from satellites through the GPS chip.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Let us move to development
I have created a project on Android studio with empty activity let us start coding.
In the SearchActivity.kt we can find the business logic.
Java:
class SearchActivity : AppCompatActivity(), OnMapReadyCallback, View.OnClickListener {
private lateinit var hmap: HuaweiMap
private lateinit var mMapView: MapView
private var mMarker: Marker? = null
private var mCircle: Circle? = null
private var isSourceAddressField: Boolean = false
private var pickupLat: Double = 0.0
private var pickupLng: Double = 0.0
private var dropLat: Double = 0.0
private var dropLng: Double = 0.0
private var searchService: SearchService? = null
private var searchIntent: SearchIntent? = null
private lateinit var mFusedLocationProviderClient: FusedLocationProviderClient
companion object {
private const val TAG = "MapViewDemoActivity"
private const val MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"
private val LAT_LNG = LatLng(12.9716, 77.5946)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
// Get mapView
mMapView = findViewById(R.id.mapView)
var mapViewBundle: Bundle? = null
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY)
}
// Add "Your API key" in api_key field value
MapsInitializer.setApiKey("DAEDADRgIFzXbAJpOqImvjRAGRkmm3wGTux0O6JBiaddIPMNTJ4SawIN8ZHWu28dtc1f1H3Cqzh0LC1cgYIvBnl1edWVuWkjciH4NA==")
mMapView.onCreate(mapViewBundle)
// get map by async method
mMapView.getMapAsync(this)
//Checking permission
checkLocationPermission()
// Location service
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
//Initialize Search Service
getLocationFromService()
//Initialize OnClickListener
customCurrentLocation.setOnClickListener(this)
pickUpLocation.setOnClickListener(this)
dropLocation.setOnClickListener(this)
}
override fun onMapReady(map: HuaweiMap?) {
Log.d(TAG, "onMapReady: ")
// Get the HuaweiMap instance in this call back method.
hmap = map!!
// Move camera by CameraPosition param, latlag and zoom params can set here.
val build = CameraPosition.Builder().target(LatLng(13.0827, 80.2707)).zoom(10f).build()
val cameraUpdate = CameraUpdateFactory.newCameraPosition(build)
hmap.animateCamera(cameraUpdate)
hmap.setMaxZoomPreference(10f)
hmap.setMinZoomPreference(1f)
// Marker can be add by HuaweiMap
mMarker = hmap.addMarker(
MarkerOptions().position(LAT_LNG)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.garden_icon))
.clusterable(true))
mMarker?.showInfoWindow()
// circle can be add by HuaweiMap
mCircle = hmap.addCircle(
CircleOptions().center(LatLng(28.7041, 77.1025)).radius(45000.0).fillColor(Color.GREEN))
mCircle?.fillColor = Color.TRANSPARENT
}
override fun onStart() {
super.onStart()
mMapView.onStart()
}
override fun onStop() {
super.onStop()
mMapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
mMapView.onDestroy()
}
override fun onPause() {
mMapView.onPause()
super.onPause()
}
override fun onResume() {
super.onResume()
mMapView.onResume()
}
private fun checkLocationPermission() {
// check location permission
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
val strings = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
ActivityCompat.requestPermissions(this, strings, 1)
}
} else {
if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
val strings = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION,
"android.permission.ACCESS_BACKGROUND_LOCATION")
ActivityCompat.requestPermissions(this, strings, 2)
}
}
}
private fun getLocationFromService() {
// Add your API Key in encode
searchService = SearchServiceFactory.create(this,
URLEncoder.encode("Add your api_key"))
}
override fun onClick(v: View?) {
val id = v?.id
if (id == R.id.pickUpLocation) {
locationBox(100)
} else if (id == R.id.dropLocation) {
locationBox(101)
} else if (id == R.id.customCurrentLocation) {
getLastLocation()
}
}
private fun locationBox(requestcode: Int) {
searchIntent = SearchIntent()
searchIntent!!.setApiKey(URLEncoder.encode("DAEDADRgIFzXbAJpOqImvjRAGRkmm3wGTux0O6JBiaddIPMNTJ4SawIN8ZHWu28dtc1f1H3Cqzh0LC1cgYIvBnl1edWVuWkjciH4NA==", "utf-8"))
val intent = searchIntent!!.getIntent(this)
startActivityForResult(intent, requestcode)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 100) {
if (SearchIntent.isSuccess(resultCode)) {
isSourceAddressField = true
val site: Site = searchIntent!!.getSiteFromIntent(data)
pickUpLocation.setText(site.name)
querySuggestion()
}
}
if (requestCode == 101) {
if (SearchIntent.isSuccess(resultCode)) {
isSourceAddressField = false
val site: Site = searchIntent!!.getSiteFromIntent(data)
dropLocation.setText(site.name)
querySuggestion()
}
}
}
private fun querySuggestion() {
val request = QuerySuggestionRequest()
val query: String?
if (isSourceAddressField) {
query = pickUpLocation?.text.toString()
}else{
query = dropLocation?.text.toString()
}
if (!TextUtils.isEmpty(query)) {
request.query = query
}
searchService?.querySuggestion(
request,
searchResultListener as SearchResultListener<QuerySuggestionResponse>?
)
}
private var searchResultListener =
object : SearchResultListener<QuerySuggestionResponse> {
override fun onSearchResult(results: QuerySuggestionResponse?) {
val stringBuilder = StringBuilder()
results?.let {
val sites = results.sites
if (sites != null && sites.size > 0) {
for (site in sites) {
val location = site.location
if (isSourceAddressField) {
pickupLat = location.lat
pickupLng = location.lng
moveCamera(LatLng(pickupLat, pickupLng))
} else {
dropLat = location.lat
dropLng = location.lng
moveCamera(LatLng(dropLat, dropLng))
}
break
}
} else {
stringBuilder.append("0 results")
}
}
}
override fun onSearchError(status: SearchStatus) {
}
}
private fun getLastLocation() {
try {
val lastLocation = mFusedLocationProviderClient.lastLocation
lastLocation.addOnSuccessListener(OnSuccessListener { location ->
if (location == null) {
[email protected]
}
moveCamera(LatLng(location.latitude, location.longitude))
[email protected]
}).addOnFailureListener { e ->
}
} catch (e: Exception) {
}
}
private fun moveCamera(latLng: LatLng) {
hmap!!.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
}
}
In the activity_search.xml we can create the UI screen.
Java:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".search.SearchActivity">
<com.huawei.hms.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.huawei.hms.maps.MapView>
<RelativeLayout
android:id="@+id/startpoint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="42dp"
android:layout_marginTop="42dp"
android:layout_marginRight="62dp"
android:background="@drawable/blue_border_rounded_cornwe">
<EditText
android:id="@+id/pickUpLocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/start_loc"
android:background="@android:color/transparent"
android:hint="Choose starting point "
android:maxLines="1"
android:paddingLeft="17dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:textSize="13sp">
</EditText>
<ImageView
android:id="@+id/start_loc"
android:layout_width="20dp"
android:layout_height="17dp"
android:layout_centerVertical="true"
android:layout_marginLeft="17dp"
android:src="@drawable/start_icon" />
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="42dp"
android:layout_marginTop="23dp"
android:layout_marginRight="62dp"
android:layout_below="@+id/startpoint"
android:background="@drawable/blue_border_rounded_cornwe">
<EditText
android:id="@+id/dropLocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/dest_loc"
android:background="@android:color/transparent"
android:hint="Password"
android:maxLines="1"
android:paddingLeft="17dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:textSize="13sp">
</EditText>
<ImageView
android:id="@+id/dest_loc"
android:layout_width="20dp"
android:layout_height="17dp"
android:layout_centerVertical="true"
android:layout_marginLeft="17dp"
android:src="@drawable/dest_icon" />
</RelativeLayout>
<ImageView
android:id="@+id/customCurrentLocation"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="10dp"
android:baselineAlignBottom="true"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="@drawable/location_icon"/>
</RelativeLayout>
Demo
Tips and Tricks
1. Make sure you are already registered as Huawei developer.
2. Set minSDK version to 24 or later, otherwise you will get AndriodManifest merge issue.
3. Make sure you have added the agconnect-services.json file to app folder.
4. Make sure you have added SHA-256 fingerprint without fail.
5. Make sure all the dependencies are added properly.
Conclusion
In this article, we can learn how to search the hospitals located by source and destination address with HMS Core Kits such as Map, Site, and Location Kits. Map kit is to display maps, it covers map data of more than 200 countries and regions for searching any location address. Location kit provides to get the current location and location updates, and it provides flexible location based services globally to the users. Site kit provides with convenient and secure access to diverse, place-related services to users.
I hope you have read this article. If you found it is helpful, please provide likes and comments.
Reference
Map Kit - Documentation
Map Kit – Training Video
Location Kit – Documentation
Location Kit – Training Video
Site Kit