Nearby Place Search
{
"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"
}
Overview
This Nearby Place Search API can return a list of places around the current location of a user. When the user selects a place, your app obtains the place ID and searches for details about the place.
Before going to this article, first we need to learn how to add custom markers to Map. Check the below link
To customize Maps with Custom Marker and Custom Info Window - Maps Kit
After clicking any nearby item from that recycler view mapNearByItemClick method will trigger. Here More item getHwLocationType value is set to null.
Code:
@SuppressLint("RestrictedApi")
@Override
public void mapNearByItemClick(NearByTypeModel nearByTypeModel) {
if (nearByTypeModel.getHwLocationType() == null) {
if (loutNearByTypeRoot != null) {
loutNearByTypeRoot.removeAllViews();
}
myLocationFab.setVisibility(View.INVISIBLE);
fabMapType.setVisibility(View.INVISIBLE);
setNearByTypeFoodData();
setNearByTypeThingsToDo();
setNearByTypeShopping();
setNearByTypeServices();
bottomSlideToUp(cardViewNearByType);
} else {
if (NetworkUtil.isNetworkConnected(this)) {
if (cardViewNearByType.getVisibility() == View.VISIBLE)
bottomSlideToDown(cardViewNearByType);
isFromNearByPlace = true;
progressBarPlaces.setVisibility(View.VISIBLE);
editTextSearch.setText(nearByTypeModel.getNearByTypeName());
behavior.setPeekHeight(0);
recyclerViewNearByTypes.setVisibility(View.GONE);
nearBySearch(nearByTypeModel.getNearByTypeName(), nearByTypeModel.getHwLocationType(), 20);
} else {
showNetworkDialog();
}
}
}
Create content_near_types.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="5dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/dimen_10"
android:orientation="vertical">
<TextView
android:id="@+id/txt_near_by_type_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen_10"
android:text="Food and Drinks"
android:textColor="#000"
android:textSize="14sp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_near_by_type"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
Create root layout for adding content_near_types.xml child
Code:
<androidx.cardview.widget.CardView
android:id="@+id/card_near_by_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dimen_50">
<ImageView
android:id="@+id/img_back_near_by_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_margin="@dimen/dimen_10"
android:src="@drawable/back_pc" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:text="More Categories"
android:textColor="#000"
android:textSize="14sp"
android:textStyle="bold" />
</RelativeLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/lout_near_by_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.cardview.widget.CardView>
Now set data to adapters and add child layouts to root. Check the below code
Code:
private void setNearByTypeServices() {
View view = LayoutInflater.from(MapActivity.this).inflate(R.layout.content_near_types, null, false);
TextView txtNearByTypeTitle = view.findViewById(R.id.txt_near_by_type_title);
RecyclerView recyclerViewNearByType = view.findViewById(R.id.recycler_view_near_by_type);
NearByAdapter nearByAdapter = new NearByAdapter(MapActivity.this);
GridLayoutManager gridLayoutManager = new GridLayoutManager(MapActivity.this, 2);
recyclerViewNearByType.setLayoutManager(gridLayoutManager);
recyclerViewNearByType.setAdapter(nearByAdapter);
ArrayList<NearByTypeModel> nearByTypeServices = nearByTypeServices();
txtNearByTypeTitle.setText("Services");
nearByAdapter.addList(nearByTypeServices);
loutNearByTypeRoot.addView(view);
}
private void setNearByTypeShopping() {
View view = LayoutInflater.from(MapActivity.this).inflate(R.layout.content_near_types, null, false);
TextView txtNearByTypeTitle = view.findViewById(R.id.txt_near_by_type_title);
RecyclerView recyclerViewNearByType = view.findViewById(R.id.recycler_view_near_by_type);
NearByAdapter nearByAdapter = new NearByAdapter(MapActivity.this);
GridLayoutManager gridLayoutManager = new GridLayoutManager(MapActivity.this, 2);
recyclerViewNearByType.setLayoutManager(gridLayoutManager);
recyclerViewNearByType.setAdapter(nearByAdapter);
ArrayList<NearByTypeModel> nearByTypeShopping = nearByTypeShopping();
txtNearByTypeTitle.setText("Shopping");
nearByAdapter.addList(nearByTypeShopping);
loutNearByTypeRoot.addView(view);
}
private void setNearByTypeThingsToDo() {
View view = LayoutInflater.from(MapActivity.this).inflate(R.layout.content_near_types, null, false);
TextView txtNearByTypeTitle = view.findViewById(R.id.txt_near_by_type_title);
RecyclerView recyclerViewNearByType = view.findViewById(R.id.recycler_view_near_by_type);
NearByAdapter nearByAdapter = new NearByAdapter(MapActivity.this);
GridLayoutManager gridLayoutManager = new GridLayoutManager(MapActivity.this, 2);
recyclerViewNearByType.setLayoutManager(gridLayoutManager);
recyclerViewNearByType.setAdapter(nearByAdapter);
ArrayList<NearByTypeModel> nearByTypeThingsToDoList = nearByTypeThingsToDo();
txtNearByTypeTitle.setText("Things to do");
nearByAdapter.addList(nearByTypeThingsToDoList);
loutNearByTypeRoot.addView(view);
}
private void setNearByTypeFoodData() {
View view = LayoutInflater.from(MapActivity.this).inflate(R.layout.content_near_types, null, false);
TextView txtNearByTypeTitle = view.findViewById(R.id.txt_near_by_type_title);
RecyclerView recyclerViewNearByType = view.findViewById(R.id.recycler_view_near_by_type);
NearByAdapter nearByAdapter = new NearByAdapter(MapActivity.this);
GridLayoutManager gridLayoutManager = new GridLayoutManager(MapActivity.this, 2);
recyclerViewNearByType.setLayoutManager(gridLayoutManager);
recyclerViewNearByType.setAdapter(nearByAdapter);
ArrayList<NearByTypeModel> foodList = nearByTypeFood();
txtNearByTypeTitle.setText("Food and Drink");
nearByAdapter.addList(foodList);
loutNearByTypeRoot.addView(view);
}
private ArrayList<NearByTypeModel> nearByTypeFood() {
ArrayList<NearByTypeModel> nearByTypeModels = new ArrayList<>();
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Restaurants", HwLocationType.RESTAURANT));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Hotels", HwLocationType.HOTEL));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Bars", HwLocationType.BAR));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Takeaway", HwLocationType.TAKE_AWAY_RESTAURANT));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Coffee", HwLocationType.COFFEE_SHOP));
return nearByTypeModels;
}
private ArrayList<NearByTypeModel> nearByTypeThingsToDo() {
ArrayList<NearByTypeModel> nearByTypeModels = new ArrayList<>();
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Parks", HwLocationType.PARK));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Music Center", HwLocationType.MUSIC_CENTER));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Cinema", HwLocationType.CINEMA));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Art school", HwLocationType.ART_SCHOOL));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Museum", HwLocationType.MUSEUM));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Library", HwLocationType.LIBRARY));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Night life", HwLocationType.NIGHTLIFE));
return nearByTypeModels;
}
private ArrayList<NearByTypeModel> nearByTypeShopping() {
ArrayList<NearByTypeModel> nearByTypeModels = new ArrayList<>();
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Groceries", HwLocationType.GROCERY));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Shopping center", HwLocationType.SHOPPING_CENTER));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Beauty supplies", HwLocationType.BEAUTY_SUPPLY_SHOP));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Electronics store", HwLocationType.ELECTRONICS_STORE));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Car dealers", HwLocationType.CAR_DEALER));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Sports store", HwLocationType.SPORTS_STORE));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Convenience store", HwLocationType.CONVENIENCE_STORE));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Shopping", HwLocationType.SHOPPING));
return nearByTypeModels;
}
private ArrayList<NearByTypeModel> nearByTypeServices() {
ArrayList<NearByTypeModel> nearByTypeModels = new ArrayList<>();
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Dry cleaning", HwLocationType.DRY_CLEANERS));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Electric vehicle charging", HwLocationType.ELECTRIC_VEHICLE_CHARGING_STATION));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Hotels", HwLocationType.HOTEL));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Petrol", HwLocationType.PETROL_STATION));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Hospitals", HwLocationType.GENERAL_HOSPITAL));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Beauty salons", HwLocationType.BEAUTY_SALON));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Post office", HwLocationType.POST_OFFICE));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Parking", HwLocationType.TRUCK_PARKING_AREA));
nearByTypeModels.add(new NearByTypeModel(R.drawable.cinema_holder, "Car wash", HwLocationType.CAR_WASH));
return nearByTypeModels;
}
Find the output in below image
Now initialize Search Service
Code:
private void initSearchService() {
try {
searchService = SearchServiceFactory.create(this, URLEncoder.encode(getString(R.string.api_key), "utf-8"));
} catch (UnsupportedEncodingException e) {
Log.e(TAG + " Exception", "encode apikey error " + e.getMessage());
}
}
Now Create a NearbySearchRequest object, which is used as the request body for nearby place search. Related parameters are as follows, among which location is mandatory and others are optional:
location: current location of a user.
radius: search radius, in meters. The value ranges from 1 to 50000. The default value is 1000. The search radius is used to specify an area where places are searched in priority, but not restrict the search result to this area.
query: search keyword.
poiType: POI type of returned places. The value range is the same as that of LocationType
hwPoiType: Huawei POI type of returned places. This parameter is recommended. The value range is the same as that of HwLocationType.
language: language in which search results are displayed. For details about the value range, refer to language codes in Language Mapping. If this parameter is not passed, English will be used. If English is unavailable, the local language will be used.
pageSize: number of records on each page. The value ranges from 1 to 20. The default value is 20.
pageIndex: current page number. The value ranges from 1 to 60. The default value is 1
NOTE
If both poiType and hwPoiType are set, search results of hwPoiType take precedence.
The following formula must be met: pageIndex x pageSize ≤ 60
More information, you can visit https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201380592438280450&fid=0101187876626530001
Related
Hey guys,
I am trying to change textview properties of a textview that looks like this:
{
"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 a seperate Activity that looks like this:
I tried to do this with bundles but I can't get it to work.
This is how my BookActivity looks like:
Code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.book_activity);
//this is where the size property comes in
Integer size = getIntent().getExtras().getInt("SGRkey");
TextView test2 = (TextView) findViewById(R.id.booktext);
test2.setTextSize(size);
Spinner spinner = (Spinner) findViewById(R.id.kapitelspinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.kapitel_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}
public class MyOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
Toast.makeText(parent.getContext(),
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
final String[] theporn = getResources().getStringArray(R.array.allkapitel);
TextView text = (TextView) findViewById(R.id.booktext);
text.setText(theporn[pos]);
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
(i pick the chapter string in the spinner and that works just fine.)
And this is how my SettingsActivity looks like:
Code:
public class SettingsActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_view);
Spinner SGRspinner = (Spinner) findViewById(R.id.schriftgroeße_spinner);
ArrayAdapter<CharSequence> SGRadapter = ArrayAdapter.createFromResource(
this, R.array.schriftgroesse_list, android.R.layout.simple_spinner_item);
SGRadapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
SGRspinner.setAdapter(SGRadapter);
}
public class SGROnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
Intent answer = new Intent();
Toast.makeText(parent.getContext(),
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
final String[] SGRstring = getResources().getStringArray(R.array.schriftgroesse_list);
int SGRint = Integer.parseInt(SGRstring[pos]);
Bundle size = new Bundle();
size.putInt("SGRkey", SGRint);
Intent nextActivity = new Intent(com.asm.reader.SettingsActivity.this, com.asm.reader.BookActivity.class);
nextActivity.putExtras(size);
com.asm.reader.SettingsActivity.this.startActivity(nextActivity);
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
I get an error when I try this. All activities are declared in the manifest. I really don't know how to go on. I'm pretty new to this, so sorry if this is something simple, but any help would be greatly appreciated!!
What is the error and where does it occur? Have you tried stepping through with the debugger?
I think it would be better if you'd do your layout on xml.
Sent from my SGH-T959 using XDA App
Try using a PreferenceActivity instead of an Activity for your settings. Then tie in SharedPreferences so that a value there can be edited and displayed by two activities. One will write the value and the other will read it
also... your code seems to have a bunch of useless stuff. in your SGROnItemSelectedListener you have an Intent you never use Intent answer = new Intent();
I don't see an onRecieve() to do anything with the intent you sent
From something awesome
first of all, thanks for the replies!
when I run the application, it says it has stopped unexpectedly.
the debugger says this:
@iynfynity
I have my layout in xml. im trying to change it with the settings activity
@killersnowman
the google dev guide says that prior to honeycomb, the class only allows a single preference. do you think that would interfere with what i wanna do? (since i wanna make the app available for API level 4 or so. thanks for the advice!
I'm trying to figure out the flow of things here.
So I'm assuming that your app launches and you get the tab bar shown and "Home" is the default activity (and its code is the first code block) and it starts normally. Now you hit the "Settings" tab and its activity (and its code is in the second block) starts OK, then you "Select Max Size" (assuming my rusty German is correct), set it to 8, and you want this "size" to be used to change the font size (guessing here) of the textview in the "Home" activity?
If so, then I don't think you are doing this right. The code in the settings tab's activity should not try to relaunch the home activity. You should save the settings value somewhere (like a preference class) then when the Home activity is reactivated (by the user clicking back to that tab) you should read the preferences and adjust your textview using the saved value.
Gene Poole said:
If so, then I don't think you are doing this right. The code in the settings tab's activity should not try to relaunch the home activity. You should save the settings value somewhere (like a preference class) then when the Home activity is reactivated (by the user clicking back to that tab) you should read the preferences and adjust your textview using the saved value.
Click to expand...
Click to collapse
yep. thats what i was trying to say so inelegantly on my mobile
Gene Poole said:
I'm trying to figure out the flow of things here.
So I'm assuming that your app launches and you get the tab bar shown and "Home" is the default activity (and its code is the first code block) and it starts normally. Now you hit the "Settings" tab and its activity (and its code is in the second block) starts OK, then you "Select Max Size" (assuming my rusty German is correct), set it to 8, and you want this "size" to be used to change the font size (guessing here) of the textview in the "Home" activity?
thats exactly how i want it
If so, then I don't think you are doing this right. The code in the settings tab's activity should not try to relaunch the home activity. You should save the settings value somewhere (like a preference class) then when the Home activity is reactivated (by the user clicking back to that tab) you should read the preferences and adjust your textview using the saved value.
thank you very much!
Click to expand...
Click to collapse
I will try it out as soon as i get home from work tonight
I am really puzzled by the coding part of this.
The dev reference looks convoluted and it gets me really confused. I'm sorry that I am such a newbie at this but I couldn't find any good guides out there that helped me. All I got so far is the XML part of it:
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Einstellungen am Text">
<ListPreference
android:title="Schriftgröße"
android:summary="Passen Sie die Schriftgröße ihres Textes an"
android:key="schriftgroesse"
android:defaultValue="8"
android:entries="@array/schriftgroesse_list"
android:entryValues="@array/schriftgroesse_values" />
<ListPreference
android:title="Schriftfarbe"
android:summary="Passen Sie die Farbe ihres Textes an"
android:key="schriftfarbe"
android:defaultValue="#ffffff"
android:entries="@array/schriftfarbe_list"
android:entryValues="@array/schriftfarbe_values" />
<ListPreference
android:title="Hintergrundfarbe"
android:summary="Passen Sie den Hintergrund an"
android:key="schriftfarbe"
android:defaultValue="#000000"
android:entries="@array/hintergrundfarbe_list"
android:entryValues="@array/hintergrundfarbe_values" />
</PreferenceCategory>
</PreferenceScreen>
(I know, nothing really..)
It would be very much appreciated if someone could help me !
I am stuck on the color setting
Code:
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
TextView text = (TextView) findViewById(R.id.booktext);
SharedPreferences PRFSize=PreferenceManager.getDefaultSharedPreferences(this);
String Size = PRFSize.getString("schriftgroesse", "8");
SharedPreferences PRFColor=PreferenceManager.getDefaultSharedPreferences(this);
String Color = PRFColor.getString("schriftfarbe", "#ffffff");
Integer SizeInt = Integer.parseInt(Size);
text.setTextSize(SizeInt);
//now what?
text.setTextColor();
Context context = getApplicationContext();
CharSequence hello = Size;
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, hello, duration);
toast.show();
}
How do I convert the String (Color) to an interger/float to get it to work for the method setTextColor?? I always get an error when I try to do
Code:
Integer.parseInt( string );
..
I am puzzled
Why not load/save to SharedPreferences as an integer (use Editor.putInt() and getInt() )?
Okay, sorry for the quadriple post, but I got it all now. Thanks for all the help!
This article is originally from HUAWEI Developer Foum
Forum link: https://forums.developer.huawei.com/forumPortal/en/home
About GymOut:
GymOut is a simple work out App which uses some of the features of HMS awareness Kit. In this, we have to set Gym location (here it is taking current location) and work out time. Once we enter into Gym it prompts us to plug in the head set to listen the work out music. The music will stop playing after the completion of work out /on leaving the gym.
{
"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"
}
An Introduction for Awareness Kit:
HUAWEI Awareness Kit provides your app with the ability to obtain contextual information including users' current time, location, behavior, audio device status, ambient light, weather, and nearby beacons. Through this features the app can gain insight into a user's current situation more efficiently, making it possible to deliver a smarter, more considerate user experience
· Capture API
The Capture API allows the app to request the current user status, such as time, location, behaviour, and whether a headset is connected. For example, it can request location for getting latitude and longitude.
· BarrierAPI
The Barrier API allows the app to set a combination of contextual conditions. When the preset contextual conditions are met, the app will receive a notification. We can even accommodate our app with different combinations of contextual conditions to support different use cases. For example, we will get notification once we enter into a specified location.
Software Requirements
Android Studio
Java JDK 1.8 or later
Huawei Mobile Services (APK) 4.0.0.300 or later
Integration
1. Create a project in android studio and Huawei AGC.
2. Provide the SHA-256 Key in App Information Section.
3. Provide storage location. (Selected Singapore here)
4. Download the agconnect-services.json from AGCand save into app directory.
5. In root build.gradle
Go to allprojects->repositories and buildscript->repositories and the given line.
Code:
maven { url 'http://developer.huawei.com/repo/' }
In dependency add class path
Code:
classpath 'com.huawei.agconnect:agcp:1.2.1.301'
6. In app build.gradle
We have to add signingConfigs and buildTypes, otherwise we have to create signed apk for awareness testing.
Code:
signingConfigs {
release {
storeFile file('store.jks')
keyAlias 'mykey'
keyPassword 'hmsapp'
storePassword 'hmsapp'
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.release
debuggable true
}
}
Add Implementation
Code:
implementation 'com.huawei.hms:awareness:1.0.4.301'
Apply plugin
Code:
apply plugin: 'com.huawei.agconnect'
7. The app need the following permissions
Code:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Code Implementation:
In this application we are using the following HMS Features:
Capture API
Location Capture: For getting gym Latitude and Longitude.
Barrier API
Location Barrier: To get notification when entering into Gym and exit from Gym .
Headset Barrier:To get alert to connect Head set for workout music
Time Barrier: To alert, once the time elapses the specified workout time.
To capture Location API using getLocation () function
Code:
private void getLocation() {
Awareness.getCaptureClient(this).getLocation()
.addOnSuccessListener(new OnSuccessListener<LocationResponse>() {
@Override
public void onSuccess(LocationResponse locationResponse) {
Location location = locationResponse.getLocation();
latitude=location.getLatitude();
longitude=location.getLongitude();
Toast.makeText(getApplicationContext(),"Longitude:" + longitude
+ ",Latitude:" + latitude,Toast.LENGTH_SHORT).show();
mLogView.printLog("Longitude:" + longitude
+ ",Latitude:" + latitude);
mp = MediaPlayer.create(getApplicationContext(), R.raw.audio);
mp.setLooping(true);
alert_stayTimeDialog();
//add_locationBarrier_enter
AwarenessBarrier enterBarrier = LocationBarrier.enter(latitude, longitude, radius);
Utils.addBarrier(getApplicationContext(), ENTER_BARRIER_LABEL, enterBarrier, mPendingIntent);
AwarenessBarrier exitBarrier = LocationBarrier.exit(latitude, longitude, radius);
Utils.addBarrier(getApplicationContext(), EXIT_BARRIER_LABEL, exitBarrier, mPendingIntent);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Toast.makeText(getApplicationContext(),"Failed to get the location.",Toast.LENGTH_SHORT).show();
mLogView.printLog("Failed to get the location.");
Log.e(TAG, "Failed to get the location.", e);
}
});
mScrollView.postDelayed(()-> mScrollView.smoothScrollTo(0,mScrollView.getBottom()),200);
}
Using GymBarrierReceiver to receive the broadcast sent by Awareness Kit when the barrier status changes.
Code:
final class GymBarrierReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
BarrierStatus barrierStatus = BarrierStatus.extract(intent);
String label = barrierStatus.getBarrierLabel();
int barrierPresentStatus = barrierStatus.getPresentStatus();
switch (label) {
case ENTER_BARRIER_LABEL:
if (barrierPresentStatus == BarrierStatus.TRUE) {
mLogView.printLog("You are in Gym");
alert_startWorkOutDialog();
} else if (barrierPresentStatus == BarrierStatus.FALSE) {
// mLogView.printLog("You are away from Gym");
} else {
mLogView.printLog("The location status is unknown.");
}
break;
case STAY_BARRIER_LABEL:
if (barrierPresentStatus == BarrierStatus.TRUE) {
mLogView.printLog("You have to spent "
+ workOutTime + " minutes in Gym");
} else if (barrierPresentStatus == BarrierStatus.FALSE) {
mLogView.printLog("Your time of duration in Gym is Over.");
} else {
mLogView.printLog("The location status is unknown.");
}
break;
case EXIT_BARRIER_LABEL:
if (barrierPresentStatus == BarrierStatus.TRUE) {
mLogView.printLog("You are exiting Gym");
mp.pause();
play_pause.setBackground(getDrawable(android.R.drawable.ic_media_play));
} else if (barrierPresentStatus == BarrierStatus.FALSE) {
// mLogView.printLog("You are in Gym");
} else {
mLogView.printLog("The location status is unknown.");
}
break;
case KEEPING_BARRIER_LABEL:
if (barrierPresentStatus == BarrierStatus.TRUE) {
mLogView.printLog("Audio is playing...");
play_pause.setVisibility(View.VISIBLE);
mp.start();
play_pause.setBackground(getDrawable(android.R.drawable.ic_media_pause));
} else if (barrierPresentStatus == BarrierStatus.FALSE) {
mLogView.printLog("Connect headset to play audio");
mp.pause();
play_pause.setBackground(getDrawable(android.R.drawable.ic_media_play));
} else {
mLogView.printLog("The headset status is unknown.");
}
break;
case CONNECTING_BARRIER_LABEL:
if (barrierPresentStatus == BarrierStatus.TRUE) {
mLogView.printLog("The headset is connecting. Audio is playing");
play_pause.setVisibility(View.VISIBLE);
mp.start();
play_pause.setBackground(getDrawable(android.R.drawable.ic_media_pause));
} else if (barrierPresentStatus == BarrierStatus.FALSE) {
} else {
mLogView.printLog("The headset status is unknown.");
}
break;
case DURING_TIME_PERIOD_BARRIER_LABEL:
if (barrierPresentStatus == BarrierStatus.TRUE) {
mLogView.printLog("Your Work out is "+workOutTime+" minutes.");
} else if (barrierPresentStatus == BarrierStatus.FALSE) {
mLogView.printLog("Work out time reached "+workOutTime+" minutes.");
} else {
mLogView.printLog("The time status is unknown.");
}
break;
default:
break;
}
mScrollView.postDelayed(()-> mScrollView.smoothScrollTo(0,mScrollView.getBottom()*3),200);
}
}
MediaPlayer is added as given :
Code:
MediaPlayer mp = MediaPlayer.create(this, R.raw.audio);
mp.setLooping(true);
CountDownTimer to notify remaining workout time:
Code:
public void countDown(long workOutInMs){
new CountDownTimer(workOutInMs,1000) {
@Override
public void onTick(long millisUntilFinished) {
int seconds = (int) (millisUntilFinished / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
workOut_txt.setText(String.format("%d:%02d", minutes, seconds));
// counter++;
}
@Override
public void onFinish() {
workOut_txt.setText("Your work out is over");
mp.pause();
play_pause.setBackground(getDrawable(android.R.drawable.ic_media_play));
play_pause.setVisibility(View.GONE);
}
}.start();
}
Added different barriers as given:
Code:
AwarenessBarrier enterBarrier = LocationBarrier.enter(latitude, longitude, radius);
Utils.addBarrier(getApplicationContext(), ENTER_BARRIER_LABEL, enterBarrier, mPendingIntent);
AwarenessBarrier exitBarrier = LocationBarrier.exit(latitude, longitude, radius);
Utils.addBarrier(getApplicationContext(), EXIT_BARRIER_LABEL, exitBarrier, mPendingIntent);
AwarenessBarrier stayBarrier = LocationBarrier.stay(latitude, longitude, radius, workOutInMs);
Utils.addBarrier(getApplicationContext(), STAY_BARRIER_LABEL, stayBarrier, mPendingIntent);
AwarenessBarrier keepingConnectedBarrier = HeadsetBarrier.keeping(HeadsetStatus.CONNECTED);
Utils.addBarrier(getApplicationContext(), KEEPING_BARRIER_LABEL, keepingConnectedBarrier, mPendingIntent);
AwarenessBarrier connectingBarrier = HeadsetBarrier.connecting();
Utils.addBarrier(getApplicationContext(), CONNECTING_BARRIER_LABEL, connectingBarrier, mPendingIntent);
AwarenessBarrier timePeriodBarrier = TimeBarrier.duringTimePeriod(currentTimeStamp,
currentTimeStamp + workOutInMs);
Utils.addBarrier(getApplicationContext(), DURING_TIME_PERIOD_BARRIER_LABEL,
timePeriodBarrier, mPendingIntent);
The function alert_stayTimeDialog() is used to capture user workout time.
Code:
void alert_stayTimeDialog(){
final EditText edittext = new EditText(this);
edittext.setText("0");
edittext.setInputType(InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_CLASS_NUMBER);
AlertDialog.Builder alert = new AlertDialog.Builder(
this);
alert.setMessage("Your Workout Time");
alert.setTitle("Enter time in minutes ");
alert.setView(edittext);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//What ever you want to do with the value
Editable YouEditTextValue = edittext.getText();
//OR
int stayTime = Integer.parseInt(edittext.getText().toString());
//Add the code after success
SharedPreferences.Editor editor = gymOutPref.edit();
editor.putBoolean("SET_WORKOUT", true);
editor.putInt("SET_WORKOUT_TIME", stayTime);
editor.commit();
workOutTime=stayTime;
set_workout.setEnabled(false);
set_workout.setBackground(getDrawable(R.drawable.button_style_disable));
delete_workout.setEnabled(true);
delete_workout.setBackground(getDrawable(R.drawable.button_style));
workOut_txt.setText("WorkOut Time:"+stayTime+" Mnts");
Toast.makeText(getApplicationContext(), "WorkOut Time: " + stayTime, Toast.LENGTH_LONG).show();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// what ever you want to do with No option.
}
});
alert.show();
}
More articles like this, you can visit HUAWEI Developer Forum and Medium.
{
"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:
Behavior Awareness is being used to obtain user current behaviour or detect the behavior change.
For calling Behavior Awareness capability we have to assign the given permissions in the manifest file.
Code:
<!-- Behavior detection permission (Android 10 or later). This permission is sensitive and needs to be dynamically applied for in the code after being declared. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<!-- Behavior detection permission (Android 9). This permission is sensitive and needs to be dynamically applied for in the code after being declared. -->
<uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION" />
Capture API
We can use the Capture API to detect user behaviour such as walking, running,cycling,driving etc.
To get current behavior status of a user, we need to call the getBehavior() method - this will return an instance of the BehaviorResponse class that if successful, will contain information about the current user behavior.
Code:
private void getBehavorInfo() {
Awareness.getCaptureClient(this).getBehavior()
.addOnSuccessListener(new OnSuccessListener<BehaviorResponse>() {
@Override
public void onSuccess(BehaviorResponse behaviorResponse) {
BehaviorStatus behaviorStatus = behaviorResponse.getBehaviorStatus();
DetectedBehavior mostLikelyBehavior = behaviorStatus.getMostLikelyBehavior();
String str1 = "Most likely behavior type is " + mostLikelyBehavior.getType() +
",the confidence is " + mostLikelyBehavior.getConfidence();
behavior_info_capture.setTextColor(getColor(R.color.green));
if(mostLikelyBehavior.getType()==0){
behavior_info_capture.setText("You are in Vehicle");
behavior_image.setImageDrawable(getDrawable(R.drawable.vehicle));
}else if(mostLikelyBehavior.getType()==1){
behavior_info_capture.setText("You are in Bicycle");
behavior_image.setImageDrawable(getDrawable(R.drawable.bicycle));
}else if(mostLikelyBehavior.getType()==2){
behavior_info_capture.setText("You are on Foot");
behavior_image.setImageDrawable(getDrawable(R.drawable.foot));
} else if(mostLikelyBehavior.getType()==3){
behavior_info_capture.setText("You are still now");
behavior_image.setImageDrawable(getDrawable(R.drawable.still));
}else if(mostLikelyBehavior.getType()==4){
behavior_info_capture.setText("Unknown behavior");
}else if(mostLikelyBehavior.getType()==7){
behavior_info_capture.setText("You are Walking");
behavior_image.setImageDrawable(getDrawable(R.drawable.walking));
}else if(mostLikelyBehavior.getType()==8){
behavior_info_capture.setText("You are Running");
behavior_image.setImageDrawable(getDrawable(R.drawable.running));
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "get behavior failed", e);
behavior_info_capture.setTextColor(getColor(R.color.red));
behavior_info_capture.setText("get behavior failed: "+e);
}
});
}
Barrier API
We can use the Barrier API to detect the behavior change such as from walking to running.
Public Methods:
Behavior barriers, including the beginning, ending, and keeping barriers of behaviors. Given three mathods which we use in behavior barrier.
public static AwarenessBarrier beginning(int… behaviorTypes)
When a user is in the behavior status, the barrier status is TRUE and a barrier event is reported. After 5s, the barrier status changes to FALSE.
Code:
AwarenessBarrier awarenessBarrier = BehaviorBarrier.beginning(BehaviorBarrier.BEHAVIOR_WALKING);
public static AwarenessBarrier keeping(int… behaviorTypes)
When a user is in the behavior status , the barrier status is TRUE and a barrier event is reported.
Code:
AwarenessBarrier awarenessBarrier = BehaviorBarrier.keeping(BehaviorBarrier.BEHAVIOR_WALKING);
public static AwarenessBarrier ending(int… behaviorTypes)
When a user stops the behavior, the barrier status is TRUE and a barrier event is reported. After 5s, the barrier status changes to FALSE.
Code:
AwarenessBarrier awarenessBarrier = BehaviorBarrier.ending(BehaviorBarrier.BEHAVIOR_WALKING);
Sample Code
Given an example in which a barrier is triggered by the keeping condition. That is, the barrier will be triggered when a user is in stand still.
Code:
public class BehaviorBarrierActivity extends AppCompatActivity {
private static final String TAG ="BehaviorBarrierActivity" ;
private TextView behavior_info_barrier;
private ImageView behavior_info_barrier_image;
PendingIntent pendingIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.behavior_barrier_activity);
behavior_info_barrier=findViewById(R.id.behavior_info_barrier);
behavior_info_barrier_image=findViewById(R.id.behavior_info_barrier_image);
// define PendingIntent that will be triggered upon a barrier status change.
final String BARRIER_RECEIVER_ACTION = getApplication().getPackageName() + "BEHAVIOR_BARRIER_RECEIVER_ACTION";
Intent intent = new Intent(BARRIER_RECEIVER_ACTION);
pendingIntent = PendingIntent.getBroadcast(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
BehaviorBarrierReceiver barrierReceiver = new BehaviorBarrierReceiver();
registerReceiver(barrierReceiver, new IntentFilter(BARRIER_RECEIVER_ACTION));
addbarrier(this);
}
private void addbarrier(Context context) {
//define the barrier
AwarenessBarrier keepStillBarrier = BehaviorBarrier.keeping(BehaviorBarrier.BEHAVIOR_STILL);
//define the label for the barrier and add the barrier
String behaviorBarrierLabel = "behavior keeping barrier";
//add the barrier
BarrierUpdateRequest.Builder builder = new BarrierUpdateRequest.Builder();
BarrierUpdateRequest request = builder.addBarrier(behaviorBarrierLabel, keepStillBarrier,pendingIntent).build();
Awareness.getBarrierClient(context).updateBarriers(request)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(getApplicationContext(), "add barrier success", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Toast.makeText(getApplicationContext(), "add barrier failed", Toast.LENGTH_SHORT).show();
Log.e(TAG, "add barrier failed", e);
}
});
}
// define the broadcast receiver to listen for the barrier event.
class BehaviorBarrierReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
BarrierStatus barrierStatus = BarrierStatus.extract(intent);
String label = barrierStatus.getBarrierLabel();
switch(barrierStatus.getPresentStatus()) {
case BarrierStatus.TRUE:
Log.i(TAG, label + " status:true");
behavior_info_barrier.setText("You are standing now");
behavior_info_barrier_image.setImageDrawable(getDrawable(R.drawable.still));
break;
case BarrierStatus.FALSE:
Log.i(TAG, label + " status:false");
behavior_info_barrier.setText("Looks like you are not standing");
behavior_info_barrier_image.setImageDrawable(getDrawable(R.drawable.foot));
break;
case BarrierStatus.UNKNOWN:
Log.i(TAG, label + " status:unknown");
break;
}
}
}
}
References:
https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/awareness-behavior-dev
More information like this, you can visit HUAWEI Developer Forum
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201333611965550036&fid=0101187876626530001
Introduction
Nowadays, you’ll see cute and funny face stickers everywhere. They’re not only used in camera apps, but also in social media and entertainment apps. In this post, I’m going to show you how to create a 2D sticker using HUAWEI ML Kit. We’ll share the development process for 3D stickers soon, so keep an eye out!
Scenarios
Apps that are used to take and edit photos, such as beauty cameras and social media apps (TikTok, Weibo, and WeChat, etc.), often offer a range of stickers which can be used to customize images. With these stickers, users can create content which is more engaging and shareable.
Preparations
Add the Huawei Maven Repository to the Project-Level build.gradle File
Open the build.gradle file in the root directory of your Android Studio project.
{
"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"
}
Add the Maven repository address.
Code:
buildscript {
{
maven {url 'http://developer.huawei.com/repo/'}
}
}
allprojects {
repositories {
maven { url 'http://developer.huawei.com/repo/'}
}
}
Add SDK Dependencies to the App-Level build.gradle File
Code:
// Face detection SDK.
implementation 'com.huawei.hms:ml-computer-vision-face:2.0.1.300'
// Face detection model.
implementation 'com.huawei.hms:ml-computer-vision-face-shape-point-model:2.0.1.300'
Apply for Camera, Network Access, and Storage Permissions in the AndroidManifest.xml File
Code:
<!--Camera permission-->
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<!--Write permission-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--Read permission-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Code Development
Set the Face Analyzer
Code:
MLFaceAnalyzerSetting detectorOptions;
detectorOptions = new MLFaceAnalyzerSetting.Factory()
.setFeatureType(MLFaceAnalyzerSetting.TYPE_UNSUPPORT_FEATURES)
.setShapeType(MLFaceAnalyzerSetting.TYPE_SHAPES)
.allowTracing(MLFaceAnalyzerSetting.MODE_TRACING_FAST)
.create();
detector = MLAnalyzerFactory.getInstance().getFaceAnalyzer(detectorOptions);
Obtain Face Contour Points and Pass Them to the FacePointEngine
Use the camera callback to obtain camera frame data, then call the face analyzer to obtain face contour points, and pass the points to the FacePointEngine. This will allow the sticker filter to use them later.
Code:
@Override
public void onPreviewFrame(final byte[] imgData, final Camera camera) {
int width = mPreviewWidth;
int height = mPreviewHeight;
long startTime = System.currentTimeMillis();
// Set the shooting directions of the front and rear cameras to be the same.
if (isFrontCamera()){
mOrientation = 0;
}else {
mOrientation = 2;
}
MLFrame.Property property =
new MLFrame.Property.Creator()
.setFormatType(ImageFormat.NV21)
.setWidth(width)
.setHeight(height)
.setQuadrant(mOrientation)
.create();
ByteBuffer data = ByteBuffer.wrap(imgData);
// Call the face analyzer API.
SparseArray<MLFace> faces =
detector.analyseFrame(MLFrame.fromByteBuffer(data,property));
// Determine whether face information is obtained.
if(faces.size()>0){
MLFace mLFace = faces.get(0);
EGLFace EGLFace = FacePointEngine.getInstance().getOneFace(0);
EGLFace.pitch = mLFace.getRotationAngleX();
EGLFace.yaw = mLFace.getRotationAngleY();
EGLFace.roll = mLFace.getRotationAngleZ() - 90;
if (isFrontCamera())
EGLFace.roll = -EGLFace.roll;
if (EGLFace.vertexPoints == null) {
EGLFace.vertexPoints = new PointF[131];
}
int index = 0;
// Obtain the coordinates of a user's face contour points and convert them to the floating point numbers in normalized coordinate system of OpenGL.
for (MLFaceShape contour : mLFace.getFaceShapeList()) {
if (contour == null) {
continue;
}
List<MLPosition> points = contour.getPoints();
for (int i = 0; i < points.size(); i++) {
MLPosition point = points.get(i);
float x = ( point.getY() / height) * 2 - 1;
float y = ( point.getX() / width ) * 2 - 1;
if (isFrontCamera())
x = -x;
PointF Point = new PointF(x,y);
EGLFace.vertexPoints[index] = Point;
index++;
}
}
// Insert a face object.
FacePointEngine.getInstance().putOneFace(0, EGLFace);
// Set the number of faces.
FacePointEngine.getInstance().setFaceSize(faces!= null ? faces.size() : 0);
}else{
FacePointEngine.getInstance().clearAll();
}
long endTime = System.currentTimeMillis();
Log.d("TAG","Face detect time: " + String.valueOf(endTime - startTime));
}
You can see the face contour points which the ML Kit API returns in the image below.
Sticker JSON Data Definition
Code:
public class FaceStickerJson {
public int[] centerIndexList; // Center coordinate index list. If the list contains multiple indexes, these indexes are used to calculate the central point.
public float offsetX; // X-axis offset relative to the center coordinate of the sticker, in pixels.
public float offsetY; // Y-axis offset relative to the center coordinate of the sticker, in pixels.
public float baseScale; // Base scale factor of the sticker.
public int startIndex; // Face start index, which is used for computing the face width.
public int endIndex; // Face end index, which is used for computing the face width.
public int width; // Sticker width.
public int height; // Sticker height.
public int frames; // Number of sticker frames.
public int action; // Action. 0 indicates default display. This is used for processing the sticker action.
public String stickerName; // Sticker name, which is used for marking the folder or PNG file path.
public int duration; // Sticker frame displays interval.
public boolean stickerLooping; // Indicates whether to perform rendering in loops for the sticker.
public int maxCount; // Maximum number of rendering times.
...
}
Make a Cat Sticker
Create a JSON file of the cat sticker, and find the center point between the eyebrows (84) and the point on the tip of the nose (85) through the face index. Paste the cat’s ears and nose, and then place the JSON file and the image in the assets directory.
Code:
{
"stickerList": [{
"type": "sticker",
"centerIndexList": [84],
"offsetX": 0.0,
"offsetY": 0.0,
"baseScale": 1.3024,
"startIndex": 11,
"endIndex": 28,
"width": 495,
"height": 120,
"frames": 2,
"action": 0,
"stickerName": "nose",
"duration": 100,
"stickerLooping": 1,
"maxcount": 5
}, {
"type": "sticker",
"centerIndexList": [83],
"offsetX": 0.0,
"offsetY": -1.1834,
"baseScale": 1.3453,
"startIndex": 11,
"endIndex": 28,
"width": 454,
"height": 150,
"frames": 2,
"action": 0,
"stickerName": "ear",
"duration": 100,
"stickerLooping": 1,
"maxcount": 5
}]
}
Render the Sticker to a Texture
We use the GLSurfaceView to render the sticker to a texture, which is easier than using the TextureView. Instantiate the sticker filter in the onSurfaceChanged, pass the sticker path, and start the camera.
Code:
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mTextures = new int[1];
mTextures[0] = OpenGLUtils.createOESTexture();
mSurfaceTexture = new SurfaceTexture(mTextures[0]);
mSurfaceTexture.setOnFrameAvailableListener(this);
// Pass the samplerExternalOES into the texture.
cameraFilter = new CameraFilter(this.context);
// Set the face sticker path in the assets directory.
String folderPath ="cat";
stickerFilter = new FaceStickerFilter(this.context,folderPath);
// Create a screen filter object.
screenFilter = new BaseFilter(this.context);
facePointsFilter = new FacePointsFilter(this.context);
mEGLCamera.openCamera();
}
Initialize the Sticker Filter in onSurfaceChanged
Code:
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.d(TAG, "onSurfaceChanged. width: " + width + ", height: " + height);
int previewWidth = mEGLCamera.getPreviewWidth();
int previewHeight = mEGLCamera.getPreviewHeight();
if (width > height) {
setAspectRatio(previewWidth, previewHeight);
} else {
setAspectRatio(previewHeight, previewWidth);
}
// Set the image size, create a FrameBuffer, and set the display size.
cameraFilter.onInputSizeChanged(previewWidth, previewHeight);
cameraFilter.initFrameBuffer(previewWidth, previewHeight);
cameraFilter.onDisplaySizeChanged(width, height);
stickerFilter.onInputSizeChanged(previewHeight, previewWidth);
stickerFilter.initFrameBuffer(previewHeight, previewWidth);
stickerFilter.onDisplaySizeChanged(width, height);
screenFilter.onInputSizeChanged(previewWidth, previewHeight);
screenFilter.initFrameBuffer(previewWidth, previewHeight);
screenFilter.onDisplaySizeChanged(width, height);
facePointsFilter.onInputSizeChanged(previewHeight, previewWidth);
facePointsFilter.onDisplaySizeChanged(width, height);
mEGLCamera.startPreview(mSurfaceTexture);
}
Draw the Sticker on the Screen Using onDrawFrame
Code:
@Override
public void onDrawFrame(GL10 gl) {
int textureId;
// Clear the screen and depth buffer.
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
// Update a texture image.
mSurfaceTexture.updateTexImage();
// Obtain the SurfaceTexture transform matrix.
mSurfaceTexture.getTransformMatrix(mMatrix);
// Set the camera display transform matrix.
cameraFilter.setTextureTransformMatrix(mMatrix);
// Draw the camera texture.
textureId = cameraFilter.drawFrameBuffer(mTextures[0],mVertexBuffer,mTextureBuffer);
// Draw the sticker texture.
textureId = stickerFilter.drawFrameBuffer(textureId,mVertexBuffer,mTextureBuffer);
// Draw on the screen.
screenFilter.drawFrame(textureId , mDisplayVertexBuffer, mDisplayTextureBuffer);
if(drawFacePoints){
facePointsFilter.drawFrame(textureId, mDisplayVertexBuffer, mDisplayTextureBuffer);
}
}
And that’s it, your face sticker is good to go.
Let’s see it in action!
We have open sourced the demo code in Github, you can download the demo and have a try:
https://github.com/HMS-Core/hms-ml-demo/tree/master/Face2D-Sticker
For more details, you can go to Our official website:
https://developer.huawei.com/consumer/en/hms
Our Development Documentation page, to find the documents you need:
https://github.com/HMS-Core
Stack Overflow to solve any integration problems:
https://stackoverflow.com/questions/tagged/huawei-mobile-services?tab=Newest
BackgroundThe ubiquity of the Internet and smart devices has made e-commerce the preferred choice for countless consumers. However, many longtime users have grown wary of the stagnant shopping model, and thus enhancing user experience is critical to stimulating further growth in e-commerce and attracting a broader user base. HMS Core offers intelligent graphics processing capabilities to identify a user's facial and physical features, which when combined with a new display paradigm, enables users to try on products virtually through their mobile phones, for a groundbreaking digital shopping experience.
ScenariosAR Engine and Scene Kit allow users to virtually try on products found on shopping apps and shopping list sharing apps, which in turn will lead to greater customer satisfaction and fewer returns and replacements.
EffectsA user opens an shopping app, then the user taps a product's picture to view the 3D model of the product, which they can rotate, enlarge, and shrink for interactive viewing.
{
"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"
}
Getting StartedConfiguring the Maven Repository Address for the HMS Core SDK
Open the project-level build.gradle file in your Android Studio project. Go to buildscript > repositories and allprojects > repositories to configure the Maven repository address for the HMS Core SDK.
Code:
buildscript {
repositories{
...
maven {url 'http://developer.huawei.com/repo/'}
}
}
allprojects {
repositories {
...
maven { url 'http://developer.huawei.com/repo/'}
}
}
Adding Build Dependencies for the HMS Core SDK
Open the app-level build.gradle file of your project. Add build dependencies in the dependencies block and use the Full-SDK of Scene Kit and AR Engine SDK.
Code:
dependencies {
....
implementation 'com.huawei.scenekit:full-sdk:5.0.2.302'
implementation 'com.huawei.hms:arenginesdk:2.13.0.4'
}
For details about the preceding steps, please refer to the development guide for Scene Kit on HUAWEI Developers.
Adding Permissions in the AndroidManifest.xml File
Open the AndroidManifest.xml file in main directory and add the permission to use the camera above the <application line.
Code:
<!--Camera permission-->
<uses-permission android:name="android.permission.CAMERA" />
Development ProcedureConfiguring MainActivityAdd two buttons to the layout configuration file of MainActivity. Set the background of the onBtnShowProduct button to the preview image of the product and add the text Try it on! to the onBtnTryProductOn button to guide the user to the feature.
Code:
<Button
android:layout_width="260dp"
android:layout_height="160dp"
android:background="@drawable/sunglasses"
android:onClick="onBtnShowProduct" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Try it on!"
android:textAllCaps="false"
android:textSize="24sp"
android:onClick="onBtnTryProductOn" />
If the user taps the onBtnShowProduct button, the 3D model of the product will be loaded. After tapping the onBtnTryProductOn button, the user will enter the AR fitting screen.
Configuring the 3D Model Display for a Product1. Create a SceneSampleView inherited from SceneView.
Code:
public class SceneSampleView extends SceneView {
public SceneSampleView(Context context) {
super(context);
}
public SceneSampleView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
}
Override the surfaceCreated method to create and initialize SceneView. Then call loadScene to load the materials, which should be in the glTF or GLB format, to have them rendered and displayed. Call loadSkyBox to load skybox materials, loadSpecularEnvTexture to load specular maps, and loadDiffuseEnvTexture to load diffuse maps. These files should be in the DDS (cubemap) format.
All loaded materials are stored in the src > main > assets > SceneView folder.
Code:
@Override
public void surfaceCreated(SurfaceHolder holder) {
super.surfaceCreated(holder);
// Load the materials to be rendered.
loadScene("SceneView/sunglasses.glb");
// Call loadSkyBox to load skybox texture materials.
loadSkyBox("SceneView/skyboxTexture.dds");
// Call loadSpecularEnvTexture to load specular texture materials.
loadSpecularEnvTexture("SceneView/specularEnvTexture.dds");
// Call loadDiffuseEnvTexture to load diffuse texture materials.
loadDiffuseEnvTexture("SceneView/diffuseEnvTexture.dds");
}
2. Create a SceneViewActivity inherited from Activity.
Call setContentView using the onCreate method, and then pass SceneSampleView that you have created using the XML tag in the layout file to setContentView.
Code:
public class SceneViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
}
}
Create SceneSampleView in the layout file as follows:
Code:
<com.huawei.scene.demo.sceneview.SceneSampleView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
3. Create an onBtnShowProduct in MainActivity.
When the user taps the onBtnShowProduct button, SceneViewActivity is called to load, render, and finally display the 3D model of the product.
Code:
public void onBtnShowProduct(View view) {
startActivity(new Intent(this, SceneViewActivity.class));
}
Configuring AR Fitting for a ProductProduct virtual try-on is easily accessible, thanks to the facial recognition, graphics rendering, and AR display capabilities offered by HMS Core.
1. Create a FaceViewActivity inherited from Activity, and create the corresponding layout file.
Create face_view in the layout file to display the try-on effect.
Code:
<com.huawei.hms.scene.sdk.FaceView
android:id="@+id/face_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:sdk_type="AR_ENGINE"></com.huawei.hms.scene.sdk.FaceView>
Create a switch. When the user taps it, they can check the difference between the appearances with and without the virtual glasses.
Code:
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/switch_view"
android:layout_alignParentTop="true"
android:layout_marginTop="15dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd ="15dp"
android:text="Try it on"
android:theme="@style/AppTheme"
tools:ignore="RelativeOverlap" />
2. Override the onCreate method in FaceViewActivity to obtain FaceView.
Code:
public class FaceViewActivity extends Activity {
private FaceView mFaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_face_view);
mFaceView = findViewById(R.id.face_view);
}
}
3. Create a listener method for the switch. When the switch is enabled, the loadAsset method is called to load the 3D model of the product. Set the position for facial recognition in LandmarkType.
Code:
mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mFaceView.clearResource();
if (isChecked) {
// Load materials.
int index = mFaceView.loadAsset("FaceView/sunglasses.glb", LandmarkType.TIP_OF_NOSE);
}
}
});
Use setInitialPose to adjust the size and position of the model. Create the position, rotation, and scale arrays and pass values to them.
Code:
final float[] position = { 0.0f, 0.0f, -0.15f };
final float[] rotation = { 0.0f, 0.0f, 0.0f, 0.0f };
final float[] scale = { 2.0f, 2.0f, 0.3f };
Put the following code below the loadAsset line:
Code:
mFaceView.setInitialPose(index, position, scale, rotation);
4. Create an onBtnTryProductOn in MainActivity. When the user taps the onBtnTryProductOn button, the FaceViewActivity is called, enabling the user to view the try-on effect.
Code:
public void onBtnTryProductOn(View view) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this, new String[]{ Manifest.permission.CAMERA }, FACE_VIEW_REQUEST_CODE);
} else {
startActivity(new Intent(this, FaceViewActivity.class));
}
}
ReferencesFor more details, you can go to:
AR Engine official website; Scene Kit official website
Reddit to join our developer discussion
GitHub to download sample codes
Stack Overflow to solve any integration problems
Does it support Quick App?
Hello sir,
from where i can get the asset folder for above given code(virtual try-on glasses)
Mamta23 said:
Hello sir,
from where i can get the asset folder for above given code(virtual try-on glasses)
Click to expand...
Click to collapse
Hi,
You can get the demo here: https://github.com/HMS-Core/hms-AREngine-demo
Hope this helps!