Readini log templet

How Metroid Prime has become one of my all time favorite childhood games on the Nintendo Gamecube.

2024.05.14 05:15 CyberShogunOP How Metroid Prime has become one of my all time favorite childhood games on the Nintendo Gamecube.

So my mom recently bought me Metroid Prime Remastered for the Nintendo Switch about 2 days ago and I have to say that the game is as incredible as I remember it playing as a kid on my original Gamecube. The updated visuals really compliment the game well especially given the fact that even the original 2002 graphics have aged surprisingly well even by today's standards.
Metroid Prime is easily one of the best original Gamecube games of all time right next to Resident Evil 4, Pikmin 2, Super Smash Bros Melee and Legend of Zelda Windwaker. The game is the best due to it's epic, fun and fast paced combat, beautiful, dynamic and unique environments spread throughout the alien world of Tallon IV, lots of collectibles to find throughout the game's vast open world and a rich and complex story which is told through walls of text which the player must find through scanning Chozo templets and Pirate Data logs with the scan visor.
For anyone who hasn't yet played or ever bothered reading all of story logs in order to dig deeper into the story of the game I will going over a brief yet detailed description of the games main story so spoilers ahead.
In the reaches of space a bounty hunter known as Samus Aran is seen boarding onto a large space station known as the frigate orpheon which is home to the space pirates. A group of highly advanced, reptilian like extra-terrestrial beings who are similar to the predators/yautja from the predatoavp franchise and are hellbent on taking over the galaxy. After entering the space station Samus discovers that things have gone horribly wrong and many of the space pirates are weak and dying due to them doing experiments on various different life forms with a blue mutagenic substance known as Phazon which would cause the creatures to eventually turn against their masters. After Samus defeats a giant insect like parasite creature it falls into the reactor core causing the place to become unstable and thus forcing her to evacuate. Samus is then encountered by Ridley who has undergone cybernetic reconstruction after his first defeat with the bounty hunter back on Zebes. After Samus escapes the space station on her spaceship she follows her target on the alien homeworld known as Tallon IV. Having lost track of her old arch enemy Samus is forced to explore the vast world and recover her abilities she lost after being hit by an explosion back on the frigate orpheon. As Samus uncovers all of the deep dark mysteries of Tallon IV she soon discovers that the planet was once a peaceful world home to the Chozo. A bird like alien race which are responsible for raising the young bounty hunter from childhood and have since become extinct and now exist as evil spirits that roam the depths of the Chozo Ruins after a meteorite containing the mutagenic substance which the Chozo refer to as the great poison collided into Tallon IV's surface causing it kill and mutate any life it comes in contact with into hideous monstrosities. Leaving the planet infected and in danger of being consumed by the mutagenic ooze The Chozo lock the great poison away in an impact crater that can only be accessed through finding 12 artifacts which are the key to finding and destroying the source responsible. 50 years later It is now up to Samus to regain and obtain new abilities in order to save Tallon IV from being consumed by the Mutagenic Ooze bent on corrupting and consuming all life in the galaxy.
submitted by CyberShogunOP to Metroid [link] [comments]


2024.04.23 04:32 bigboolean Anyone come across this error?

I just tried logging in like usual and I got an error I've never seen before several times in a row just a few minute ago.
submitted by bigboolean to outerplane [link] [comments]


2023.08.26 17:11 Jazzlike-Ostrich Second Universe Tales: The Origins: Reptile's beginning

Fifth Era
3.000 Million Years before "modern" Second Universe times.
Much of the First Planet is covered in large swamp forests.
Here nothing is as it seems.
The one kilometers giant plants towering over this water world may look like trees, but they're actually distant relatives of ferns.
Even the air is alien compared to most planets today. Over a third is oxygen, much higher than any other time in the lifespan of the First Planet.
This oxygen rich atmosphere has fuelled the growth of new, supersized arthropod predators.
Jumping on top of a tree was a fearsome creature, a mixture between a dragonfly and a spider.
This Megarachnea spider is the size of a limousine. She'd be hunting mammoths if she was alive today.
She's an ambush predator, operating from her headquarters on one of the giant plants. She had created an entrance on one of the plants, and now waited.
Safe in her nest, she rests her feed in carefully constructed tripwires extending all the way to the base of the plant.
This allows her to pick up vibrations from the outside world.
As she waits, an opportunity ventures near her burrow.
It was a 9 meters long reptile, with large eyes and many small, pointed teeth.
This Hylostegus is hunting on the forest floor.
Unlike it's amphibian ancestors, he has tough, scaley skin, which traps moisture inside his body, vital for all land dwellers.
Because it doesn't dry out in the sun, he can venture away from water.
But that means encountering new predators.
Inadvertently, the Hylostegus stepped on one of the wires at the base of the plant, with the Megarachnea diving at full speed to catch it.
Barely dodging the attack, the Hylostegus fled for his life, chased by the flying spider.
At the last second, the Hylostegus managed to take cover from the powerful predator, hiding inside the rotten remains of a giant plant.
The reptile has outrun the spider.
He has evolved a complex heart, much more efficient than his enemies, in fact the templet for all modern vertebrates. It's a powerful pump, that pushes oxygen and blood around his body to his muscles, so he can run at high speed without having to stop for a rest.
But now, he's trapped inside a log. Outside, the Megarachnea tried to break inside to catch her prey.
At first the spider armour stops her from squeezing in. But she's not going to give up so easily.
Taking advantage of an opening on the top of the log, the Megarachnea dived at full speed at its prey, using its powerful jaws to kill the unfortunate Hylostegus.
Back in her lair, Megarachnea would inject her victims with digestive juices, dissolving them from the inside.
But as the spider dragged her victim to her lair, she soon found out that the plant where her nest was located had been cut in half with surgical precision.
Not too far is the creature responsible. A massive arthropod resembling a giant scissor.
This is one of the most peculiar arthropods of the First Planet: a Forbicid, a powerful, flying arthropod the size of a house that has evolved to fly by expelling excess air from its carapaceon.
This is an herbivore, using its sharp, scissor like mandibles to cut down large plants and feast on their lymph.
The Megarachnea is now forced to find another suitable plant where to make a new home.
And once outside, she's vulnerable to even larger predators.
Descending from the air, another Forbicid, smaller and resembling a plier, grabbed the dead Hylostegus, consuming it with ease.
Forbicoraptor is a fearsome predatory Forbicid, queen of the Fifth Era skies. With a length of almost 20 meters, she's the size of a sperm whale, with an appetite to match.
High above the Fifth Era kingdom, normally she's invincible. But trouble's brewing.
A storm is approaching. The super oxygenated atmosphere, which has helped fuel the growth of the insects and arthropods, is highly volatile. A lightning strike could trigger an explosion.
The clock is ticking for the swamp.
Xxxxxxx
Below, a group of large creatures is enjoying the large quantity of water of the swamp.
They had a very long and slender body, with small and feeble limbs, and large jaws with powerful fangs.
These are Pholidoderpetons, 34 meters long amphibians.
They have continued to thrive in the last 600 million years.
Their thin skins still restrict them to the water's edge, but they're now powerful predators, with a devastating pair of jaws, ready to ambush anything that wonders within reach.
Xxxxxxx
The homeless spider tries her luck further inland, but other Megarachnea fill the nearby giant plants, and they don't like to share.
But as the spider kept on searching, she barely managed to dodge the attack of a giant.
It was a massive, armoured millipede, with large horns on the side of the head in the shape of a boomerang.
This giant, Diplopleura, doesn't like to share either.
He's a distant relative of modern millipedes, but as long as a tower crane. He could rear up, tall enough to look a person in the eyes if they stood at the top of a lighthouse.
Although he's vegetarian, its strong jaws can deliver a nasty bite.
As the Megarachnea flew away, the Diplopleura moved to its usual grazing grounds.
But with the rising waters, Diplopleura's foraging brings him into dangerous territories.
A group of Pholidoderpetons charged in, trying to kill the giant arthropod.
All tried to bite the giant millipede, with little success.
In this clash of the titans, the arthropod armour is his best defence.
Using its powerful jaws, the Diplopleura grabbed one of the Pholidoderpetons, crushing their skulls in seconds.
The rest of the group realizes they have little hope of tackling this giant. Not that it matters; Pholidoderpetons are not fussy eaters.
Their dead companion will provide a feast.
Xxxxxxx
Meanwhile, the lightning storm is building.
Just in time, the spider finds another giant plant.
Emerging from a hole on the side of the plant, an Hylostegus is evicted, but reptiles don't need nests to avoid danger. They have speed and stamina on their side.
Meanwhile the spider starts to turn the hole into her hunter's lair.
Xxxxxxx
Night falls.
And the Megarachnea settles into her new silk covered home.
She test the new tripwires. They're already picking up vibrations from outside.
The storm is very close now.
Lightning strikes light up the oxygen rich air.
The Forbicoraptors are forced down from the canopies to seek shelter below.
An unexpected bounty for the water predators below, as the Pholidoderpetons jumped out of the water to grab as many as possible.
Among the chaos, Megarachnea seems safe in her nest.
But luck is not on her side. One of the lightning strikes hits the plant she's residing in, with deadly precision.
Xxxxxxx
A huge fire, ignited by lightning, has devastated Megarachnea's neighbourhood. There are no signs of life above ground.
However a Hylostegus has managed to outrun the flames, and heads towards the spider's lair, now collapsed to the ground.
Megarachnea's hole was at the centre of the lightning strike, frying her on the spot.
The reptile gets a spider barbeque.
The era of the giant bugs is coming to an end for the First Planet.
The climate is drying and the air is losing oxygen. The monster insects and spiders can't survive the change.
Xxxxxxx
I hope you guys enjoyed this new chapter! Please review so I can know your opinion. I'm willing to accept suggestions for what is going to happen, so stay tuned! Also, remember to like and follow, if you want!
See you to the next update!
submitted by Jazzlike-Ostrich to TheSecondUniverse [link] [comments]


2023.06.06 01:01 lolipopghost Window->Glyphs for special characters

Window->Glyphs for special characters
PSA for custom card making: if u don’t have a numpad, in photoshop you can go windows -> glyphs to find all the characters! I was looking all over the internet for a solution to this!
submitted by lolipopghost to FourSouls [link] [comments]


2023.04.27 21:04 Mig_The_FlipnoteFrog What's the true philosophy of frutiger aero and the utopic future that it envisioned

Hi, i'm getting deeper in the frutiger aero and aesthethic rabbit hole but something that i never quite understand is the future that it envisions, i think that it it's a future that humanity managed to solve poverty, social inequality, hunger, inequality between countries and areas with different climates (at the point that basically every city in the world looks the same futuristic developed eco city with a shit ton of skycreepers, access to some kind of water corpse like the sea, a lake or river and stable climate you'd see in a country like denmark or canada). global warming, logging, global peace (at the point that i think it envisions a future with the world being united as one single country) and everything that makes the present so bad while still using capitalism as most frutiger aero is used especially now exclusevely as corporate design for cleaning products and corporate eco powerpoint templetes and i think the frutiger aero future doesn't has poverty because it never really shows it and shows cities with tons of skycreepers and no surburbs but i think it might envision a socialist world because the words "solving poverty, social inequality and hunger" while using a system that basically promotes these things to make the rich more rich sounds impossible but what do you think
submitted by Mig_The_FlipnoteFrog to FrutigerAero [link] [comments]


2022.12.09 13:12 aaspider Week 53 Update Info - One Year of Icarus & Data Decentralization

https://store.steampowered.com/news/app/1149460/view/3611354355089820956
Icarus Week Fifty Three Update One Year of Icarus & Data Decentralization
Data Decentralization is here along with our Dedicated Servers Beta. Plus we look back on 52 weeks of updates.
Happy One Year Anniversary! Today marks a year since the launch of Icarus and the 52 updates we’ve made to the game every single week since. We’re excited to celebrate it by giving power back to the players with our player data decentralization patch.
This week, all data will be migrated to players' local computers, shifting away from a reliance on cloud providers, allowing some new features and ensuring the player community can own their game data permanently. This opens the door for many more features and changes, including characters now being able to be used across multiple sessions simultaneously, the new Orbital Exchange Interface for Exotic extraction, and our Dedicated Servers Beta.
This is a big update and will require a full data migration upon launch of the patch, so have a read through all the details below.
Once you’re briefed on the changes, we’ve included a reflection on 52 weekly updates to Icarus, including a word from our game runner, Rocket, on this incredible journey and what’s to come.
Data Decentralization & Migration This week, we are releasing the highly anticipated data decentralization change.
This is a large update, requiring a migration process that will occur the first time you log in after the patch. However, for many players, it may not change how you play Icarus at all. None of your data, characters or gear will be lost - we’re moving where it is stored.
Going forward, all player data will be stored locally - on your PC. Previously, save files and player data were saved in the cloud, while everything else (including your Outposts and Open World games) was saved locally. Now, all data will be saved locally, shifting data ownership to the players, and moving away from the ‘game-as-a-service’ model which can leave us open to internet outages and can limit customization.
We see this move as putting the power back in the players' hands, giving them true ownership of the product. While this comes with some concessions, it’s a truer representation of the relationship we want to build between ourselves and the players, where you own what you buy without strings attached.
Migration will combine your offline and online characters and account data into a single entity. This includes loadouts, inventories, exotics, ren and skill refund tokens. It will also combine your mission progress and workshop talents, so players who have played both Offline and Online will see a much more saturated environment and may want to spend some time organizing their account.
All currently active Missions will be reset and not migrated over, and current progress on these missions will be lost. Characters and gear will not be lost. Characters and loadouts will be returned to your select screen, but you will have to restart any prospects you are currently in.
We have added a new branch on Steam called ‘Centralized’ which will hold the last 1.2.27 Update in case players want to bring their characters out of missions etc. This will not be present forever and will be removed in the following weeks.
This migration will also migrate over your Open World and Outpost sessions, but will reset and remove your characters from these missions in the process. You’ll find your characters and their loadouts in the character select screen, and can rejoin game via their dropship.
Steam Cloud has been enabled for Icarus, so if you have multiple computers on which you play Icarus, make sure you migrate on your preferred machine first (the one with the most up-to-date Outpost and/or Open World content). Steam should then sync it to your other machines.
We very much see this patch as providing players ownership over their own data and enabling everyone to play without having to have access to our servers. To enable this we had to make some concessions on various gameplay elements but it also allows us to explore new options and provide new levels of customization and persistence that have not been available before. It has been a massive effort from the team to pull this through and they have done a fantastic job. I want to thank everyone who has been with us over the last year providing feedback, enjoying the game and being patient throughout the issues we have had and hope you will join us for the next year as we continue to develop Icarus.
Jake Dodunski, Project Lead
A Multiplayer Hosting Change
Icarus will continue to have the peer-to-peer multiplayer it has always had, where one player acts as the host for their Steam friends - but with one change. That original host must always be online.
From now on the player who initially created the mission will be the only one able to resume it. Other players will not be able to carry on or launch a mission that another player has started, as this save data is now stored on the initial host’s hard drive rather than in the cloud. This is the same way that Outposts and Open World have functioned since their launch, so that experience won’t be entirely foreign to many of you.
It’s important to note that the host should always be the last person to leave a prospect. This way, players are guaranteed to be able to recover their gear and claim any rewards/exotics as they will be unable to launch the mission later (however, we now grant rewards immediately during missions to help).
If you want a way to play anytime regardless of where the original host is, then we’ve introduced Dedicated Servers to cater for you (see below).
Previously, Icarus had a very helpful feature that migrated the hosting between players when the original host left the game. While this feature won’t exist in the new data decentralized model, there is still a way to manually share saves with each other so you can continue someone else’s prospect while they aren’t online. You can find your saves in your file explorer at:
C:\ > Users > (your profile) > AppData > Local > Icarus > Saved > PlayerData > (your Steam ID) > Prospects
or
%LocalAppData%/Icarus/Saved/PlayerData/[SteamId]/Prospect
Steam ID with your 17 digit number, read more from Valve about how to locate this
From here, you can share them with your friends, but be aware that once a file has been activated, you’ll need to have the most recent version shared back to you to be able to continue it where they left off.
Gameplay Changes
Alongside this change, there are a few new features that provide a more seamless experience and take advantage of the new localised data: * The new Orbital Exchange Interface is a planetary-crafted deployable that when activated, allows you to call a drop ship down to extract your exotics up to the space station. This means you no longer need to take them up in your dropship with you on completion of your prospect. * Mission rewards are now granted immediately on completion of the mission, rather than sent to your inbox in orbit. * Characters are no longer ‘locked’ to one Mission or session and can be used on multiple active sessions simultaneously. You can select any character from the character select screen for any session at any time. * Insurance now only insures your items, as characters can’t be lost on prospects. If you do not bring your items up with you in a dropship, they stay on planet until returned. If you have insurance, you can reclaim your items after 5 real-time days from the menu. * Workshop items are no longer ‘auto-repaired’ when you return them to space. You will now have the option to repair them for 10 ren in the inventory, or on the surface using the new Tier 3 repair bench.
Dedicated Servers Beta
Decentralization opens the door for Dedicated Servers, which we are launching in Beta today.
Dedicated Servers let you host your own Icarus server to play with friends. You can control access, timing, hardware and in future customize your settings.
It is a new way to play Icarus multiplayer, but is not compulsory. You can still continue to play Icarus multiplayer without a dedicated server as described above.
If you are interested in setting up and running your own (beta) Icarus dedicated server, you can access our setup guide on github here. We will be partnering with a range of dedicated server providers to offer rental servers, so stay posted for news and info on who these are.
This application is still in Beta, so we imagine we’ll have some teething issues as we work through scaling this up to full capacity. To support this, we have a special discord channel #dedicated-server-beta where you can engage directly with our team on any issues that arise. Click here to join.
52 Weeks of Updates
After releasing Icarus back in December 2021, we quickly shifted our attention to how we could keep innovating, improving and adding to the game. Weekly updates became our approach, focusing on consistently improving and optimizing the base game while expanding the playable content and adding new ways to play to provide an experience regardless of how you enjoyed Icarus.
During this time we’ve released some big updates, small ones and everything in between. Some of our more memorable updates included:
Looking back, the work we’ve done has been quite the journey. The Icarus we launched was a different game than it is now. We’ve tripled the available missions, added an entire second map, new game modes, new dynamic features, new deployables, craftables and fixed thousands of bugs in this time. In this time, our players have invested over 34 million hours in-game, a number that still blows us away to this day.
One Year of Icarus
Releasing ICARUS has been the studio's coming of age. As I've mentioned before the Beta weekends last year, prior to our release, were a mixed blessing. On one hand, it demonstrated a significant ground of players eager for our content - but it also outlined problems with both the concept as well as the game itself.
Most of all, the beta weekends crystalized what the game needed to be very effectively, helping end any uncertainty about what the game needed to be on the development front. You can think of the beta weekends as lighting a fuse on an explosive, it could only last a finite time before it needed to end. Our studio has a long and strong history of not crunching our project, but short iteration cycles during the beta week was exhausting for our team. Not to mention outages out of hours placed additional pressure.
The launch proper was rocky as well because we had made so many changes in the final beta weekend that it had become impossible within that last week to properly test the breadth of the changes in the game in a 'real' environment with large players. That came with the launch. After such a rocky launch we focused on two things:
It was really hard, but I'm really proud to say the team did both of those and done so with aplomb. The initial weeks were hard as the team scoped as much as possible into every update, but eventually we learned to keep the scope measured and portion out the work in smaller, more manageable, and consistent ways. We changed our build processes to bring the builds out earlier, and worked with our fantastic community members (particularly on discord), who would give excellent feedback. This feedback extended far beyond traditional testing - providing real "boots on the ground" information around balance.
Each weekend we would be fortunate to see a number of content creators who stuck with the project from the start. Most of them I would say have at times (and continue to be) quite critical of the project. This has played a very important role in the game getting to where it is today. They've asked tough questions, and pointed out our mistakes or missteps. This has helped the team and studio to grow.
This update brings us to the point we move away from that traditional "game as a service" or "live service" model. When we first announced this there was some pushback and concern, I hope we have done well at explaining why this is important for the longevity for the game. We do not want the game to be reliant on the studio. As a game creator I think the best outcome for me would be if people continue playing the games I make for long after I am not there to work on them. This is an important step on that path.
The addition of dedicated servers, and the decentralization of the data, also also the community to do further work to pull the game a part and make mods and conversions for the game. They allow our team to make changes that were impossible before. They provide resilience - removing the requirement to support a complex (and expensive) back end.
I know we haven't always done the right things, and we haven't always been as fast as you (or we!) would like at fixing these mistakes - but we thank you for being here with us nevertheless. We're excited for the future of ICARUS. I hope you are as proud of the team as I am. It's been a heck of a twelve months, and their work on the game is a testament to their resilience. We watch your videos. We read your reviews. We look at your posts. We talk with you on the discord. Together, I'm confident we've reached a point we can really build ICARUS into a game we all want.
Dean Hall, CEO
Changelog v1.2.28.105394
New Content
Fixed
Future Content
submitted by aaspider to SurviveIcarus [link] [comments]


2022.07.27 18:21 radael Stream Frequently Asked Questions and please, ask about the players suffering with motion sickness, headache and dizzyness with Cnidarian and Kuumarke abilities effects

Stream Frequently Asked Questions

Wall of text incomming:
I went trough TheSajuukKhar Dev streams transcripts of 2022, and found those questions were asked almost every stream. The question about DSC Andorians was asked and answered the most. I am posting them here to inform those who don´t watch them, or those who want to ask them again. Posting them, I hope unanswered questions to have more chance to get an answer.
The post will have mistakes, I will try to fix them and I will try to add suggestions of questions and answers. Those questions and answers are not exact, they are a generalization, but they represent the overall idea, and I will be happy to try to correct mistakes/misinterpretations.

Also, Kuumarke set and Cnidarian console have upped the quantity of posts about motion sickness, headache, dizzyness and general unhappiness with the visual spam overload.

I hope this FAQ help us players by avoiding repeated questions and open space to non-repeated questions
Q: Why can´t we fly a Borg Cube? We can fly round ships as Lukari and now the Cnidarian
A: They say they have not found a way to make the make the cube show in a good way what side is the front, or the back. The other issues other than front/back is Cubes don't bank, and they don't actually have a front, as in the cube doesn't turn to face a ship in Startrek, it just changes direction without turning.
Q: Why can´t we have a Terran Faction?
A: They say playing as villains is not that popular, they learned that from Champions Online where villains were not popular. Also, Terrans would do really mean things against the overall spirit of Star Trek
Q: Why can´t we have more bridges?
A: Bridges don´t sell well for the ammount of effort spent on them
Q: Why the episodes taken off for remaster were not remastered?
A: There was not enough time/a reason with monetization to push more resources to release them
Q: Why don´t you get rid of lockboxes and sell all things for zen?
A: A ship from a lockbox give at least "a magnitude" more of money than selling the same ship at Zen Store. A magnitude/order is often 10x
Q: If last years were "banner" years, why don´t you hire more employees?
A: They currently have more employees than at the time before they closed the Magic the Gathering game. The current STO team is between 30-40 people
Q: A ship/uniform/weapon/thing appeared appeared in yesterday´s episode, when we will get it in game?
A: It will take months to they to put in game, sometimes more than a year. They plan content ahead for months to give time to artists, also, they need pre-release info from CBS to them a heads on about what will happen. Most of the times, CBS leave them in the dark as much as the fans for the surprise element.
A: Why there are more Federation shps than the other factions, now that we have cross faction fly?
Q: They are doing more ships from other species than before, but federation ships sell much better
Q: Why are special effects so flashy and unable to be turned off?
A: Not enough time or an easy way to do a toggle on/off for it now, they have the opinion that when a player get a new ship/console/power they want to feel good watching it work
Q: Why there are no Enterprise Era content/ships?
A: Nothing new done about that era on official shows/movie lately, other eras are more popular.
Q: Why we did not get Protostar yet?
A: Nickleodeon owns the design, the company and the show are of a different parental/viewer rating than STO. They are negotiating if they can use the Protostar but seems the rating is a bit of a problem.
Q: Sometheing happened on last episode of X series, it will break the timeline!
A: If something that really breaks the timeline of the game, we will adapt it somehow, so far nothing really broke it
Q: Why can´t we get actor XYZ?
A: Usually is time or money. Patrick Stewart is usually too busy to record.
Q: Why don´t we get more fleet holdings?
A: Currently they think there are enough holdings, and it the effort to do one does not reward enough, from TFW 5/4/22, doing a new fleet holding would mean no new content for two seasons. No new missions, no revamps, lowered ship releases, using the old templets of what they would add in a fleet holding
Q: Why don´t we have a new reputation?
A: Currently they think there are enough reputations, and it the effort to do one does not reward enough
Q: Why don´t you do "this idea" for an arc?
A: They don´t read player ideas for arcs so they don´t get into intellectual property problems. They said they maybe might read ideas for ships
Q: Lots of people in chat/reddit/forums are talking/wanting this, why don´t you do it?
A: They use metrics from inside the game, as what ships are being played more, what weapons are played more. One of things they measured is that a significative part of the players only log in when new stories are released. Metrics from inside the game are sometimes different/more accurate than post metrics.
Q: Can we get Jupiter map for a social zone? Or a new social zone in Andoria/Vulcan/Gamma Quadrant, etc?
A: TFW 7/13/22 There's a lot of social zones already, and its a lot of work to make even an existing map into a social zone.
Q: What is the Elite Boff Token?
A: TFW 7/7/22 The Elite BOFF Token, which Kael can't talk about because it hasn't been officially announced, was supposed to launch several times now, but theres a few kinks left to work out with it
Latest Forum questions from Q&A link: https://www.arcgames.com/en/forums/startrekonline#/discussion/1267506/july-developer-q-a-thread/p1 from TheSajuukKhar
Q: What is the philosophy behind restricting characters to certain uniform options based on location or faction? In a Star Trek theme park style game, I would love to put my Captains and Bridge Officers in any outfit.
A: Lead Character Artist, Ian Castaneda: Part of the issue is time. Not all costume parts will mix with other costume parts simply because of fitment, size, bulkyness, tiling textures, etc. It's not simply a case of moving a few edges and suddenly the costume piece works with every other costume piece. It would often require much more time, to allow it to fit with other costume pieces. That is why we generally try to make costume parts mixable to a limited degree - which is doable within our limited amount of time. But in some cases, the costume piece (and the rest of that piece's costume set) doesn't work well when being mixed. In those cases, we create a limited category where the costume is not customizable or is very limited. While we do strive to allow the player to customize their costume, there are time constraints that we have to deal with.
Q: Is it possible to open up the color palletes for all uniforms and clothing? Space Barbie is the true end game, but some of the clothing choices (especially those for Klingons and Romulans) are stuck with very drab pallettes. We would love to be able to choose any color for any uniform.
A: Lead Character Artist: Ian Castaneda: Giving the ability to allow any color on any costume part: The costume customization system is currently in a state where this is not possible, and we would require some additional Software Engineering support to be viable.
Other answers:
TLDR: Read to see if they already answered your question. Please if possible ask about visual spam giving players sickness.
submitted by radael to sto [link] [comments]


2022.07.21 14:41 WinnerPristine6119 No table to create upload functionality.

I know a lot of you guys would ask for stackblitz but i'm a total noob to angular.
I'm facing a major problem here i need to create a upload form and i'm stuck here.
My code is as follows:
Html part:
  
Here is the component part:
uploadTemplatehere(event: any){ console.log(event.target.files.item(0),"upload template event",event.target.files[0]); this.filename = event.target.files[0].name; this.loader.open(); this.routesArray = []; this.uploadEvent = event; if (event.target.files.length > 0) { this.fromLoc = this.exampleForm.get('startingSource').value; this.toLoc = this.exampleForm.get('Destination').value; this.routeName = this.exampleForm.get('routeName').value this.exampleForm.get('fileUpload').setValue(event.target.files[0]) const formData = new FormData(); formData.append("company_id", this.branchid); formData.append("route_name", this.routeName); formData.append("from_location", this.fromLoc); formData.append("to_location", this.toLoc); formData.append("uploadfile", this.exampleForm.get('fileUpload').value); console.log(this.fileUpload0, "files upploaded1"); let req ={ "route_name": this.routeName, "company_id": this.branchid, "from_location": this.fromLoc, "to_location": this.toLoc, "uploadfile": this.files, }; this.jrmservice.loadingTemplate(formData).subscribe((e)=>{ console.log(e); console.log("route res-----===",e); this.bookingsenddata=e; }); 
Here is the Service file part:
const HttpUploadOptions = { headers: new HttpHeaders({ "Content-Type": "multipart/form-data" }) }; public loadingTemplate(formData){ return this.http.post(ANALYSIS_URL8+`/jrm/upload_jrm_route`,formData,HttpUploadOptions); } 
The error i get :

core.js:4442 ERROR DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string. at EmulatedEncapsulationDomRenderer2.setProperty (http://localhost:4200/vendor.js:94135:18) at BaseAnimationRenderer.setProperty (http://localhost:4200/vendor.js:39502:27) at DefaultValueAccessor.writeValue (http://localhost:4200/vendor.js:8454:24) at http://localhost:4200/vendor.js:10627:27 at http://localhost:4200/vendor.js:11655:50 at Array.forEach () at FormControl.setValue (http://localhost:4200/vendor.js:11655:28) at JrmUploadComponent.uploadTemplatehere (http://localhost:4200/views-jrm-upload-jrm-upload-module.js:242:48) at JrmUploadComponent_Template_input_change_40_listener (http://localhost:4200/views-jrm-upload-jrm-upload-module.js:361:159) at executeListenerWithErrorHandling (http://localhost:4200/vendor.js:73732:16) 
What should i do to make the form work.
(The reason i'm not posting the URL is because the API is having AUTH_GUARD which makes it hard to give you guys to work )
submitted by WinnerPristine6119 to angular [link] [comments]


2022.05.10 17:31 MishMish8 windows server local user managment and group policies

Hi, If im administrator and i have a few users on the local machine , how can i control them? How to change thier configurations or give and take permissions?
I did changed the background wallpaper in group policies (user config./admin.templetes/desktop) and it didnt worked the wallpaper is now black/blank, i dont understand how it works in order to get it right
What will happen to the permissions if i change a users name? Or if i create a user with the same name?
I was asked to make a user log off when he logs on, that could be funny trolling but i didnt know how to do it and i want to make sure i know how to revert it before i try
submitted by MishMish8 to techsupport [link] [comments]


2022.05.10 17:26 MishMish8 windows server questions on local users managment

Hi, If im administrator and i have a few users on the local machine , how can i control them? How to change thier configurations or give and take permissions?
What will happen to the permissions if i change a users name? Or if i create a user with the same name?
I was asked to make a user log off when he logs on, that could be funny trolling but i couldnt do it and i want to make sure i know how to revert it before i try
I know this info is out there, but i just couldnt find answers and im experimented on an non activated windows server 2019
I did changed the background wallpaper in gpedit.msc (user config./admin.templetes/desktop) and it didnt worked the wallpaper is now black/blank, but i'd love to understand more about group policies and how it works?
submitted by MishMish8 to WindowsHelp [link] [comments]


2022.05.05 09:34 TheSajuukKhar Ten Forward Weekly 5/4/22

submitted by TheSajuukKhar to sto [link] [comments]


2021.10.01 09:24 lokeshsuryan Beginner: Integration of Camera service in Harmony OS

Beginner: Integration of Camera service in Harmony OS

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover Camera device with Java in Harmony OS.
The HarmonyOS camera module enables your application to provide camera functions. You can access and operate the camera device and develop new functions through the open APIs. Common operations include preview, photographing, burst photographing, and video recording.

Basic Concepts

  • Static camera capability
A series of parameters used to describe inherent capabilities of a camera, such as orientation and supported resolution
  • Physical camera
A physical camera is an independent camera device. The physical camera ID is a string that uniquely identifies a physical camera.
  • Logical camera
A logical camera is the abstracted capability of many physical cameras and centrally controls these physical cameras to implement camera functions, such as wide aperture and zooming. A logical camera ID is a unique character string that identifies the abstraction capability of multiple physical cameras.
  • Frame capture
All actions of capturing frames after a camera is started, including single-frame capture, multi-frame capture and looping-frame capture.
  • Single-frame capture
This function captures one frame in the frame data stream transmitted after the camera is started. It is frequently used for photographing.
  • Multi-frame capture
This function repeatedly captures multiple frames in the frame data stream transmitted after the camera is started. It is frequently used for burst photographing.

Development Overview

You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • DevEcho studio installed.

Follows the steps.

  1. Create Harmony OS Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select Empty Ability(Java) template and click Next as per below image.

https://preview.redd.it/s1ghdhj6hsq71.png?width=689&format=png&auto=webp&s=534eb37e1c18010ab7f97ebd000354222b3824dd
  • Enter Project Name and Package Name and click on Finish.

https://preview.redd.it/fw23x7c8hsq71.png?width=685&format=png&auto=webp&s=edde59970baf371820d39fa3d0af5de1faa37e1d
2. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.

https://preview.redd.it/dzs30igahsq71.png?width=602&format=png&auto=webp&s=5f5d5e620daae4e14569b9f1e701a81ae72381f8
  1. Add the below maven URL in build.gradle(Project level) file under the repositories of buildscript, dependencies, for more information refer Add Configuration.
maven {
url 'https://repo.huaweicloud.com/repository/maven/'
}
maven {
url 'https://developer.huawei.com/repo/'
}
  1. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values.
"reqPermissions": [
{
"name": "ohos.permission.CAMERA"
},
{
"name": "ohos.permission.WRITE_USER_STORAGE"
},
{
"name": "ohos.permission.READ_USER_STORAGE"
},
{
"name": "ohos.permission.MICROPHONE"
},
{
"name": "ohos.permission.LOCATION"
}
]

https://preview.redd.it/10j7dcrmhsq71.png?width=602&format=png&auto=webp&s=5fa3e054e6565e411749dbff333b3cf1b29e9d3e
  1. Create New > Ability, as follows.
https://preview.redd.it/ejykrxrqhsq71.png?width=690&format=png&auto=webp&s=e2abce2b184b6f662dfa5cd301661b22c6cd4bec
  1. Development Procedure.
Create MainAbility.java ability and add the below code.
package ohos.samples.camera;

import ohos.samples.camera.slice.MainAbilitySlice;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.bundle.IBundleManager;
import ohos.security.SystemPermission;

import java.util.Arrays;

/**
* MainAbility
*/
public class MainAbility extends Ability {
u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
requestPermissions();
}

private void requestPermissions() {
String[] permissions = {
SystemPermission.WRITE_USER_STORAGE, SystemPermission.READ_USER_STORAGE, SystemPermission.CAMERA,
SystemPermission.MICROPHONE, SystemPermission.LOCATION
};
requestPermissionsFromUser(Arrays.stream(permissions)
.filter(permission -> verifySelfPermission(permission) != IBundleManager.PERMISSION_GRANTED).toArray(String[]::new), 0);
}

u/Override
public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
if (permissions == null permissions.length == 0 grantResults == null grantResults.length == 0) {
return;
}
for (int grantResult : grantResults) {
if (grantResult != IBundleManager.PERMISSION_GRANTED) {
terminateAbility();
break;
}
}
}
}

Create MainAbilitySlice.java ability and add the below code.

package ohos.samples.camera.slice;

import ohos.samples.camera.ResourceTable;
import ohos.samples.camera.TakePhotoAbility;
import ohos.samples.camera.VideoRecordAbility;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Component;

/**
* MainAbilitySlice
*/
public class MainAbilitySlice extends AbilitySlice {
u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_main_ability_slice);
initComponents();
}

private void initComponents() {
Component takePhoto = findComponentById(ResourceTable.Id_take_photo);
Component videoRecord = findComponentById(ResourceTable.Id_video_record);
takePhoto.setClickedListener((component) -> startAbility(TakePhotoAbility.class.getName()));
videoRecord.setClickedListener((component) -> startAbility(VideoRecordAbility.class.getName()));
}

private void startAbility(String abilityName) {
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName(getBundleName())
.withAbilityName(abilityName)
.build();
Intent intent = new Intent();
intent.setOperation(operation);
startAbility(intent);
}
}
Create TakePhotoAbility.java ability and add the below code.
package ohos.samples.camera;

import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PICTURE;
import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.CameraInfo;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.device.FrameConfig;
import ohos.media.image.ImageReceiver;
import ohos.media.image.common.ImageFormat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* TakePhotoAbility
*/
public class TakePhotoAbility extends Ability {
private static final String TAG = TakePhotoAbility.class.getSimpleName();

private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);

private static final int SCREEN_WIDTH = 1080;

private static final int SCREEN_HEIGHT = 1920;

private static final int IMAGE_RCV_CAPACITY = 9;

private SurfaceProvider surfaceProvider;

private ImageReceiver imageReceiver;

private boolean isFrontCamera;

private Surface previewSurface;

private Camera cameraDevice;

private Component buttonGroupLayout;

private ComponentContainer surfaceContainer;

private final EventHandler eventHandler = new EventHandler(EventRunner.current()) {
};

u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_main_camera_slice);

initComponents();
initSurface();
}

private void initSurface() {
getWindow().setTransparent(true);
DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
surfaceProvider = new SurfaceProvider(this);
surfaceProvider.setLayoutConfig(params);
surfaceProvider.pinToZTop(false);
if (surfaceProvider.getSurfaceOps().isPresent()) {
surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
}
surfaceContainer.addComponent(surfaceProvider);
}

private void initComponents() {
buttonGroupLayout = findComponentById(ResourceTable.Id_directionalLayout);
surfaceContainer = (ComponentContainer) findComponentById(ResourceTable.Id_surface_container);
Image takePhotoImage = (Image) findComponentById(ResourceTable.Id_tack_picture_btn);
Image exitImage = (Image) findComponentById(ResourceTable.Id_exit);
Image switchCameraImage = (Image) findComponentById(ResourceTable.Id_switch_camera_btn);
exitImage.setClickedListener(component -> terminateAbility());
takePhotoImage.setClickedListener(this::takeSingleCapture);
takePhotoImage.setLongClickedListener(this::takeMultiCapture);
switchCameraImage.setClickedListener(this::switchCamera);
}

private void openCamera() {
imageReceiver = ImageReceiver.create(SCREEN_WIDTH, SCREEN_HEIGHT, ImageFormat.JPEG, IMAGE_RCV_CAPACITY);
imageReceiver.setImageArrivalListener(this::saveImage);
CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
String[] cameraList = cameraKit.getCameraIds();
String cameraId = "";
for (String logicalCameraId : cameraList) {
int faceType = cameraKit.getCameraInfo(logicalCameraId).getFacingType();
switch (faceType) {
case CameraInfo.FacingType.CAMERA_FACING_FRONT:
if (isFrontCamera) {
cameraId = logicalCameraId;
}
break;
case CameraInfo.FacingType.CAMERA_FACING_BACK:
if (!isFrontCamera) {
cameraId = logicalCameraId;
}
break;
case CameraInfo.FacingType.CAMERA_FACING_OTHERS:
default:
break;
}
}
if (cameraId != null && !cameraId.isEmpty()) {
CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
}
}

private void saveImage(ImageReceiver receiver) {
File saveFile = new File(getFilesDir(), "IMG_" + System.currentTimeMillis() + ".jpg");
ohos.media.image.Image image = receiver.readNextImage();
ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);
byte[] bytes = new byte[component.remaining()];
component.read(bytes);
try (FileOutputStream output = new FileOutputStream(saveFile)) {
output.write(bytes);
output.flush();
String msg = "Take photo succeed";
showTips(this, msg);
} catch (IOException e) {
HiLog.error(LABEL_LOG, "%{public}s", "saveImage IOException");
}
}

private void takeSingleCapture(Component component) {
if (cameraDevice == null imageReceiver == null) {
return;
}
FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());


FrameConfig pictureFrameConfig = framePictureConfigBuilder.build();
cameraDevice.triggerSingleCapture(pictureFrameConfig);
saveImage(imageReceiver);
}

private void takeMultiCapture(Component component) {
FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
List frameConfigs = new ArrayList<>();
FrameConfig firstFrameConfig = framePictureConfigBuilder.build();
frameConfigs.add(firstFrameConfig);
FrameConfig secondFrameConfig = framePictureConfigBuilder.build();
frameConfigs.add(secondFrameConfig);
cameraDevice.triggerMultiCapture(frameConfigs);
}

private void switchCamera(Component component) {
isFrontCamera = !isFrontCamera;
if (cameraDevice != null) {
cameraDevice.release();
}
updateComponentVisible(false);
openCamera();
}

private class CameraStateCallbackImpl extends CameraStateCallback {
CameraStateCallbackImpl() {
}

u/Override
public void onCreated(Camera camera) {
if (surfaceProvider.getSurfaceOps().isPresent()) {
previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
}
if (previewSurface == null) {
HiLog.error(LABEL_LOG, "%{public}s", "Create camera filed, preview surface is null");
return;
}
CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();
cameraConfigBuilder.addSurface(previewSurface);
cameraConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
camera.configure(cameraConfigBuilder.build());
cameraDevice = camera;
updateComponentVisible(true);
}

u/Override
public void onConfigured(Camera camera) {
FrameConfig.Builder framePreviewConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
framePreviewConfigBuilder.addSurface(previewSurface);
camera.triggerLoopingCapture(framePreviewConfigBuilder.build());
}
}

private void updateComponentVisible(boolean isVisible) {
buttonGroupLayout.setVisibility(isVisible ? Component.VISIBLE : Component.INVISIBLE);
}

private class SurfaceCallBack implements SurfaceOps.Callback {
u/Override
public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
if (callbackSurfaceOps != null) {
callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
}
eventHandler.postTask(TakePhotoAbility.this::openCamera, 200);
}

u/Override
public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
}

u/Override
public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
}
}

private void showTips(Context context, String msg) {
getUITaskDispatcher().asyncDispatch(() -> new ToastDialog(context).setText(msg).show());
}

private void releaseCamera() {
if (cameraDevice != null) {
cameraDevice.release();
}

if (imageReceiver != null) {
imageReceiver.release();
}
}

u/Override
protected void onStop() {
releaseCamera();
}
}
Create VideoRecordAbility.java ability and add the below code.
package ohos.samples.camera;

import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.window.dialog.ToastDialog;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.CameraInfo;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.device.FrameConfig;
import ohos.media.common.AudioProperty;
import ohos.media.common.Source;
import ohos.media.common.StorageProperty;
import ohos.media.common.VideoProperty;
import ohos.media.recorder.Recorder;
import ohos.multimodalinput.event.TouchEvent;

import java.io.File;

/**
* VideoRecordAbility
*/
public class VideoRecordAbility extends Ability {
private static final String TAG = VideoRecordAbility.class.getSimpleName();

private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);

private static final int SCREEN_WIDTH = 1080;

private static final int SCREEN_HEIGHT = 1920;

private SurfaceProvider surfaceProvider;

private Surface recorderSurface;

private Surface previewSurface;

private boolean isFrontCamera;

private Camera cameraDevice;

private Component buttonGroupLayout;

private Recorder mediaRecorder;

private ComponentContainer surfaceContainer;

private CameraConfig.Builder cameraConfigBuilder;

private boolean isRecording;

private final Object lock = new Object();

private final EventHandler eventHandler = new EventHandler(EventRunner.current()) {
};

u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_main_camera_slice);

initComponents();
initSurface();
}

private void initSurface() {
getWindow().setTransparent(true);
DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
surfaceProvider = new SurfaceProvider(this);
surfaceProvider.setLayoutConfig(params);
surfaceProvider.pinToZTop(false);
if (surfaceProvider.getSurfaceOps().isPresent()) {
surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
}
surfaceContainer.addComponent(surfaceProvider);
}

private void initComponents() {
buttonGroupLayout = findComponentById(ResourceTable.Id_directionalLayout);
surfaceContainer = (ComponentContainer) findComponentById(ResourceTable.Id_surface_container);
Image videoRecord = (Image) findComponentById(ResourceTable.Id_tack_picture_btn);
Image exitImage = (Image) findComponentById(ResourceTable.Id_exit);
Image switchCameraImage = (Image) findComponentById(ResourceTable.Id_switch_camera_btn);
exitImage.setClickedListener(component -> terminateAbility());
switchCameraImage.setClickedListener(this::switchCamera);

videoRecord.setLongClickedListener(component -> {
startRecord();
isRecording = true;
videoRecord.setPixelMap(ResourceTable.Media_ic_camera_video_press);
});

videoRecord.setTouchEventListener((component, touchEvent) -> {
if (touchEvent != null && touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP && isRecording) {
stopRecord();
isRecording = false;
videoRecord.setPixelMap(ResourceTable.Media_ic_camera_video_ready);
}
return true;
});
}

private void initMediaRecorder() {
mediaRecorder = new Recorder();
VideoProperty.Builder videoPropertyBuilder = new VideoProperty.Builder();
videoPropertyBuilder.setRecorderBitRate(10000000);
videoPropertyBuilder.setRecorderDegrees(90);
videoPropertyBuilder.setRecorderFps(30);
videoPropertyBuilder.setRecorderHeight(Math.min(1440, 720));
videoPropertyBuilder.setRecorderWidth(Math.max(1440, 720));
videoPropertyBuilder.setRecorderVideoEncoder(Recorder.VideoEncoder.H264);
videoPropertyBuilder.setRecorderRate(30);

Source source = new Source();
source.setRecorderAudioSource(Recorder.AudioSource.MIC);
source.setRecorderVideoSource(Recorder.VideoSource.SURFACE);
mediaRecorder.setSource(source);
mediaRecorder.setOutputFormat(Recorder.OutputFormat.MPEG_4);
File file = new File(getFilesDir(), "VID_" + System.currentTimeMillis() + ".mp4");
StorageProperty.Builder storagePropertyBuilder = new StorageProperty.Builder();
storagePropertyBuilder.setRecorderFile(file);
mediaRecorder.setStorageProperty(storagePropertyBuilder.build());

AudioProperty.Builder audioPropertyBuilder = new AudioProperty.Builder();
audioPropertyBuilder.setRecorderAudioEncoder(Recorder.AudioEncoder.AAC);
mediaRecorder.setAudioProperty(audioPropertyBuilder.build());
mediaRecorder.setVideoProperty(videoPropertyBuilder.build());
mediaRecorder.prepare();
}

private void openCamera() {
CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
String[] cameraList = cameraKit.getCameraIds();
String cameraId = "";
for (String logicalCameraId : cameraList) {
int faceType = cameraKit.getCameraInfo(logicalCameraId).getFacingType();
switch (faceType) {
case CameraInfo.FacingType.CAMERA_FACING_FRONT:
if (isFrontCamera) {
cameraId = logicalCameraId;
}
break;
case CameraInfo.FacingType.CAMERA_FACING_BACK:
if (!isFrontCamera) {
cameraId = logicalCameraId;
}
break;
case CameraInfo.FacingType.CAMERA_FACING_OTHERS:
default:
break;
}
}
if (cameraId != null && !cameraId.isEmpty()) {
CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
}
}

private void switchCamera(Component component) {
isFrontCamera = !isFrontCamera;
if (cameraDevice != null) {
cameraDevice.release();
}
updateComponentVisible(false);
openCamera();
}

private class CameraStateCallbackImpl extends CameraStateCallback {
CameraStateCallbackImpl() {
}

u/Override
public void onCreated(Camera camera) {
if (surfaceProvider.getSurfaceOps().isPresent()) {
previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
}
if (previewSurface == null) {
HiLog.error(LABEL_LOG, "%{public}s", "Create camera filed, preview surface is null");
return;
}
cameraConfigBuilder = camera.getCameraConfigBuilder();
cameraConfigBuilder.addSurface(previewSurface);
camera.configure(cameraConfigBuilder.build());
cameraDevice = camera;
updateComponentVisible(true);
}

u/Override
public void onConfigured(Camera camera) {
FrameConfig.Builder frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
frameConfigBuilder.addSurface(previewSurface);
if (isRecording && recorderSurface != null) {
frameConfigBuilder.addSurface(recorderSurface);
}
camera.triggerLoopingCapture(frameConfigBuilder.build());
if (isRecording) {
eventHandler.postTask(() -> mediaRecorder.start());
}
}
}

private void startRecord() {
if (cameraDevice == null) {
HiLog.error(LABEL_LOG, "%{public}s", "startRecord failed, parameters is illegal");
return;
}
synchronized (lock) {
initMediaRecorder();
recorderSurface = mediaRecorder.getVideoSurface();
cameraConfigBuilder = cameraDevice.getCameraConfigBuilder();
try {
cameraConfigBuilder.addSurface(previewSurface);
if (recorderSurface != null) {
cameraConfigBuilder.addSurface(recorderSurface);
}
cameraDevice.configure(cameraConfigBuilder.build());
} catch (IllegalStateException IllegalArgumentException e) {
HiLog.error(LABEL_LOG, "%{public}s", "startRecord IllegalStateException IllegalArgumentException");
}
}
new ToastDialog(this).setText("Recording").show();
}

private void stopRecord() {
synchronized (lock) {
try {
eventHandler.postTask(() -> mediaRecorder.stop());
if (cameraDevice == null cameraDevice.getCameraConfigBuilder() == null) {
HiLog.error(LABEL_LOG, "%{public}s", "StopRecord cameraDevice or getCameraConfigBuilder is null");
return;
}
cameraConfigBuilder = cameraDevice.getCameraConfigBuilder();
cameraConfigBuilder.addSurface(previewSurface);
cameraConfigBuilder.removeSurface(recorderSurface);
cameraDevice.configure(cameraConfigBuilder.build());
} catch (IllegalStateException IllegalArgumentException exception) {
HiLog.error(LABEL_LOG, "%{public}s", "stopRecord occur exception");
}
}
new ToastDialog(this).setText("video saved").show();
}

private void updateComponentVisible(boolean isVisible) {
buttonGroupLayout.setVisibility(isVisible ? Component.VISIBLE : Component.INVISIBLE);
}

private class SurfaceCallBack implements SurfaceOps.Callback {
u/Override
public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
if (callbackSurfaceOps != null) {
callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
}
eventHandler.postTask(VideoRecordAbility.this::openCamera, 200);
}

u/Override
public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
}

u/Override
public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
}
}

private void releaseCamera() {
if (cameraDevice != null) {
cameraDevice.release();
}
}

u/Override
protected void onStop() {
releaseCamera();
}
}
Create ability_main.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:id="$+id:root_layout"
ohos:height="match_parent"
ohos:padding="30px"
ohos:width="match_parent"
ohos:orientation="vertical">

ohos:id="$+id:take_photo"
ohos:height="match_content"
ohos:width="match_parent"
ohos:padding="10vp"
ohos:text_size="25fp"
ohos:text_alignment="left"
ohos:text="$string:take_photo"
ohos:background_element="$graphic:button_background"
ohos:element_end="$media:arrow_next_right_icon"/>

ohos:id="$+id:video_record"
ohos:height="match_content"
ohos:top_margin="30vp"
ohos:padding="10vp"
ohos:text_alignment="left"
ohos:text_size="25fp"
ohos:width="match_parent"
ohos:text="$string:video_record"
ohos:background_element="$graphic:button_background"
ohos:element_end="$media:arrow_next_right_icon"/>

Create main_camera_slice.xml in graphic folder and add the below code.
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent">

ohos:id="$+id:root_container"
ohos:height="match_parent"
ohos:width="match_parent">

ohos:id="$+id:surface_container"
ohos:height="match_parent"
ohos:width="match_parent"/>

ohos:id="$+id:directionalLayout"
ohos:height="match_content"
ohos:width="match_parent"
ohos:align_parent_bottom="$+id:root_container"
ohos:bottom_margin="30vp"
ohos:orientation="horizontal"
ohos:visibility="invisible">

ohos:id="$+id:exit"
ohos:height="match_content"
ohos:width="match_parent"
ohos:image_src="$media:ic_camera_back"
ohos:layout_alignment="vertical_center"
ohos:scale_mode="center"
ohos:weight="1"/>

ohos:id="$+id:tack_picture_btn"
ohos:height="match_content"
ohos:width="match_parent"
ohos:image_src="$media:ic_camera_photo"
ohos:layout_alignment="vertical_center"
ohos:scale_mode="center"
ohos:weight="1"/>

ohos:id="$+id:switch_camera_btn"
ohos:height="match_content"
ohos:width="match_parent"
ohos:image_src="$media:ic_camera_switch"
ohos:layout_alignment="vertical_center"
ohos:scale_mode="center"
ohos:weight="1"/>



  1. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.

https://preview.redd.it/87xqvognisq71.png?width=693&format=png&auto=webp&s=3f5959e572955c05ceb8a1211e5a8d828c7bbebb

Result

  1. Run Application on connected device, we can see below result.

https://preview.redd.it/dqfki55visq71.png?width=364&format=png&auto=webp&s=fdaa601b194cddbe82a8c2bebe442fb39924456e

https://preview.redd.it/syulx37visq71.png?width=346&format=png&auto=webp&s=aa098ddff5df41e047fff03cb056fcfd0c566a13
  1. Click on button, one by one see result as per below screen.

https://preview.redd.it/doza8scvisq71.png?width=362&format=png&auto=webp&s=a826d4f1774b50296e082ca544d094312a93fb2a

https://preview.redd.it/kd36j01xisq71.png?width=366&format=png&auto=webp&s=426380de8e18b3c47bf8ead4e0f5203a999ba27b

https://preview.redd.it/8e11q16zisq71.png?width=368&format=png&auto=webp&s=a1081effa5142495ebcae3e2f451e86fb2cce335

https://preview.redd.it/8812tw31jsq71.png?width=366&format=png&auto=webp&s=b671273dfac436c53b8b98406ab12fba3c856a44

Tips and Tricks

  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Do not forgot to add permission in config.json file.
  • To ensure better compatibility of your application, you must query the supported camera capabilities before creating a camera instance or setting related parameters.

Conclusion

In this article, we have learnt Camera service in Harmony OS. We can access and operate the camera device and develop new functions through the open APIs. Common operations include preview, photographing, burst photographing, and video recording.
Thanks for reading the article, please do like and comment your queries or suggestions.

References

Harmony OS: https://www.harmonyos.com/en/develop/?ha\_source=hms1
Camera Overview: https://developer.harmonyos.com/en/docs/documentation/doc-guides/media-camera-overview-0000000000031783?ha\_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.09.24 11:17 lokeshsuryan Beginner: Integration of Fusion Search in Harmony OS

Beginner: Integration of Fusion Search in Harmony OS

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover Huawei Fusion Search with Java in Harmony OS.
HarmonyOS provides full-text search features at the search engine level. HarmonyOS Fusion search provide many types of searches such as Full-text index, Full-text search, Global search, index filed etc search records and provide accurate results. These features enable the users to perform both in-application and global search and provide a more accurate and efficient search. HarmonyOS provides SearchAbility, SearchSession fusion search APIs for searching persistent data in an application.

Basic Concepts

  • Full-text index An inverted index that records the position and count of each term.
  • Full-text search A search engine technology that matches search results by full-text indexing.
  • Global search A feature that allow users to search all application data through one entry.
  • Global search application An application that provides a global search entry in HarmonyOS. Generally, the application is a drop-down list box or a floating search box on the desktop.
  • Index source application An application whose data is to be indexed using the fusion search APIs.
  • Index field Name of an index field. For example: An image that has its file name, storage path, size, and shooting time, the file name can be used as an index field.
  • Index form Description of an index field, such as the index type, whether the index field is the primary key, whether to store the index field, and whether to analyze the index field value.

Development Overview

You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • DevEcho studio installed.

Follows the steps.

  1. Create Harmony OS Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select Empty Ability(Java) template and click Next as per below image.

https://preview.redd.it/dxdepz413fp71.png?width=689&format=png&auto=webp&s=969ea0c10920a918b9a25ecd05b089720c77dec1
  • Enter Project Name and Package Name and click on Finish.
https://preview.redd.it/pxzi62x33fp71.png?width=685&format=png&auto=webp&s=f6806bcbd5ebc17a9fe724178ad69ee58baa50be
2. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.
https://preview.redd.it/wgzopfz73fp71.png?width=602&format=png&auto=webp&s=a1dd153a07948f37a606a6ae640dd30b4b1ec69d
  1. Add the below maven URL in build.gradle(Project level) file under the repositories of buildscript, dependencies, for more information refer Add Configuration.
maven {
url 'https://repo.huaweicloud.com/repository/maven/'
}
maven {
url 'https://developer.huawei.com/repo/'
}
4. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values.
"reqPermissions": [
{
"name": "ohos.permission.ACCESS_SEARCH_SERVICE"
}
]

https://preview.redd.it/ad3oublx4fp71.png?width=602&format=png&auto=webp&s=26f4fa00606342b368e50d83f9fdf9750cf8584a
  1. Create New > Ability, as follows.
https://preview.redd.it/e7aycu6x4fp71.png?width=690&format=png&auto=webp&s=ef6450a5d777b90bae777dfff992e8bca3e0e354
  1. Development Procedure.
Create MainAbility.java ability and add the below code.
package com.hms.fusionsearchdemo.slice;

import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.data.search.SearchAbility;
import ohos.data.search.connect.ServiceConnectCallback;
import ohos.samples.search.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.samples.search.utils.LogUtils;
import ohos.samples.search.utils.SearchUtils;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
* MainAbilitySlice
*
* u/since 2021-07-23
*/
public class MainAbilitySlice extends AbilitySlice {
private static final String TAG = MainAbilitySlice.class.getSimpleName();

private SearchAbility searchAbility;

private SearchUtils searUtils;

private Text searchResult;

u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initComponents();
connectService();
}

private void connectService() {
LogUtils.info(TAG, "connect search service");
TaskDispatcher task = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
searchAbility = new SearchAbility(getContext());
searUtils = new SearchUtils(getContext(), searchAbility);
task.asyncDispatch(() -> {
CountDownLatch lock = new CountDownLatch(1);

// connect to SearchService
searchAbility.connect(new ServiceConnectCallback() {
u/Override
public void onConnect() {
lock.countDown();
}

u/Override
public void onDisconnect() {
}
});
try {
lock.await(3000, TimeUnit.MILLISECONDS);
if (searchAbility.hasConnected()) {
searchResult.setText(ResourceTable.String_connect_service_succeed);
} else {
searchResult.setText(ResourceTable.String_connect_service_failed);
}
} catch (InterruptedException e) {
LogUtils.info(TAG, "connect search service failed");
}
});
}

private void initComponents() {
Button btnBuildIndex = (Button)findComponentById(ResourceTable.Id_btnBuildIndex);
btnBuildIndex.setClickedListener(this::buildIndexForms);
Button btnReadIndex = (Button)findComponentById(ResourceTable.Id_btnReadIndex);
btnReadIndex.setClickedListener(this::readIndexForms);
Button btnInsertIndexData = (Button)findComponentById(ResourceTable.Id_btnInsertIndexData);
btnInsertIndexData.setClickedListener(this::insertIndexData);
Button btnUpdateIndexData = (Button)findComponentById(ResourceTable.Id_btnUpdateIndexData);
btnUpdateIndexData.setClickedListener(this::updateIndexData);
Button btnDeleteIndexData = (Button)findComponentById(ResourceTable.Id_btnDeleteIndexData);
btnDeleteIndexData.setClickedListener(this::deleteIndexData);
Button btnDeleteIndexDataByQuery = (Button) findComponentById(ResourceTable.Id_btnDeleteIndexDataByQuery);
btnDeleteIndexDataByQuery.setClickedListener(this::deleteByQuery);
Button btnGetSearchHitCount = (Button)findComponentById(ResourceTable.Id_btnGetHitCount);
btnGetSearchHitCount.setClickedListener(this::getSearchHitCount);
Button btnSearchByGroup = (Button)findComponentById(ResourceTable.Id_btnSearchByGroup);
btnSearchByGroup.setClickedListener(this::searchByGroup);
Button btnSearchByPage = (Button)findComponentById(ResourceTable.Id_btnSearchByPage);
btnSearchByPage.setClickedListener(this::searchByPage);

searchResult = (Text) findComponentById(ResourceTable.Id_searchResult);
}

private void searchByPage(Component component) {
searchResult.setText(searUtils.searchByPage());
}

private void searchByGroup(Component component) {
searchResult.setText(searUtils.searchByGroup());
}

private void getSearchHitCount(Component component) {
searchResult.setText(searUtils.getSearchHitCount());
}

private void deleteByQuery(Component component) {
int result = searUtils.deleteIndexByQuery();
if (result == 1) {
LogUtils.info(TAG, "updateIndexData succeed");
searchResult.setText(ResourceTable.String_succeed);
} else {
LogUtils.error(TAG, "updateIndexData failed");
searchResult.setText(ResourceTable.String_failed);
}
}

private void deleteIndexData(Component component) {
int result = searUtils.deleteIndexData();
if (result > 0) {
LogUtils.error(TAG, "updateIndexData failed num=" + result);
searchResult.setText(ResourceTable.String_failed);
} else {
LogUtils.info(TAG, "updateIndexData succeed");
searchResult.setText(ResourceTable.String_succeed);
}
}

private void updateIndexData(Component component) {
int result = searUtils.updateIndexData();
if (result > 0) {
LogUtils.error(TAG, "updateIndexData failed num=" + result);
searchResult.setText(ResourceTable.String_failed);
} else {
LogUtils.info(TAG, "updateIndexData succeed");
searchResult.setText(ResourceTable.String_succeed);
}
}

private void insertIndexData(Component component) {
int result = searUtils.insertIndexData();
if (result > 0) {
LogUtils.error(TAG, "insertIndexData failed num=" + result);
searchResult.setText(ResourceTable.String_failed);
} else {
LogUtils.info(TAG, "insertIndexData succeed");
searchResult.setText(ResourceTable.String_succeed);
}
}

private void readIndexForms(Component component) {
searchResult.setText(searUtils.readIndexForms());
}

private void buildIndexForms(Component component) {
int result = searUtils.buildIndexForms();
if (result == 1) {
LogUtils.info(TAG, "buildIndexForms succeed");
searchResult.setText(ResourceTable.String_succeed);
} else {
LogUtils.error(TAG, "buildIndexForms failed");
searchResult.setText(ResourceTable.String_failed);
}
}

u/Override
public void onActive() {
super.onActive();
}

u/Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}
Create SearchUtils.java ability and add the below code.
package com.hms.fusionsearchdemo.utils;

import ohos.app.Context;
import ohos.data.search.SearchAbility;
import ohos.data.search.SearchSession;
import ohos.data.search.model.*;
import ohos.data.search.schema.CommonItem;
import ohos.data.search.schema.IndexSchemaType;
import ohos.utils.zson.ZSONArray;
import ohos.utils.zson.ZSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SearchUtils {
private final String LOCAL_DEVICE_ID = "";
private final String FILE_PATH;
private final Context context;
private final SearchAbility searchAbility;

public SearchUtils(Context context, SearchAbility searchAbility) {
this.context = context;
this.searchAbility = searchAbility;
FILE_PATH = context.getFilesDir().getPath();
}

/**
* build indexfroms
*
* u/return int
*/
public int buildIndexForms() {
searchAbility.clearIndex(SearchParameter.DEFAULT_GROUP, context.getBundleName(), null);
searchAbility.clearIndexForm(context.getBundleName());

// constructing custom index attributes
List indexFormList = new ArrayList<>();
indexFormList.add( // Word segmentation, while supporting sorting and grouping
new IndexForm("tag", IndexType.SORTED, false, true, false));
indexFormList.add( // Support sorting and range query
new IndexForm("bucket_id", IndexType.INTEGER, false, true, false));
indexFormList.add( // Support range search
new IndexForm("latitude", IndexType.FLOAT, false, true, false));
indexFormList.add( // Support range search
new IndexForm("longitude", IndexType.FLOAT, false, true, false));
indexFormList.add( // Support search
new IndexForm("device_id", IndexType.NO_ANALYZED, false, true, false));

// constructing index attributes using a generic template
return searchAbility.setIndexForm(context.getBundleName(), 1, indexFormList, IndexSchemaType.COMMON);
}

/**
* readIndexForms
*
* u/return String
*/
public String readIndexForms() {
StringBuilder result = new StringBuilder("Result:");
List indexFormList = searchAbility.getIndexForm(context.getBundleName());
for (IndexForm indexForm : indexFormList) {
result.append(indexForm.toString()).append(System.lineSeparator());
}
return result.toString();
}

/**
* insert index data
*
* u/return int
*/
public int insertIndexData() {
// Create an IndexData instance.
List indexDataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i)
.setTitle("position")
.setSubtitle("subtitle")
.setCategory("things")
.setDescription("is description")
.setName("name")
.setAlternateName("othername")
.setDateCreate(System.currentTimeMillis())
.setKeywords("key")
.setPotentialAction("com.sample.search.TestAbility")
.setThumbnailUrl(FILE_PATH)
.setUrl(FILE_PATH)
.setReserved1("reserved1")
.setReserved2("reserved2");
commonItem.put("tag", "location" + i);
commonItem.put("bucket_id", i);
commonItem.put("latitude", i / 10.0 * 180);
commonItem.put("longitude", i / 10.0 * 360);
commonItem.put("device_id", "localDeviceId");
indexDataList.add(commonItem);
}

// Insert a list of indexes.
List failedList = searchAbility.insert(SearchParameter.DEFAULT_GROUP,
context.getBundleName(), indexDataList);
// If some indexes fail to be inserted, try again later.
return failedList.size();
}

/**
* update index data
*
* u/return int
*/
public int updateIndexData() {
// constructing index data
List indexDataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i).setTitle("position update");
commonItem.put("tag", "location update" + i);
commonItem.put("bucket_id", i + 1);
commonItem.put("latitude", i / 10.0 * 100);
commonItem.put("longitude", i / 10.0 * 300);
commonItem.put("device_id", "localDeviceId");
indexDataList.add(commonItem);
}

List failedList = searchAbility.update(SearchParameter.DEFAULT_GROUP,
context.getBundleName(), indexDataList);
return failedList.size();
}

/**
* delete index data
*
* u/return int
*/
public int deleteIndexData() {
// constructing index data
List indexDataList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i);
indexDataList.add(commonItem);
}

List failedList = searchAbility.delete(SearchParameter.DEFAULT_GROUP,
context.getBundleName(), indexDataList);
return failedList.size();
}

/**
* deleteIndexByQuery
*
* u/return int
*/
public int deleteIndexByQuery() {
return searchAbility.deleteByQuery(SearchParameter.DEFAULT_GROUP,
context.getBundleName(), buildQueryString().toString());
}

/**
* getSearchHitCount
*
* u/return int
*/
public String getSearchHitCount() {
SearchSession session = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName());
String result = "SearchHitCount:" + System.lineSeparator();
if (session == null) {
return result;
}
try {
String query = buildQueryString().toString();
return result + session.getSearchHitCount(query);
} finally {
searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName(), session);
}
}

/**
* searchByGroup
*
* u/return String
*/
public String searchByGroup() {
// Start a search session.
SearchSession session = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName());
StringBuilder result = new StringBuilder("searchByGroup:" + System.lineSeparator());
if (session == null) {
return result.toString();
}
try {
ZSONObject query = buildQueryString();
// SearchParameter.GROUP_FIELD_LIST indicates the field list you need to specify when calling the groupSearch method.
query.put(SearchParameter.GROUP_FIELD_LIST, new ZSONArray(Arrays.asList("tag", CommonItem.CATEGORY)));

int limit = 10; // A maximum of 10 groups (recommendations) are returned for each field.
List recommendationList = session.groupSearch(query.toString(), limit);

// Process recommendations.
for (Recommendation recommendation : recommendationList) {
result.append(recommendation.toString()).append(System.lineSeparator());
}
return result.toString();
} finally {
searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName(), session);
}
}

/**
* searchByPage
*
* u/return String
*/
public String searchByPage() {
// Start a search session.
SearchSession session = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName());
StringBuilder result = new StringBuilder("searchByPage:" + System.lineSeparator());
if (session == null) {
return result.toString();
}
try {
String query = buildQueryString().toString();
int count = session.getSearchHitCount(query);
int batch = 50; // A maximum of 50 results are allowed on each page.
for (int i = 0; i < count; i += batch) {
List indexDataList = session.search(query, i, batch);
for (IndexData indexData : indexDataList) {
result.append("tag:").append(indexData.get("tag")).append(", latitude:")
.append(indexData.get("latitude")).append(", longitude:")
.append(indexData.get("longitude")).append(System.lineSeparator());
}
}
return result.toString();
} finally {
searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName(), session);
}
}

/**
* buildQueryString
*
* u/return ZSONObject
*/
public ZSONObject buildQueryString() {
// Create a JSONObject.
ZSONObject zsonObject = new ZSONObject();

// SearchParameter.QUERY indicates the user input. It is recommended that the search fields be analyzed.
// Assume that the user inputs location and starts a search for the title and tag fields.
ZSONObject query = new ZSONObject();
query.put("location", new ZSONArray(Arrays.asList(CommonItem.TITLE, "tag")));
zsonObject.put(SearchParameter.QUERY, query);

/*
* Search criteria can be added to ZSONArray of the SearchParameter.FILTER_CONDITION.
* An index in the index library is hit only if the search criteria of each ZSONObject in the ZSONArray is met.
* The search criteria of a ZSONArray is met as long as one of the conditions in the search criteria is met.
*/
ZSONArray filterCondition = new ZSONArray();

// For the first condition, a field may have multiple values.
ZSONObject filter1 = new ZSONObject();
filter1.put("bucket_id", new ZSONArray(Arrays.asList(0, 1, 2, 3, 4, 5))); // An index is hit if its value is 0, 1, 2, 3, 4, or 5 for the bucket_id field.
filter1.put(CommonItem.IDENTIFIER, new ZSONArray(Arrays.asList(0, 1, 2, 3, 4, 5))); // The index is also hit if its value is 0 , 1, 2, 3, 4 or 5 for the CommonItem.IDENTIFIER field.
filterCondition.add(filter1);
ZSONObject filter2 = new ZSONObject();
filter2.put("tag", new ZSONArray(Collections.singletonList("position")));
filter2.put(CommonItem.TITLE, new ZSONArray(Collections.singletonList("position"))); // An index is hit if the value of the tag or CommonItem.TITLE field is position.
filterCondition.add(filter2);
zsonObject.put(SearchParameter.FILTER_CONDITION, filterCondition); // An index is hit only if both the first and second conditions are met.

// SearchParameter.DEVICE_ID_LIST indicates the device ID list. Indexes with the specified IDs are hit.
ZSONObject deviceId = new ZSONObject();
deviceId.put("device_id", new ZSONArray(Collections.singletonList("localDeviceId"))); // Specify the local device.
zsonObject.put(SearchParameter.DEVICE_ID_LIST, deviceId);

// Start a search by specifying the value range of a specified index field.
// Indexes whose values fall within the value range of the specified index field are hit.
ZSONObject latitudeObject = new ZSONObject();
latitudeObject.put(SearchParameter.LOWER, -80.0f);
latitudeObject.put(SearchParameter.UPPER, 80.0f);
zsonObject.put("latitude", latitudeObject); // The latitude must be in the range of [-80.0f, 80.0f].
ZSONObject longitudeObject = new ZSONObject();
longitudeObject.put(SearchParameter.LOWER, -90.0);
longitudeObject.put(SearchParameter.UPPER, 90.0);
zsonObject.put("longitude", longitudeObject); // The longitude must be in the range of [-90.0, 90.0].

/*
* SearchParameter.ORDER_BY indicates how the search results are sorted.
* The value can be SearchParameter.ASC or SearchParameter.DESC.
* The sequence of the fields matters.
* In the following example, indexes are first sorted in ascending order of the CommonItem.CATEGORY field.
* If they are equal on the CommonItem.CATEGORY field, they will be sorted in descending order of the tag field.
*/
ZSONObject order = new ZSONObject();
order.put(CommonItem.CATEGORY, SearchParameter.ASC);
order.put("tag", SearchParameter.DESC);
zsonObject.put(SearchParameter.ORDER_BY, order);

// Obtain the string for search.
return zsonObject;
}
}
Create ability_main.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#FFDEAD">
ohos:height="match_content"
ohos:width="match_parent"
ohos:alignment="horizontal_center"
ohos:orientation="vertical">
ohos:id="$+id:btnBuildIndex"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_build_index_forms"/>
ohos:id="$+id:btnInsertIndexData"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_insert_index_data"/>

ohos:id="$+id:btnReadIndex"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_read_index_forms"/>
ohos:id="$+id:btnUpdateIndexData"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_update_index_data"/>
ohos:id="$+id:btnSearchByPage"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_search_by_page"/>
ohos:id="$+id:btnDeleteIndexData"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_delete_indexdata"/>
ohos:id="$+id:btnDeleteIndexDataByQuery"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_delete_indexdata_by_query"/>
ohos:id="$+id:btnGetHitCount"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_get_search_hint_count"/>
ohos:id="$+id:btnSearchByGroup"
ohos:height="$float:button_height"
ohos:width="match_parent"
ohos:theme="$pattern:button_green"
ohos:text="$string:btn_search_by_group"/>

ohos:id="$+id:searchResult"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:theme="$pattern:content_text"
ohos:text="$string:result"
ohos:scrollable="true"
ohos:text_alignment="start"/>


Create background_button_green_color.xml in graphic folder and add the below code.

http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
ohos:radius="20"/>
ohos:color="#1E7D13"/>

7. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.


Result

  1. Run Application on connected device, we can see below result.

https://preview.redd.it/0j2o45014fp71.png?width=328&format=png&auto=webp&s=c29675b20ef40e8b9c43b164e8a7fccc42ee7bb4
  1. Click on button, one by one see result as per below screen

https://preview.redd.it/vdsa3ftv4fp71.png?width=369&format=png&auto=webp&s=c596730975f46137da25a448c3be5c8e01ef5bb4

https://preview.redd.it/n8rlwrcv4fp71.png?width=375&format=png&auto=webp&s=5a7c00107cddcc20ab53f2eb9778c21be394635f
https://preview.redd.it/642agoou4fp71.png?width=374&format=png&auto=webp&s=097b3a10c9db80a104d6c3a541642915cfd1ffb7
https://preview.redd.it/zqweshkt4fp71.png?width=366&format=png&auto=webp&s=11f7f4255683c2d272d534e86aea2cc829af1486
https://preview.redd.it/hn01et9u4fp71.png?width=360&format=png&auto=webp&s=bda16b111363b468aec4a7eaeddf84f7ac6a20b9

Tips and Tricks

  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Do not forgot to add permission in config.json file.
  • Do not create, update, or delete too many indexes at one time.
  • While performing a search, you can create a search session. After the search is complete, close the session to release memory resources.

Conclusion

In this article, we have learnt Fusion search in Harmony OS.
Fusion search APIs enable users to perform both in-application and global search and provide a more accurate and efficient search.
Thanks for reading the article, please do like and comment your queries or suggestions.

References

Harmony OS: https://www.harmonyos.com/en/develop/?ha_source=hms1
Fusion search Overview:
https://developer.harmonyos.com/en/docs/documentation/doc-guides/database-fusion-search-overview-0000001050191132?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.09.24 08:06 lokeshsuryan Intermediate: WLAN (wireless local area network) in Harmony OS

Intermediate: WLAN (wireless local area network) in Harmony OS

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover WLAN with Java in Harmony OS.
A wireless LAN (WLAN) is a wireless local area network that links two or more devices using wireless communication to form a local area network (LAN) within a limited area such as a campus, school, computer laboratory home, or office building etc. A wireless local area network (WLAN) uses the radio, infrared, or other technologies to transmit data between devices that are not physically connected with each other. This gives users the ability to move around within the area and remain connected to the network.
When to Use
  • Check whether WLAN is enabled.
  • Obtain the WLAN connection and IP information.
  • Obtain the country/region code of a device.
  • Start a scan and obtain the scan result.
  • Check whether the device supports a specified feature.
Development Overview
You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.
Hardware Requirements
  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.
Software Requirements
  • Java JDK installation package.
  • DevEcho studio installed.
Follows the steps.
  1. Create HarmonyOS Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select ability template and click Next as per below image.
https://preview.redd.it/icc3cw5q5ep71.png?width=602&format=png&auto=webp&s=1b35325609e3e5bfcded011b1b75574e71862a34
  • Enter Project and Package Name and click on Finish.
https://preview.redd.it/3mfg7y3s5ep71.png?width=602&format=png&auto=webp&s=b95615f2dd3b93d522a8c3a9b9eb9a41788d8ed1
  1. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.
https://preview.redd.it/j78hcbjt5ep71.png?width=602&format=png&auto=webp&s=630c525f9f3d43a3f14e43aa10126bd74ef22722
  1. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values. To use the functions of the network management module, you must obtain the below permissions.
"module": { "reqPermissions": [ { "name": "ohos.permission.LOCATION" }, { "name": "ohos.permission.GET_WIFI_INFO" }, { "name": "ohos.permission.SET_WIFI_INFO" } ]
}
https://preview.redd.it/oabzfu8v5ep71.png?width=602&format=png&auto=webp&s=cf4c4096644c1575c4a0e1ed8167b767656dc896
  1. Create New Ability, as follows.
https://preview.redd.it/89aewcyn6ep71.png?width=602&format=png&auto=webp&s=db7fc090a26ab75f2340598eb27a9a1b547835ad
  1. Development Procedure.
Create MainAbilitySlice.java ability and add the below code.
package com.hms.wlannetworkmanagment.slice;
import ohos.bundle.IBundleManager;
import ohos.samples.wlan.ResourceTable;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.window.dialog.ToastDialog;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.security.SystemPermission;
import ohos.wifi.IpInfo;
import ohos.wifi.WifiDevice;
import ohos.wifi.WifiLinkedInfo;
import ohos.wifi.WifiScanInfo;
import ohos.wifi.WifiUtils;

import java.util.List;
import java.util.Optional;

/**
* MainAbilitySlice
*/
public class MainAbilitySlice extends AbilitySlice {
private static final String TAG = FeatureSlice.class.getSimpleName();

private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);

private Text logText;

u/Override
protected void onStart(Intent intent) {
super.onStart(intent);
setUIContent(ResourceTable.Layout_feature_slice_layout);
initComponents();
}

private void initComponents() {
Component scanButton = findComponentById(ResourceTable.Id_scan_button);
Component getInfoButton = findComponentById(ResourceTable.Id_info_button);
Component getCountryCodeButton = findComponentById(ResourceTable.Id_countryCode_button);
Component getSupportedFeatureButton = findComponentById(ResourceTable.Id_support_feature_button);

scanButton.setClickedListener(this::scanWifi);
getInfoButton.setClickedListener(this::getConnectedStateInfo);
getCountryCodeButton.setClickedListener(this::getCountryCode);
getSupportedFeatureButton.setClickedListener(this::getSupportFeature);

logText = (Text) findComponentById(ResourceTable.Id_log_text);
initStateText();
}

private void initStateText() {
WifiDevice wifiDevice = WifiDevice.getInstance(this);
boolean isWifiActive = wifiDevice.isWifiActive();
logText.append(isWifiActive ? "State : ON" : "State : OFF" + System.lineSeparator());
}

private void scanWifi(Component component) {
WifiDevice wifiDevice = WifiDevice.getInstance(this);
boolean isScanSuccess = wifiDevice.scan();
if (!isScanSuccess) {
HiLog.info(LABEL_LOG, "%{public}s", "Scan fail");
return;
}
List scanInfos = wifiDevice.getScanInfoList();

logText.append(System.lineSeparator());
for (WifiScanInfo wifiScanInfo : scanInfos) {
logText.append(wifiScanInfo.getSsid() + System.lineSeparator());
}
}

private void getConnectedStateInfo(Component component) {
WifiDevice wifiDevice = WifiDevice.getInstance(this);
boolean isConnected = wifiDevice.isConnected();
if (!isConnected) {
new ToastDialog(this).setText("Wifi is not connected").show();
return;
}
Optional linkedInfo = wifiDevice.getLinkedInfo();
String ssid = linkedInfo.get().getSsid();
Optional ipInfo = wifiDevice.getIpInfo();
int ipAddress = ipInfo.get().getIpAddress();
int gateway = ipInfo.get().getGateway();

logText.append(System.lineSeparator());
logText.append("SSID: " + ssid + System.lineSeparator());
logText.append("IP: " + ipAddress + System.lineSeparator());
logText.append("Gateway: " + gateway + System.lineSeparator());
}

private void getCountryCode(Component component) {
if (verifySelfPermission(SystemPermission.LOCATION) != IBundleManager.PERMISSION_GRANTED) {
HiLog.info(LABEL_LOG, "join getCountryCode method and the location permission is failed");
return;
}
WifiDevice wifiDevice = WifiDevice.getInstance(this);
String countryCode = wifiDevice.getCountryCode();

logText.append(System.lineSeparator());
logText.append("Country Code : " + countryCode + System.lineSeparator());
}

private void getSupportFeature(Component component) {
WifiDevice wifiDevice = WifiDevice.getInstance(this);
boolean isSupportInfra = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_INFRA);
boolean isSupport5G = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_INFRA_5G);
boolean isSupportPassPoint = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_PASSPOINT);
boolean isSupportP2P = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_P2P);
boolean isSupportHotSpot = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_MOBILE_HOTSPOT);
boolean isSupportAware = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_AWARE);
boolean isSupportApSta = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_AP_STA);
boolean isSupportWpa3Sae = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_WPA3_SAE);
boolean isSupportWpa3Suite = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_WPA3_SUITE_B);
boolean isSupportOwe = wifiDevice.isFeatureSupported(WifiUtils.WIFI_FEATURE_OWE);

logText.append(System.lineSeparator());
logText.append(isSupportInfra ? "Infra : Support" : "Infra : Not Support" + System.lineSeparator());
logText.append(isSupport5G ? "5G : Support" : "5G : Not Support" + System.lineSeparator());
logText.append(isSupportPassPoint ? "PassPoint : Support" : "PassPoint : Not Support" + System.lineSeparator());
logText.append(isSupportP2P ? "P2P : Support" : "P2P : Not Support" + System.lineSeparator());
logText.append(
isSupportHotSpot ? "Mobile HotPot : Support" : "Mobile HotPot : Not Support" + System.lineSeparator());
logText.append(isSupportAware ? "Aware : Support" : "Aware : Not Support" + System.lineSeparator());
logText.append(isSupportApSta ? "AP_STA : Support" : "AP_STA : Not Support" + System.lineSeparator());
logText.append(isSupportWpa3Sae ? "WPA3_SAE : Support" : "WPA3_SAE : Not Support" + System.lineSeparator());
logText.append(isSupportWpa3Suite ? "WPA3_Suit : Support" : "WPA3_Suit : Not Support" + System.lineSeparator());
logText.append(isSupportOwe ? "OWE : Support" : "OWE : Not Support" + System.lineSeparator());
}
}

Create ability_main.xml layout and add the below code.
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">

ohos:id="$+id:scan_button"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:button_background"
ohos:left_margin="24vp"
ohos:padding="10vp"
ohos:right_margin="24vp"
ohos:text="$string:scan"
ohos:text_alignment="center"
ohos:text_size="16fp"
ohos:top_margin="20vp"/>

ohos:id="$+id:info_button"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:button_background"
ohos:left_margin="24vp"
ohos:padding="10vp"
ohos:right_margin="24vp"
ohos:text="$string:get_connected_info"
ohos:text_alignment="center"
ohos:text_size="16fp"
ohos:top_margin="20vp"/>

ohos:id="$+id:countryCode_button"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:button_background"
ohos:left_margin="24vp"
ohos:padding="10vp"
ohos:right_margin="24vp"
ohos:text="$string:get_country_code"
ohos:text_alignment="center"
ohos:text_size="16fp"
ohos:top_margin="20vp"/>

ohos:id="$+id:support_feature_button"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:button_background"
ohos:left_margin="24vp"
ohos:padding="10vp"
ohos:right_margin="24vp"
ohos:text="$string:get_support_feature"
ohos:text_alignment="center"
ohos:text_size="16fp"
ohos:top_margin="20vp"/>

ohos:id="$+id:log_text"
ohos:height="250vp"
ohos:width="match_parent"
ohos:background_element="$graphic:text_background"
ohos:left_margin="24vp"
ohos:multiple_lines="true"
ohos:padding="10vp"
ohos:right_margin="24vp"
ohos:scrollable="true"
ohos:text_alignment="topleft"
ohos:text_size="16fp"
ohos:top_margin="10vp"/>

Create button_background.xml in graphic folder and add the below code.


  1. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.
https://preview.redd.it/8zyc8gtz5ep71.png?width=693&format=png&auto=webp&s=02db031a4e322e51ba07ab1e56e0f670f65d6393
Result
Provide location permission and Click on UI ‘Scan button. It will show result as per screen.

https://preview.redd.it/2kun4u566ep71.png?width=364&format=png&auto=webp&s=97e663eed9e29760e86a14243cae1bb124992413

https://preview.redd.it/3c4sazh86ep71.png?width=365&format=png&auto=webp&s=8f2d557700a64cf7ab4098cdbed396b26fba8db5
Click on UI ‘Get Connected Info’ button. It will show connected device and ip address as per below screen.

https://preview.redd.it/obius9ka6ep71.png?width=369&format=png&auto=webp&s=b61fd3447d39aa14cc8837686488d3b420b07cc3
Click on UI ‘Get Country Code’ button. It will show connected device Country code as per below screen.

https://preview.redd.it/ge549x1c6ep71.png?width=366&format=png&auto=webp&s=f8059b1fdd035f54e0d8c44d22bd7ae6e011bce0
Click on UI ‘Get Support Feature button. It will supported feature by connected device as per below screen.

https://preview.redd.it/1sqq8mhd6ep71.png?width=377&format=png&auto=webp&s=8e90cd7463afef3c921eb2e54a88d6e287811f01
Tips and Tricks
  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Network task or any long running task should run in background thread.· Make sure network permissions added into config.json file.
Conclusion
In this article, we have learnt how connect two or more devices using wireless communication to form a local area network (LAN) within a limited area such as a campus, school, computer laboratory home, or office building etc. A wireless local area network (WLAN) uses the radio, infrared, or other technologies to transmit data between devices that are not physically connected with each other.
Thanks for reading the article, please do like and comment your queries or suggestions.
References
Harmony OS: https://www.harmonyos.com/en/develop/?ha_source=hms1
WLAN: https://developer.harmonyos.com/en/docs/documentation/doc-guides/connectivity-wlan-overview-0000000000030016?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.09.09 07:54 lokeshsuryan Intermediate: Integration of Huawei Crash service in Harmony OS

Intermediate: Integration of Huawei Crash service in Harmony OS

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover Huawei Crash Service with Java in Harmony OS.
The AppGallery Connect Crash service provides a powerful lightweight solution for app crash problems. This service helps us to minimize crash risks. Also this service integration is relatively simple and doesn’t require coding. The Crash Service provides crash reports which are easy to reference and analyze. This service helps quickly to detect, locate, and resolve app crashes (unexpected exits of apps), and have access to highly readable crash reports in real time.
After you integrate the Crash SDK into your app, it will be initialized automatically when your app is launched. When an app crash occurs, the SDK will report the crash information to HUAWEI Analytics. A readable report will be generated in 5 to 10 minutes, helping you to quickly detect, locate, and rectify the problem.
https://preview.redd.it/kjy8229b2fm71.png?width=602&format=png&auto=webp&s=7ec304859ea60340c90f56e8dad411db0f47bc39

Crash Service various features

  1. You can view information about a specific crash, and analyze the app and Android versions with the crash.
  2. The Crash service can also detect major crashes in real time. After you enable crash notifications, App Gallery Connect can send you an email when a major crash occurs.
  3. A readable report will be generated in 5 to 10 minutes, helping you to delete, locate and rectify the problem.
  4. The Crash service automatically categorizes crashes, and provides indicator data of the crashes allowing you to prioritize the most important crashes.
  5. You can also view information about the app, operating system, and device corresponding to a specific crash, as well as the crashed stack.
  6. The last-hour crash report allows you to monitor the quality of your app in real time.

Development Overview

You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • DevEcho studio installed.

Follows the steps.

  1. Create Harmony OS Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select Empty Ability(Java) template and click Next as per below image.
https://preview.redd.it/xgu5qzod2fm71.png?width=689&format=png&auto=webp&s=c659abe0e71959c12b297c3b461e35f4912cf20e
  • Enter Project Name and Package Name and click on Finish.
https://preview.redd.it/sebtbsff2fm71.png?width=685&format=png&auto=webp&s=cf469ecdd3678012ff89372c0c1c9202ec707e42
  1. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.
https://preview.redd.it/f2ncbstl2fm71.png?width=602&format=png&auto=webp&s=73672efbf62afd70489377ff2b601ea9494e538c
  1. Add the below maven URL in build.gradle(Project level) file under the repositories of buildscript, dependencies, for more information refer Add Configuration.
classpath 'com.huawei.agconnect:agcp-harmony:1.1.0.200' maven { url 'https://developer.huawei.com/repo/' }
  1. Add the below plugin and dependencies in build.gradle(App level)
apply plugin: 'com.huawei.agconnect'
implementation 'com.huawei.agconnect:agconnect-crash-harmony:1.1.0.200'
  1. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values.

https://preview.redd.it/2l1xly4o2fm71.png?width=602&format=png&auto=webp&s=a76264011c3c615e7fbd227b66439c9bb94ec38a
  1. Create New > Ability, as follows.
https://preview.redd.it/q6yc6i8q2fm71.png?width=690&format=png&auto=webp&s=f425f34d474ac57e7d464ec725f702137b576b2a
  1. Development Procedure.
Create MainAbility.java ability and add the below code.
package com.hms.crashkitharmony.slice;
import com.hms.crashkitharmony.ResourceTable; import com.huawei.agconnect.crash.AGConnectCrash; import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.content.Intent; import ohos.agp.components.Button; import ohos.agp.components.Component; import ohos.hiviewdfx.HiLog; import ohos.hiviewdfx.HiLogLabel;
public class MainAbilitySlice extends AbilitySlice { HiLogLabel LABEL_LOG; u/Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "Main_ability"); Button button = (Button) findComponentById(ResourceTable.Id_btn_get_crash); Button arithmeticCrashButton = (Button) findComponentById(ResourceTable.Id_btn_arithmetic_crash); button.setClickedListener(component -> AGConnectCrash.getInstance().testIt(MainAbilitySlice.this)); arithmeticCrashButton.setClickedListener(component -> { AGConnectCrash.getInstance().setCustomKey("intkey",1234); AGConnectCrash.getInstance().setCustomKey("floatKey",2.5f); AGConnectCrash.getInstance().setCustomKey("doubleKey",12.3456); AGConnectCrash.getInstance().setCustomKey("stringKey","qwerty"); AGConnectCrash.getInstance().setUserId("absd"); AGConnectCrash.getInstance().log(HiLog.FATAL,"This User generated crash FATAL"); AGConnectCrash.getInstance().log(HiLog.ERROR,"This User generated crash ERROR"); AGConnectCrash.getInstance().log(HiLog.INFO,"This User generated crash INFO"); AGConnectCrash.getInstance().log(HiLog.LOG_APP,"This User generated crash LOG_APP"); AGConnectCrash.getInstance().log(HiLog.WARN,"This User generated crash WARN"); AGConnectCrash.getInstance().log(HiLog.DEBUG,"This User generated crash DEBUG"); AGConnectCrash.getInstance().log("This User generated crash without crash level"); int divisor=0; int value=100; int result=value/divisor; HiLog.info(LABEL_LOG, "result: " +result);
}); }
u/Override public void onActive() { super.onActive(); }
u/Override public void onForeground(Intent intent) { super.onForeground(intent); } }
Create ability_main.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:margin="20vp"
ohos:orientation="vertical">
ohos:id="$+id:btn_get_crash"
ohos:height="90vp"
ohos:width="match_parent"
ohos:background_element="$graphic:background_button_green_color"
ohos:start_margin="20vp"
ohos:end_margin="20vp"
ohos:text="$string:mainability_make_crash"
ohos:text_color="#ffffff"
ohos:text_size="32fp"/>
ohos:id="$+id:btn_arithmetic_crash"
ohos:height="90vp"
ohos:width="match_parent"
ohos:background_element="$graphic:background_button_green_color"
ohos:top_margin="20vp"
ohos:start_margin="20vp"
ohos:end_margin="20vp"
ohos:text="$string:mainability_arithmetic"
ohos:text_color="#ffffff"
ohos:text_size="32fp"/>

Create background_button_green_color.xml in graphic folder and add the below code.

ohos:shape="rectangle">
ohos:radius="20"/>
ohos:color="#1E7D13"/>

  1. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.
https://preview.redd.it/xpyklvfs2fm71.png?width=693&format=png&auto=webp&s=7bac8a3f5a84dbd2b0b0e72339d1fed1d815bead

Result

  1. Run Application on connected device, we can see below result.

https://preview.redd.it/m0tufdyu2fm71.png?width=370&format=png&auto=webp&s=f103e3edbc7f879ff5ea2ef1500304a4a4d10734
  1. Click on “Make Arithmetic exception” button, application will close unexpected check below result on app gallery.

https://preview.redd.it/aro4rb2x2fm71.png?width=602&format=png&auto=webp&s=095738de317ae2a1b24e9f7ab268292462b2a4d1

https://preview.redd.it/eyt96b9y2fm71.png?width=672&format=png&auto=webp&s=7ec07f9159f218aa8d12b71633ca93ff03ad3226

https://preview.redd.it/pwuiijiz2fm71.png?width=602&format=png&auto=webp&s=257182a322fd2b808da3c9ff34c17dd446a27a32

https://preview.redd.it/qgt4niq03fm71.png?width=658&format=png&auto=webp&s=e83df5906fdeef3025fa8abf02acaeaaf24f0dc5

https://preview.redd.it/1tie9m423fm71.png?width=602&format=png&auto=webp&s=ff86e8c38cff01cff52470b07e443b0e75b66f09

https://preview.redd.it/c46jkhc33fm71.png?width=602&format=png&auto=webp&s=ecc4650b6836881999b2f8732be286718ba57a85

Tips and Tricks

  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Do not forgot to add permission in config.json file.
  • Do not forgot to add dependencies in build.gradle.
  • Do not forgot to enable crash service.

Conclusion

In this article, we have learnt Crash Service in Harmony OS.
Huawei Crash services makes easier to find the crashes and helps you to make crash free application also learned how to view and analyze crashes and custom crash reports and device information in which it is crashed in AppGallery Connect.
Thanks for reading the article, please do like and comment your queries or suggestions.

References

Harmony OS:https://www.harmonyos.com/en/develop/?ha_source=hms1
Crash Service Overview:
https://developer.huawei.com/consumeen/doc/development/AppGallery-connect-Guides/agc-crash-getstarted-harmonyos-0000001185398953 /?ha_source=hms
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.09.03 08:04 lokeshsuryan Beginner: Integration of Huawei Accelerate Kit in kotlin (Android)

Beginner: Integration of Huawei Accelerate Kit in kotlin (Android)

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover integration of HUAWEI Accelerate Kit in Android.
HUAWEI Accelerate Kit provides multi-thread programming APIs, enhancing the program performance and facilitating the development of multi-core and multi-thread apps, and also provides the multi-thread acceleration capability that efficiently improves concurrent execution of multiple threads. Accelerate Kit provides a new multithreaded programming method using multithread-lib. It unlatched you from the thread management details, so you can focus on developing apps that can fully utilize the multi-core hardware capability of the system, promising more efficient running.

Use Cases

  • Concurrent execution of tasks
  • Serial execution of tasks
  • Synchronization of tasks

Development Overview

You need to install Android studio IDE and I assume that you have prior knowledge about the Android and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • Android studio IDE installed.
  • Android 5.0 or later.

Follows the steps.

  1. Create Android Project.
  • Open Android Studio.
  • Click NEW Project, select a Project Templet.
  • Select Native C++.
  • Enter project name and Package Name and click on Finish:
https://preview.redd.it/pu2y50i198l71.png?width=678&format=png&auto=webp&s=8d828d9e7b0dbfd5950665d894ecd4537c36c0e4
  1. Modify the build.gradle file. Open the /app/build.gradle file and NDK build support lines as follows.
  • ·arguments "-DANDROID_STL=c++_shared": multithread-lib depends on libc++. Therefore, c++_shared needs to be declared in the CMake compilation options. Otherwise, some functions will fail to work.
  • abiFilters "arm64-v8a", "armeabi-v7a": multithread-lib supports only arm64-v8a and armeabi-v7a.
  • jniLibs.srcDirs = [‘libs']: specifies the directory of the .so files.

https://preview.redd.it/3x3twfq398l71.png?width=602&format=png&auto=webp&s=672dd042b7030f2657225154a22d3a1276103484
  1. Download the SDK package from this link and unzip.
  2. Copy the header files in the SDK to the resource library.
In the /app directory, create an include folder. Copy the files to the created include folder as per below screen.
https://preview.redd.it/mp69rk88b8l71.png?width=602&format=png&auto=webp&s=d9ddb475b96de1d84a7b8e6d42d42bab2ad95d57
  1. Copy the .so files in the SDK to the resource library.
  • Under the /app/libs directory, create two subdirectories: arm64-v8a and armeabi-v7a.
  • Copy the libdispatch.so, libdispatch_stat.so, and libBlocksRuntime.so files in the /lib64 directory of the SDK to the /libs/arm64-v8a directory of Android Studio.
  • Copy the libdispatch.so, libdispatch_stat.so, and libBlocksRuntime.so files in the /lib directory of the SDK to the /libs/armeabi-v7a directory of Android Studio.
https://preview.redd.it/i973xea898l71.png?width=602&format=png&auto=webp&s=40c83f386aa64f3716a7257abe7d2e185e1d1d98
  1. Modify the CMakeLists.txt file in the app/src/main/cpp directory as shown below.
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library. native-lib
# Sets the library as a shared library. SHARED
# Provides a relative path to your source file(s). native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build.
target_include_directories( native-lib PRIVATE ${CMAKE_SOURCE_DIR}/../../../include)
find_library( # Sets the name of the path variable. log-lib
# Specifies the name of the NDK library that # you want CMake to locate. log )
add_library( dispatch SHARED IMPORTED)
set_target_properties( dispatch PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}/libdispatch.so)
add_library( BlocksRuntime SHARED IMPORTED)
set_target_properties( BlocksRuntime PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}/libBlocksRuntime.so)
add_custom_command( TARGET native-lib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}/libdispatch.so ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}/libBlocksRuntime.so ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/ )
target_compile_options(native-lib PRIVATE -fblocks)
# Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library. native-lib dispatch BlocksRuntime # Links the target library to the log library # included in the NDK. ${log-lib} )
  1. Register as Huawei developer and complete identity verification in Huawei developer’s website, refer to register a Huawei ID.
  2. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > app > Tasks > android, and then click signing Report, as follows.
https://preview.redd.it/41fm852b98l71.png?width=680&format=png&auto=webp&s=008b84eeaeaf8cb13e889b37322742a6a60dc385
or
Also we can generate SHA-256 using command prompt.
To generating SHA-256 certificate fingerprint use below command.
keytool -list -v -keystore D:\studio\projects_name\file_name.keystore -alias alias_name
https://preview.redd.it/vdkuuemc98l71.png?width=602&format=png&auto=webp&s=21c7390752fa4c32711f5fbaf234b4d527f0ddd7
  1. Create an App in AppGallery Connect.
  2. Add the below plugin and dependencies in build.gradle(App level)
implementation 'com.huawei.hms:stats:4.0.3.302' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
  1. Open AndroidManifest file and add below permissions. `
  2. Development Procedure.
Create a kotlin class MainActivity.kt inside your package.MainActivity.ktpackage com.example.multithreaddemo
import android.annotation.SuppressLint import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() { private var pi = 0.0 u/SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) calculatePIValueBTn.setOnClickListener { val startExecutionTime= System.currentTimeMillis() val stringPI=stringFromJNI() val endExecutionTime= System.currentTimeMillis() val executionTime=endExecutionTime-startExecutionTime sample_text.text="Acceleration kit exe time: $executionTime milli second value of PI $stringPI" } singleThreadExeBTn.setOnClickListener { val startExecutionTime= System.currentTimeMillis() pi=calculatePI(0, 1) val endExecutionTime= System.currentTimeMillis() val executionTime=endExecutionTime-startExecutionTime sample_text.text="Single Thread execution time: $executionTime milli second value of PI $pi"
} multipleThreadExeBTn.setOnClickListener { val startExecutionTime= System.currentTimeMillis() pi=calculatePIMultiThread() val endExecutionTime= System.currentTimeMillis() val executionTime=endExecutionTime-startExecutionTime sample_text.text="Multiple Thread execution time: $executionTime milli second value of PI $pi" } // Example of a call to a native method
}
private fun calculatePI(initValue: Long, counter: Int) : Double { val n: Long = 1000000000 var _pi = 0.0 var sign: Double var j: Long = initValue // pi calc formula: pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 ... // pi calc formula: pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 ... while (j <= n) { sign = (if (j and 1 == 0L) -1 else 1).toDouble() _pi += 4 * sign / (2 * j - 1) j +=counter } return _pi }
private fun calculatePIMultiThread(): Double { var initValue = 0L val maxThread = 8 val threads: MutableList = ArrayList() var thread: Thread // Start threads ... while (initValue < maxThread) { thread = object : Thread() { override fun run() { val piValue: Double = calculatePI(initValue, maxThread) pi += piValue Log.d("dispatch", "Inside thread. calcPi = $piValue, mPi = $pi") } } threads.add(thread) thread.start() initValue++ }
// Wait until all threads finish. for (tt in threads) { try { tt.join() } catch (e: InterruptedException) { e.printStackTrace() } } return pi } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ external fun stringFromJNI(): String
companion object { // Used to load the 'native-lib' library on application startup. init { System.loadLibrary("native-lib") } } }

Create activity_main.xml layout file under app > main > res > layout folder.

activity_main.xml




  1. To build apk and run in device, choose Build > Generate Signed Bundle/APK > Build for apk or Build and Run into connected device follow the steps.
https://preview.redd.it/z59ov7k9b8l71.png?width=670&format=png&auto=webp&s=f2d00e51d3087585fa08a17e139e0b672c5c58f6
Result
The output response of HMS Acceleration Kit is quite faster than the kotlin multithreading code. Although, it depends on your chipset also.
https://preview.redd.it/dl2uhd6oa8l71.png?width=306&format=png&auto=webp&s=16b43a5434b4feb6c1f361f92db1c29f4a072dd8
  1. Click on “Calculate PI Value” button, it will calculate PI value and shows below result.
https://preview.redd.it/pojopyipa8l71.png?width=304&format=png&auto=webp&s=bc4039f1290fa475b442597c6604f7fdbcccc07d
  1. Click on “Calculate PI Single Thread” button, it will calculate PI value and will check how much time it will take to execute.
https://preview.redd.it/j2x4no0ra8l71.png?width=305&format=png&auto=webp&s=ebaa286071a1165ab82ec660fdf7c3e89048543d
  1. Click on “Calculate PI Multiple Thread” button, it will calculate PI value using multiple thread and will check how much time it will take to execute.
https://preview.redd.it/woh7hhbsa8l71.png?width=313&format=png&auto=webp&s=596a48cedbf848723d7f5324e2aed1dd3b6f8169

Tips and Tricks

  • Always use the latest version of the library.
  • Add header file in include folder without fail.
  • Add .SO in libs folder in respective subdirectories without fail.
  • Make sure dependencies added in build files.

Conclusion

In this article, we have learnt integration of HUAWEI Accelerate kit. HUAWEI Accelerate Kit provides multi-thread programming APIs, enhancing the program performance and facilitating the development of multi-core and multi-thread apps and increased app overall performance.

References

Accelerate Kit:
https://developer.huawei.com/consumeen/doc/development/graphics-Guides/introduction-0000001077053686?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.08.27 06:27 lokeshsuryan Intermediate: Obtaining Device Location in Harmony OS

Intermediate: Obtaining Device Location in Harmony OS

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover Device Location with Java in Harmony OS.
The Location service provides user current device location. HarmonyOS, mobile devices can obtain accurate real-time location or last known location of a mobile device. Mobile devices plays an important role in people's daily routines, whether it can be for looking at the weather forecast, truck routing, local news, navigating, historical traffic patterns and beyond. All these activities are so much associated with the location services on mobile devices.

Limitations and Constraints

Your application can use the location function only after the user has granted location permission. If user doesn’t provide location permission, then the system will not provide the location service for any application.

When to Use

To obtain the real-time location or last known location of a mobile device can call location-related APIs in HarmonyOS. If you want lower power consumption when the real-time location of the device is not needed, you may consider obtaining the last known location of the device.

Development Overview

You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • DevEcho studio installed.

Follows the steps.

  1. Create Unity Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select ability template and click Next as per below image.

https://preview.redd.it/hyamg84cutj71.png?width=689&format=png&auto=webp&s=bd5ae44c47fb5e2dd945972ac49a0b2d248b5514
  • Enter Project and Package Name and click on Finish.
https://preview.redd.it/u6obg06futj71.png?width=685&format=png&auto=webp&s=2cbe2c862c6b7dd8f01142e2efe993890114b3c8
  1. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.

https://preview.redd.it/63zplmpiutj71.png?width=602&format=png&auto=webp&s=8fcff8c854b2453858b9f0a9206113cb60062e9a
  1. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values. For Accessing location service define below permission in config.json file.
"reqPermissions": [
{
"name": "ohos.permission.LOCATION",
"reason": "$string:reason_description",
"usedScene": {
"ability": [
"com.hms.locationservice.MainAbility"
],
"when": "inuse"
}
},{
"name": "ohos.permission.LOCATION_IN_BACKGROUND",
"reason": "$string:reason_description_backgroun",
"usedScene": {
"ability": [
"com.hms.locationservice.MainAbility"
],
"when": "inuse"
}
},
{"name" : "ohos.permission.GET_NETWORK_INFO"},
{"name" : "ohos.permission.SET_NETWORK_INFO"},
{"name" : "ohos.permission.INTERNET"}
]
https://preview.redd.it/g8tq778nutj71.png?width=602&format=png&auto=webp&s=cd87ca40fc3708dd362b0e72505d82c6859ae0a7
4. Create New Ability as follows

https://preview.redd.it/5anmyghputj71.png?width=690&format=png&auto=webp&s=5a4d87a419402ecca5bbd49f766f8e8b1dc27b48
  1. Development Procedure.
Create MainAbility.java ability and add the below code.
package com.hms.locationservice;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Text;
import ohos.bundle.IBundleManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.location.*;
import java.io.IOException;

public class MainAbility extends Ability {
Locator locator;
MyLocatorCallback locatorCallback;
HiLogLabel LABEL_LOG;
RequestParam requestParam;
public static final int MY_PERMISSIONS_REQUEST_LOCATION=100;
Button getCurrentAddressBtn,stopAccessLoation,getContinuousUserLocation;
Text userAddress;
u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "Main_ability");
userAddress=(Text)findComponentById(ResourceTable.Id_userAddress);
getCurrentAddressBtn=(Button)findComponentById(ResourceTable.Id_getCurrentAddressBtn);
getContinuousUserLocation=(Button)findComponentById(ResourceTable.Id_getContinuousUserLocation);
stopAccessLoation=(Button)findComponentById(ResourceTable.Id_stopAccessLoation);
locator = new Locator(MainAbility.this);
requestParam = new RequestParam(RequestParam.PRIORITY_ACCURACY, 10, 0);
locatorCallback = new MyLocatorCallback();
requestPermission();
getCurrentAddressBtn.setClickedListener(component->{
locator.requestOnce(requestParam, locatorCallback);
});
getContinuousUserLocation.setClickedListener(component->{
locator.stopLocating(locatorCallback);
locator.startLocating(requestParam, locatorCallback);
});
stopAccessLoation.setClickedListener(component->{
locator.stopLocating(locatorCallback);
});

}

private void requestPermission() {
if (verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTEDverifySelfPermission("ohos.permission.LOCATION_IN_BACKGROUND") != IBundleManager.PERMISSION_GRANTED) {
// The application has not been granted the permission.
if (canRequestPermission("ohos.permission.LOCATION")canRequestPermission("ohos.permission.LOCATION_IN_BACKGROUND")) {
// Check whether permission authorization can be implemented via a dialog box (at initial request or when the user has not chosen the option of "don't ask again" after rejecting a previous request).
requestPermissionsFromUser(
new String[] { "ohos.permission.LOCATION","ohos.permission.LOCATION_IN_BACKGROUND" } , MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// Display the reason why the application requests the permission and prompt the user to grant the permission.
}
} else {

// The permission has been granted.
}
}


public class MyLocatorCallback implements LocatorCallback {
u/Override
public void onLocationReport(Location location) {
GeoConvert geoConvert = new GeoConvert();
HiLog.info(LABEL_LOG, "geLatitude:" +location.getLatitude()+"\n geLatitude"+location.getLongitude());

try {
userAddress.setText("User Current address: "+geoConvert.getAddressFromLocation(location.getLatitude(), location.getLongitude(), 1));
} catch (IOException e) {
e.printStackTrace();
}


}

u/Override
public void onStatusChanged(int type) {
if (type == 3) {
HiLog.info(LABEL_LOG, "geLatitude:" +"Stop Location accessing");
}else
HiLog.info(LABEL_LOG, "geLatitude:" +"onChange status");

}

u/Override
public void onErrorReport(int type) {
HiLog.info(LABEL_LOG, "geLatitude:" +"error");

}
}




u/Override
protected void onBackground() {
super.onBackground();
locator.stopLocating(locatorCallback);
}

u/Override
public void onRequestPermissionsFromUserResult (int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// Match requestCode of requestPermissions.
if (grantResults.length > 0
&& grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
locator.startLocating(requestParam, locatorCallback);
// The permission is granted.
//Note: During permission check, an interface may be considered to have no required permissions due to time difference. Therefore, it is necessary to capture and process the exception thrown by such an interface.
} else {
// The permission request is rejected.
}
return;
}
default:
throw new IllegalStateException("Unexpected value: " + requestCode);
}
}
}
Create ability_main.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">

ohos:id="$+id:userAddress"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_alignment="horizontal_center"
ohos:text_color="#000000"
ohos:text_size="30fp"/>
ohos:id="$+id:getCurrentAddressBtn"
ohos:height="90vp"
ohos:width="match_parent"
ohos:background_element="$graphic:background_button_green_color"
ohos:margin="10vp"
ohos:text="$string:entry_location"
ohos:text_color="#ffffff"
ohos:text_size="25fp"/>

ohos:id="$+id:getContinuousUserLocation"
ohos:height="90vp"
ohos:width="match_parent"
ohos:background_element="$graphic:background_button_green_color"
ohos:margin="10vp"
ohos:text="$string:entry_continuous_location"
ohos:text_color="#ffffff"
ohos:text_size="25fp"/>

ohos:id="$+id:stopAccessLoation"
ohos:height="90vp"
ohos:width="match_parent"
ohos:background_element="$graphic:background_button_green_color"
ohos:margin="10vp"
ohos:text="$string:entry_stop_location"
ohos:text_color="#ffffff"
ohos:text_size="25fp"/>


Create background_button_green_color.xml in graphic folder and add the below code.

http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
ohos:radius="20"/>
ohos:color="#1E7D13"/>

6. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.
https://preview.redd.it/jhlh9gf0vtj71.png?width=693&format=png&auto=webp&s=a216eca3e864e96083039fdb0e47a18473c76211

Result

  1. Run Application on connected device and provide respective permission as per below image
https://preview.redd.it/q6yiq6v3vtj71.png?width=370&format=png&auto=webp&s=904af380441019bbab9b3113c9bd29a88df620d6
2. Click on “Get Current Location” button for fetching current location as per below screen.

https://preview.redd.it/rugkbyj6vtj71.png?width=365&format=png&auto=webp&s=c8e5a5dee30234d000cd035282d3404607f61568
https://preview.redd.it/2gwaqeu7vtj71.png?width=452&format=png&auto=webp&s=94c547656083a3a7b5aa861ecae58f10b21c345d
  1. Click on “Get Continuous Location” button, for fetching continuous locations as per pre define interval or distance per below images.
https://preview.redd.it/nl6ut3gavtj71.png?width=602&format=png&auto=webp&s=94a4fd0d4d8ef5bb3b6291c964ea3011b9d74948
4. Click on “Stop access location” to stop access location as per below images.

https://preview.redd.it/njxkmgrcvtj71.png?width=675&format=png&auto=webp&s=52f45f007779437b1465fd35c97c5d30d0295e1a

Tips and Tricks

  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Do not forgot to add permission in config.json file.

Conclusion

In this article, we have learnt Device Location in Harmony OS. Location related API in harmonyOS we can access user device real time location. If you want lower power consumption when the real-time location of the device is not needed, you may consider obtaining the last known location of the device user.
Thanks for reading the article, please do like and comment your queries or suggestions.

References

Harmony OS:https://www.harmonyos.com/en/develop/?ha_source=hms1
Location Overview: https://developer.harmonyos.com/en/docs/documentation/doc-guides/device-location-overview-0000000000031896?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.08.20 06:24 lokeshsuryan Intermediate: Data management (Distributed Data Service) in Harmony OS

Intermediate: Data management (Distributed Data Service) in Harmony OS
Introduction
Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover Distributed Data Service (DDS) with Java in Harmony OS.
DDS provides the capability to store data in the databases of different devices. Using DDS API service we can save data in Distributed database. DDS synchronize application data between different devices and handles database version compatibility issues and data synchronization conflicts easily.

Working Principles

DDS supports distributed management of application data. Data can be synchronize between login with same account.

https://preview.redd.it/olunzcuzvfi71.png?width=602&format=png&auto=webp&s=80296076e474c293c64f736641cdb0d7f8e84cca

When to Use

DDS synchronizes application data on different devices in a distributed way. When an application on a device inserts, deletes, or updates data in the distributed database, the same application on another device can obtain the data changes.

Development Overview

You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • DevEcho studio installed.

Follows the steps.

  1. Create Unity Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select ability template and click Next as per below image.

https://preview.redd.it/rn23rki7wfi71.png?width=689&format=png&auto=webp&s=e522b8a883310fa4caf23845f3c7d2a010b71b57
  • Enter Project and Package Name and click on Finish.
https://preview.redd.it/2a3hdc89wfi71.png?width=685&format=png&auto=webp&s=5e4800ef8f27909be2af928b1c51d48ad3264150
  1. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.
https://preview.redd.it/k01j4fbbwfi71.png?width=800&format=png&auto=webp&s=82b65d2b00b35a2fa618885a90a7190484028880
  1. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values. Add below permission to access distributed database.
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
https://preview.redd.it/iyqzfspcwfi71.png?width=602&format=png&auto=webp&s=d492e5097c846565f8d7dfb2fe48ef04487cb89a
  1. Create New Ability as follows.
https://preview.redd.it/vw2pt73dwfi71.png?width=690&format=png&auto=webp&s=8f86e691d409b4aa3928f850380f530dd0140729
  1. Development Procedure.
Create MainAbilitySlice.java ability and add the below code.
package com.hms.distributeddataservicedevelopment.slice;

import com.hms.distributeddataservicedevelopment.KvStoreObserverClient;
import com.hms.distributeddataservicedevelopment.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Text;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.data.distributed.common.*;
import ohos.data.distributed.device.DeviceFilterStrategy;
import ohos.data.distributed.device.DeviceInfo;
import ohos.data.distributed.user.SingleKvStore;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.ArrayList;
import java.util.List;

public class MainAbilitySlice extends AbilitySlice {
public static SingleKvStore singleKvStore;
KvManager kvManager;
HiLogLabel LABEL_LOG;
Button readKVDetailBtn;
Button storeKVDetailBtn;
Button syncDataBtn;
Text user_detail;
u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
readKVDetailBtn = (Button) findComponentById(ResourceTable.Id_readKVdetail);
storeKVDetailBtn = (Button) findComponentById(ResourceTable.Id_storeKVdetail);
syncDataBtn = (Button) findComponentById(ResourceTable.Id_push_data);
user_detail = (Text) findComponentById(ResourceTable.Id_user_deial);

Context context = getApplicationContext();
LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "Main_ability");
KvManagerConfig config = new KvManagerConfig(context);
kvManager = KvManagerFactory.getInstance().createKvManager(config);
KvStoreObserver kvStoreObserverClient = new KvStoreObserverClient();
createSingleKVstore();
singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserverClient);
storeKVDetailBtn.setClickedListener(component -> {
present(new StoreKVdetail(),new Intent());
});
readKVDetailBtn.setClickedListener(component -> {
readKVStore();
});
syncDataBtn.setClickedListener(component -> {
List deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
List deviceIdList = new ArrayList<>();
for (DeviceInfo deviceInfo : deviceInfoList) {
deviceIdList.add(deviceInfo.getId());
}
singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
});

}

private void readKVStore() {
try {
String key_user_name = "user_name";
String key_user_detail = "user_detail";
String value_user_name = singleKvStore.getString(key_user_name);
String value_user_detail = singleKvStore.getString(key_user_detail);
user_detail.setText("Fetch detail from KV Store:- \n User Name:- "+ value_user_name+"\n User Detail: "+value_user_detail);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "getString:" + e.getKvStoreErrorCode());
}
}

private void createSingleKVstore() {
try {
Options options = new Options();
options.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION);
String storeId = "testAppDemo";
singleKvStore = kvManager.getKvStore(options, storeId);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "getKvStore:" + e.getKvStoreErrorCode());
}
}

u/Override
public void onActive() {
super.onActive();
}

u/Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}
Create ability_main.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:padding="10vp"
ohos:orientation="vertical">
ohos:id="$+id:storeKVdetail"
ohos:height="80vp"
ohos:text_color="#ffffff"
ohos:text_size="30fp"
ohos:top_margin="20vp"
ohos:background_element="$graphic:background_button_yellow_green"
ohos:text="$string:mainability_write_single_kv_store"
ohos:width="match_parent"/>
ohos:id="$+id:readKVdetail"
ohos:height="80vp"
ohos:text_color="#ffffff"
ohos:text_size="30fp"
ohos:top_margin="20vp"
ohos:background_element="$graphic:background_button_yellow_green"
ohos:text="$string:mainability_read_single_kv_store"
ohos:width="match_parent"/>
ohos:id="$+id:push_data"
ohos:height="80vp"
ohos:text_color="#ffffff"
ohos:text_size="30fp"
ohos:top_margin="20vp"
ohos:background_element="$graphic:background_button_yellow_green"
ohos:text="$string:mainability_sync_data_other_device"
ohos:width="match_parent"/>
ohos:id="$+id:user_deial"
ohos:height="match_content"
ohos:width="match_parent"
ohos:margin="10vp"
ohos:text_alignment="horizontal_centervertical_center"
ohos:text_size="32fp"
ohos:multiple_lines="true"/>



Create StoreKVdetail.java ability and add the below code.
package com.hms.distributeddataservicedevelopment.slice;

import com.hms.distributeddataservicedevelopment.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.ToastDialog;
import ohos.data.distributed.common.KvStoreException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import static com.hms.distributeddataservicedevelopment.slice.MainAbilitySlice.singleKvStore;

public class StoreKVdetail extends AbilitySlice {
TextField userDetailTextField,userNameTextField;
Button saveUserDetilBtn;
Text errorTextUserName,errorTextUserDetail;
String userName,userDetail;
HiLogLabel LABEL_LOG;
u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_store_kv_detail_layout);
userDetailTextField = (TextField) findComponentById(ResourceTable.Id_enter_user_detail);
userNameTextField = (TextField) findComponentById(ResourceTable.Id_enter_user_name);
saveUserDetilBtn = (Button) findComponentById(ResourceTable.Id_save_detil_btn);
errorTextUserName = (Text) findComponentById(ResourceTable.Id_error_tip_text_user_name);
errorTextUserDetail = (Text) findComponentById(ResourceTable.Id_error_tip_text_user_detail);
LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "storekvdetail_ability");

userDetailTextField.addTextObserver((s, i, i1, i2) -> {
enableDisableBtn();

});
userNameTextField.addTextObserver((s, i, i1, i2) -> {
enableDisableBtn();

});
saveUserDetilBtn.setClickedListener(component -> {
saveKVStore();
});
}

private void saveKVStore() {
try {
String key_user_name = "user_name";
String key_user_detail = "user_detail";
String user_name_value = userName;
String user_detail_value = userDetail;
singleKvStore.putString(key_user_name, user_name_value);
singleKvStore.putString(key_user_detail, user_detail_value);
new ToastDialog(getContext())
.setText("data saved successfully")
.setAlignment(1)
.setDuration(100000000)
.show();
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "putString:" + e.getKvStoreErrorCode());
}
}

private void enableDisableBtn() {
userDetail=userDetailTextField.getText();
userName=userNameTextField.getText();
if (userDetail.length() > 0 && userName.length()>0) {
ShapeElement activateBtn = new ShapeElement(this, ResourceTable.Graphic_background_button_green_color);
saveUserDetilBtn.setBackground(activateBtn);
saveUserDetilBtn.setTextColor(Color.WHITE);
} else {
ShapeElement inaActivateBtn = new ShapeElement(this, ResourceTable.Graphic_background_button_gray_color);
saveUserDetilBtn.setBackground(inaActivateBtn);
saveUserDetilBtn.setTextColor(Color.BLACK);
}
}
}
Create store_kv_detail_layout.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">

ohos:height="match_content"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:top_margin="60vp">

ohos:id="$+id:enter_user_name"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:background_text_field"
ohos:bottom_margin="10vp"
ohos:end_margin="10vp"
ohos:hint="$string:store_ability_enter_user_name"
ohos:hint_color="#000000"
ohos:multiple_lines="true"
ohos:padding="12vp"
ohos:start_margin="10vp"
ohos:text_color="#000000"
ohos:text_size="30fp"
ohos:top_margin="10vp"/>

ohos:id="$+id:error_tip_text_user_name"
ohos:height="match_parent"
ohos:width="match_content"
ohos:bottom_padding="8vp"
ohos:layout_alignment="right"
ohos:right_margin="20vp"
ohos:text="Please enter user detial"
ohos:text_alignment="center"
ohos:text_color="red"
ohos:text_size="28fp"
ohos:top_padding="8vp"
ohos:visibility="hide"/>


ohos:height="match_content"
ohos:width="match_parent"
ohos:layout_alignment="center"
ohos:top_margin="10vp">

ohos:id="$+id:enter_user_detail"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:background_text_field"
ohos:bottom_margin="10vp"
ohos:end_margin="10vp"
ohos:hint="$string:store_ability_enter_user_detail"
ohos:hint_color="#000000"
ohos:min_height="200vp"
ohos:multiple_lines="true"
ohos:padding="12vp"
ohos:start_margin="10vp"
ohos:text_color="#000000"
ohos:text_size="30fp"
ohos:top_margin="10vp"/>

ohos:id="$+id:error_tip_text_user_detail"
ohos:height="match_parent"
ohos:width="match_content"
ohos:bottom_padding="8vp"
ohos:layout_alignment="right"
ohos:right_margin="20vp"
ohos:text="Please enter user detial"
ohos:text_alignment="center"
ohos:text_color="red"
ohos:text_size="28fp"
ohos:top_padding="8vp"
ohos:visibility="hide"/>


ohos:id="$+id:save_detil_btn"
ohos:height="70vp"
ohos:width="match_parent"
ohos:background_element="$graphic:background_button_gray_color"
ohos:margin="10vp"
ohos:text="$string:store_ability_save_detail"
ohos:text_size="30fp"/>


Create KvStoreObserverClient.java ability and add the below code.
package com.hms.distributeddataservicedevelopment;

import ohos.agp.window.dialog.ToastDialog;
import ohos.data.distributed.common.ChangeNotification;
import ohos.data.distributed.common.Entry;
import ohos.data.distributed.common.KvStoreObserver;

import java.util.List;

public class KvStoreObserverClient implements KvStoreObserver {
u/Override
public void onChange(ChangeNotification notification) {
List insertEntries = notification.getInsertEntries();
List updateEntries = notification.getUpdateEntries();
List deleteEntries = notification.getDeleteEntries();
if(insertEntries.size()>0){
// inserted data entries in database
}
if(updateEntries.size()>0){
// updated entries in database
}if(deleteEntries.size()>0){
// deleted data entries from database
}

}
}
  1. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.
https://preview.redd.it/ia9wbqstvfi71.png?width=693&format=png&auto=webp&s=74401fa0971f43426c86f788a3e702aaa14c28a1
Result
  1. Run Application on connected device and Click on UI Write data Single KV Store button. It will navigate to StoreKVdetail screen as per below images.
https://preview.redd.it/5zcmlrtfwfi71.png?width=373&format=png&auto=webp&s=264b10348c8a5ab102d56568e73b11d1032e5ada
  1. Enter data and click on “Save KV Detail” button. It will store data in Distributed database as per below images.

https://preview.redd.it/9l79l1vhwfi71.png?width=365&format=png&auto=webp&s=3a7367e0454f9fba822df3d9697ffbd97db31943

https://preview.redd.it/063eaxljwfi71.png?width=369&format=png&auto=webp&s=25f83365ef692daa254cb377b11030ec000ea4b3
  1. Click on “Read Data Single KV Store” button, we will read data from distributed database as per below images.

https://preview.redd.it/zc5i91dlwfi71.png?width=373&format=png&auto=webp&s=6a87a9cc58fff5d175a57f2f498dffc919be86b2

https://preview.redd.it/bbenxrimwfi71.png?width=370&format=png&auto=webp&s=56047b09fb13184937d086f4ea80c5116f880b91

Tips and Tricks

  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Do not forgot to add permission in config.json file.

Conclusion

In this article, we have learnt Distributed database service in Harmony OS. Distributed Data Service (DDS) provides the capability to store data in the databases of different devices. When an application on a device inserts, deletes, or updates data in the distributed database, the same application on another device can obtain the data changes.
Thanks for reading the article, please do like and comment your queries or suggestions.

References

Harmony OS: https://www.harmonyos.com/en/develop/?ha_source=hms1
Distributed database service: https://developer.harmonyos.com/en/docs/documentation/doc-guides/database-mdds-overview-0000001160636563?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.08.13 06:57 lokeshsuryan Intermediate: Network Management (URL Using a Data Network) in Harmony OS

Intermediate: Network Management (URL Using a Data Network) in Harmony OS

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover Network Management with Java in Harmony OS.
In this article, we are going to learn how to fetch data from Rest APIs and display in List container in Harmony OS. Also we will learn how to parse easy and efficient way json result using Gson library.

Available APIs

The list of methods available in the APIs for opening a URL using a data network as follows:

https://preview.redd.it/sr37jqv022h71.png?width=639&format=png&auto=webp&s=78b8381f883c7f24521e0f210604c347790b85b9

Development Overview

You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.

Hardware Requirements

  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.

Software Requirements

  • Java JDK installation package.
  • DevEcho studio installed.

Follows the steps.

  1. Create HarmonyOS Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select ability template and click Next as per below image.
https://preview.redd.it/6tshu5f932h71.png?width=602&format=png&auto=webp&s=7e6995bc5c63d50521b67a21b363db157ed7de85
  • Enter Project and Package Name and click on Finish.
https://preview.redd.it/45ggehjb32h71.png?width=602&format=png&auto=webp&s=befa56862a635815ad5787061675a547978a9007
2. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.

https://preview.redd.it/55pyrmod32h71.png?width=602&format=png&auto=webp&s=13a2864b863e902c06c0c91b2f6ee1cac093b97e
  1. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values. To use the functions of the network management module, you must obtain the below permissions.
"module": {"reqPermissions" : [
{"name": "ohos.permission.GET_NETWORK_INFO"},
{"name" : "ohos.permission.SET_NETWORK_INFO"},
{"name" : "ohos.permission.INTERNET"}
]
}
https://preview.redd.it/a73zxujf32h71.png?width=602&format=png&auto=webp&s=37037d43dc1e5e4cb4f3f446c0eba4cbaed9aef6
  1. Create New Ability, as follows.
https://preview.redd.it/ppmrn8s342h71.png?width=602&format=png&auto=webp&s=e54fa3ba55845597b1ae63b74a23ef3712c7affe

6. Development Procedure.

Create MainAbilitySlice.java ability and add the below code.package com.hms.networkmanagment.slice;
import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.hms.networkmanagment.Providers.NMItemProvider; import com.hms.networkmanagment.ResourceTable; import com.hms.networkmanagment.model.UserDAO; import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.content.Intent; import ohos.agp.components.Component; import ohos.agp.components.ListContainer; import ohos.agp.components.ProgressBar; import ohos.agp.components.RoundProgressBar; import ohos.agp.window.dialog.ToastDialog; import ohos.app.dispatcher.TaskDispatcher; import ohos.app.dispatcher.task.TaskPriority; import ohos.hiviewdfx.HiLog; import ohos.hiviewdfx.HiLogLabel; import ohos.net.NetHandle; import ohos.net.NetManager; import ohos.net.NetStatusCallback; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList;
public class MainAbilitySlice extends AbilitySlice { HiLogLabel LABEL_LOG; public String urlString = "https://run.mocky.io/v3/1291a920-073c-48a5-ad57-851ed49c50e1"; // Specify the EXAMPLE_URL as needed. ArrayList countryList; ListContainer listContainer; RoundProgressBar progressBar;
u/Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG"); listContainer = (ListContainer) findComponentById(ResourceTable.Id_userList); progressBar = (RoundProgressBar) findComponentById(ResourceTable.Id_round_progress_bar); progressBar.setProgressHintText("Please wait"); getCountryData(); }
private void getCountryData() { TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT); globalTaskDispatcher.asyncDispatch(() -> { NetManager netManager = NetManager.getInstance(MainAbilitySlice.this);
if (!netManager.hasDefaultNet()) { new ToastDialog(getContext()) .setText("No Internet Connection!") .show(); return; } NetHandle netHandle = netManager.getDefaultNet();
// Listen to network state changes. NetStatusCallback callback = new NetStatusCallback() { // Override the callback for network state changes. }; netManager.addDefaultNetStatusCallback(callback);
// Obtain a URLConnection using the openConnection method. HttpURLConnection connection = null; try { URL url = new URL(urlString);
URLConnection urlConnection = netHandle.openConnection(url, java.net.Proxy.NO_PROXY); if (urlConnection instanceof HttpURLConnection) { connection = (HttpURLConnection) urlConnection; } connection.setRequestMethod("GET"); connection.connect(); InputStream inputStream = connection.getInputStream(); String response = convertStreamToString(inputStream); countryList = parseJsonResponse(response); TaskDispatcher uiTaskDispatcher = getUITaskDispatcher(); uiTaskDispatcher.delayDispatch(() ->{ progressBar.release(); progressBar.setVisibility(Component.HIDE); if(countryList!=null&&countryList.size()>0) { NMItemProvider nmItemProvider= new NMItemProvider(countryList,MainAbilitySlice.this); listContainer.setItemProvider(nmItemProvider); } else{ new ToastDialog(getContext()) .setText("No data found") .setAlignment(1) .setDuration(5000) .setCornerRadius(2.5f) .show(); }
} , 5);
// Perform other URL operations. } catch (Exception e) { HiLog.error(LABEL_LOG, "exception happened."); } finally { if (connection != null) { connection.disconnect(); } } });
}
private String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); }
private ArrayList parseJsonResponse(String response) { Gson gson = new Gson(); ArrayList userList = null; if (response != null) { Type countryListType = new TypeToken>(){}.getType(); userList = gson.fromJson(response, countryListType);
return userList; } return userList; }
u/Override public void onActive() { super.onActive(); }
u/Override public void onForeground(Intent intent) { super.onForeground(intent); } }
Create ability_main.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
ohos:id="$+id:userList"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:margin="10vp"
ohos:layout_alignment="horizontal_center"
/>
ohos:id="$+id:round_progress_bar"
ohos:height="200vp"
ohos:width="200vp"
ohos:progress_width="10vp"
ohos:center_in_parent="true"
ohos:progress="20"
ohos:start_angle="45"
ohos:max_angle="270"
ohos:progress_color="#47CC47"/>

Create UserDAO.java model class and add the below code, and add parameters as per APIs result. package com.hms.networkmanagment.model;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; public class UserDAO { u/SerializedName("id") u/Expose String id; u/SerializedName("first_name") u/Expose String firstName; u/SerializedName("last_name") u/Expose String lastName; u/SerializedName("email") u/Expose String email; u/SerializedName("gender") u/Expose String gender;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; } }
Create NMItemProvider.java ability and add the below code. package com.hms.networkmanagment.Providers; import com.hms.networkmanagment.ResourceTable; import com.hms.networkmanagment.model.UserDAO; import ohos.aafwk.ability.AbilitySlice; import ohos.agp.components.*;
import java.util.List;
public class NMItemProvider extends BaseItemProvider { private List list; private AbilitySlice slice; public NMItemProvider(List list, AbilitySlice slice) { this.list = list; this.slice = slice; } u/Override public int getCount() { return list == null ? 0 : list.size(); } u/Override public Object getItem(int position) { if (list != null && position >= 0 && position < list.size()){ return list.get(position); } return null; } u/Override public long getItemId(int position) { return position; } u/Override public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { final Component cpt; if (convertComponent == null) { cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_user_list_item, null, false); } else { cpt = convertComponent; } UserDAO sampleItem = list.get(position); Text name = (Text) cpt.findComponentById(ResourceTable.Id_userName); Text userID = (Text) cpt.findComponentById(ResourceTable.Id_userId); Text userEmail = (Text) cpt.findComponentById(ResourceTable.Id_userEmail); Text userGender = (Text) cpt.findComponentById(ResourceTable.Id_userGender); name.setText("Name "+sampleItem.getFirstName()+" "+ sampleItem.getLastName()); userEmail.setText("Email "+sampleItem.getEmail()); userGender.setText("Gender "+sampleItem.getGender()); userID.setText("ID "+sampleItem.getId()); return cpt; } }
Create user_list_item.xml layout and add the below code.

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_parent"
ohos:padding="15vp"
ohos:orientation="vertical">
ohos:id="$+id:userImage"
ohos:height="100vp"
ohos:width="100vp"
ohos:background_element="$media:icon"
/>

ohos:id="$+id:userId"
ohos:height="match_content"
ohos:align_parent_right="true"
ohos:text_size="32fp"
ohos:start_margin="10vp"
ohos:align_baseline="$id:userImage"
ohos:right_of="$id:userImage"
ohos:width="match_content"/>

ohos:id="$+id:userName"
ohos:height="match_content"
ohos:width="match_content"
ohos:text_size="32fp"
ohos:start_margin="10vp"
ohos:right_of="$id:userImage"
ohos:below="$id:userId"/>

ohos:id="$+id:userEmail"
ohos:height="match_content"
ohos:below="$id:userName"
ohos:text_size="32fp"
ohos:start_margin="10vp"
ohos:right_of="$id:userImage"
ohos:width="match_content"/>

ohos:id="$+id:userGender"
ohos:height="match_content"
ohos:below="$id:userEmail"
ohos:text_size="32fp"
ohos:start_margin="10vp"
ohos:right_of="$id:userImage"
ohos:width="match_content"/>


  1. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.
https://preview.redd.it/x39e25az22h71.png?width=693&format=png&auto=webp&s=7ab4ea57b2c94bf7ba2617320a024c1d8abf5268

Result

Run Apk into emulator or connected device its will fetch data as per below images.

https://preview.redd.it/yhvusel132h71.png?width=333&format=png&auto=webp&s=c09fdf4b606878f489a60a2e1050cc99d25529e0

https://preview.redd.it/er15ikk142h71.png?width=377&format=png&auto=webp&s=846ed1b7bbb7f77fbd906f2116c24d52a47f113d

Tips and Tricks

  • ·Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
  • Network task or any long running task should run in background thread.
  • Make sure network permissions added into config.json file.

Conclusion

In this article, we have learnt to fetch data from Rest APIs and show into list container in Harmony OS. Gson library used to convert a JSON string to an equivalent Java object easy and efficient way. Also we have used Task Dispatcher which help us to run network task in background thread and update UI in UI Thread.
Thanks for reading the article, please do like and comment your queries or suggestions.

References

Harmony OS: https://www.harmonyos.com/en/develop/?ha_source=hms1
Network Management: https://developer.harmonyos.com/en/docs/documentation/doc-guides/connectivity-net-overview-0000000000029978?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.08.06 06:52 lokeshsuryan Intermediate: Integration of Huawei AV Pipeline Kit in Android

Intermediate: Integration of Huawei AV Pipeline Kit in Android

Introduction

Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover integration of Huawei Wireless Kits in Android.
AV Pipeline Kit is released in HMS Core 6.0 in the media field. AV Pipeline Kit provides three major capabilities pipeline customization, video super-resolution, and sound event detection. With a framework that enables you to design your own service scenarios, it equips your app with rich and customizable audio and video processing capabilities. This service provides a framework for multimedia development, bolstered by a wealth of cross-platform, high-performing multimedia processing capabilities. The pre-set plugins and pipelines for audio and video collection, editing, and playback have simplified the development of audio and video apps, social apps, e-commerce apps etc.

Use Cases

  • Video playback pipeline
  • Video super-resolution pipeline
  • Sound event detection pipeline
  • Media asset management
  • MediaFilter
  • Plugin customization
Development Overview
You need to install Android studio IDE and I assume that you have prior knowledge about the Android and java.
Hardware Requirements
  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.
Software Requirements
  • Java JDK installation package.
  • Android studio IDE installed.
Follows the steps.
  1. Create Unity Project.
  • Open Android Studio.
  • Click NEW Project, select a Project Templet.
  • Enter project and Package name and click on Finish.
https://preview.redd.it/52tqxpe84of71.png?width=685&format=png&auto=webp&s=54c51c001dd67b1643fd95b3d6f59f4ca0434a46
  1. Register as Huawei developer and complete identity verification in Huawei developer’s website, refer to register a Huawei ID.
3. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > app > Tasks > android, and then click signing Report, as follows.
https://preview.redd.it/izet6jya4of71.png?width=676&format=png&auto=webp&s=241c3c67544b2c581d61745c5657198b1b861cc4
Also we can generate SHA-256 using command prompt.
To generating SHA-256 certificate fingerprint use below command.
keytool -list -v -keystore D:\studio\projects_name\file_name.keystore -alias alias_name
https://preview.redd.it/z2vjm21d4of71.png?width=602&format=png&auto=webp&s=a9e67e8d83310c2561beb933f50721060731f23e
  1. Create an App in AppGallery Connect.
  2. Download the agconnect-services.json file from AGC, copy and paste in android Project under app directory, as follows
  3. Add the below maven URL in build.gradle(Project level) file under the repositories of buildscript, dependencies, for more information refer Add Configuration.
maven { url 'https://developer.huawei.com/repo/' }
  1. Add the below plugin and dependencies in build.gradle(App level)
    implementation 'com.huawei.hms:avpipelinesdk:6.0.0.302' implementation 'com.huawei.hms:avpipeline-aidl:6.0.0.302' implementation 'com.huawei.hms:avpipeline-fallback-base:6.0.0.302' implementation 'com.huawei.hms:avpipeline-fallback-cvfoundry:6.0.0.302' implementation 'com.huawei.hms:avpipeline-fallback-sounddetect:6.0.0.302'
  2. Open AndroidManifest file and add below permissions.

  1. Development Procedure.
Create MainActivity.java Class and Add the below code. package com.huawei.hms.avpipeline.devsample;
import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.View; import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat;
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final String TAG = "AVP-MainActivity"; u/Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initAllView(); applyPermission(); }
void initAllView() { Button assetBtn = findViewById(R.id.asset); Button playerBaseBtn = findViewById(R.id.playerbase); Button playerSRdisabledBtn = findViewById(R.id.playerSRdisabled); Button playerSRenabledBtn = findViewById(R.id.playerSRenabled); assetBtn.setOnClickListener(this); playerSRdisabledBtn.setOnClickListener(this); playerSRdisabledBtn.setOnClickListener(this); playerSRenabledBtn.setOnClickListener(this);
playerBaseBtn.setOnClickListener(v-> {
});
playerSRdisabledBtn.setOnClickListener(v -> {
});
playerSRenabledBtn.setOnClickListener(v -> {
}); }
private void applyPermission() { String[] permissionLists = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_NETWORK_STATE }; int requestPermissionCode = 1; for (String permission : permissionLists) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissionLists, requestPermissionCode); } } }
u/Override public void onClick(View view) { switch (view.getId()){ case R.id.asset: Intent intent = new Intent(MainActivity.this, AssetActivity.class); startActivity(intent); break; case R.id.playerbase: Intent playerActivityBase = new Intent(MainActivity.this, PlayerActivityBase.class); startActivity(playerActivityBase); break; case R.id.playerSRdisabled:{ Intent playerActivitySRdisabled = new Intent(MainActivity.this, PlayerActivitySRdisabled.class); startActivity(playerActivitySRdisabled); } case R.id.playerSRenabled:{ Intent playerActivitySRenabled = new Intent(MainActivity.this, PlayerActivitySRenabled.class); startActivity(playerActivitySRenabled); } }
} }
Create activity_main.xml layout and add the below code.xml version="1.0" encoding="utf-8"?>





Create PlayerActivity.java Class and Add the below code.

package com.huawei.hms.avpipeline.devsample;
import android.annotation.SuppressLint; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.provider.DocumentsContract; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Button; import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.huawei.hms.avpipeline.sdk.AVPLoader; import com.huawei.hms.avpipeline.sdk.MediaPlayer;
import java.util.concurrent.CountDownLatch;
public abstract class PlayerActivity extends AppCompatActivity { private static final String TAG = "AVP-PlayerActivity"; private static final int MSG_INIT_FWK = 1; private static final int MSG_CREATE = 2; private static final int MSG_PREPARE_DONE = 3; private static final int MSG_RELEASE = 4; private static final int MSG_START_DONE = 5; private static final int MSG_SET_DURATION = 7; private static final int MSG_GET_CURRENT_POS = 8; private static final int MSG_UPDATE_PROGRESS_POS = 9; private static final int MSG_SEEK = 10;
private static final int MIN_CLICK_TIME_INTERVAL = 3000; private static long mLastClickTime = 0; u/SuppressLint("UseSwitchCompatOrMaterialCode") protected Switch mSwitch; protected MediaPlayer mPlayer; private SurfaceHolder mVideoHolder; private TextView mTextCurMsec; private TextView mTextTotalMsec; private String mFilePath = null; private boolean mIsPlaying = false; private long mDuration = -1; private SeekBar mProgressBar; private Handler mMainHandler; private CountDownLatch mCountDownLatch;
private Handler mPlayerHandler = null; private HandlerThread mPlayerThread = null;
void makeToastAndRecordLog(int priority, String msg) { Log.println(priority, TAG, msg); Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); }
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); mPlayerThread = new HandlerThread(TAG); mPlayerThread.start(); if (mPlayerThread.getLooper() != null) { mPlayerHandler = new Handler(mPlayerThread.getLooper()) { u/Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SEEK: { seek((long) msg.obj); break; } case MSG_GET_CURRENT_POS: { getCurrentPosition(); break; } case MSG_INIT_FWK: { initFwk(); break; } case MSG_CREATE: { mCountDownLatch = new CountDownLatch(1); startPlayMedia(); break; } case MSG_START_DONE: { onStartDone(); break; } case MSG_PREPARE_DONE: { onPrepareDone(); break; } case MSG_RELEASE: { stopPlayMedia(); mCountDownLatch.countDown(); break; } } super.handleMessage(msg); } };
initAllView(); initSeekBar(); mPlayerHandler.sendEmptyMessage(MSG_INIT_FWK); } }
private void getCurrentPosition() { long currMsec = mPlayer.getCurrentPosition(); if (currMsec == -1) { Log.e(TAG, "get current position failed, try again"); mPlayerHandler.sendEmptyMessageDelayed(MSG_GET_CURRENT_POS, 300); return; } if (currMsec < mDuration) { Message msgTime = mPlayerHandler.obtainMessage(); msgTime.obj = currMsec; msgTime.what = MSG_UPDATE_PROGRESS_POS; mMainHandler.sendMessage(msgTime); } mPlayerHandler.sendEmptyMessageDelayed(MSG_GET_CURRENT_POS, 300); }
protected void onResume() { super.onResume(); }
protected void onPause() { super.onPause(); }
protected void initAllView() { SurfaceView mSurfaceVideo = findViewById(R.id.surfaceViewup); mVideoHolder = mSurfaceVideo.getHolder(); mVideoHolder.addCallback(new SurfaceHolder.Callback() { public void surfaceCreated(SurfaceHolder holder) { if (holder != mVideoHolder) { Log.i(TAG, "holder unmatch, create"); return; } Log.i(TAG, "holder match, create");
mPlayerHandler.sendEmptyMessage(MSG_CREATE); }
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (holder != mVideoHolder) { Log.i(TAG, "holder unmatch, change"); return; } Log.i(TAG, "holder match, change"); }
public void surfaceDestroyed(SurfaceHolder holder) { if (holder != mVideoHolder) { Log.i(TAG, "holder unmatch, destroy"); return; } Log.i(TAG, "holder match, destroy ... "); mPlayerHandler.sendEmptyMessage(MSG_RELEASE); try { mCountDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } Log.i(TAG, "holder match, destroy done ");
} });
ImageButton btn = findViewById(R.id.startStopButton); btn.setOnClickListener(v -> { Log.i(TAG, "click button"); if (mPlayer == null) { return; } if (mIsPlaying) { mIsPlaying = false; mPlayer.pause(); btn.setBackgroundResource(R.drawable.pause); mPlayer.setVolume(0.6f, 0.6f); } else { mIsPlaying = true; mPlayer.start(); btn.setBackgroundResource(R.drawable.play); } });
ImageButton mutBtn = findViewById(R.id.muteButton); mutBtn.setOnClickListener(v -> { if (mPlayer == null) { return; } MediaPlayer.VolumeInfo volumeInfo = mPlayer.getVolume(); boolean isMute = mPlayer.getMute(); Log.i(TAG, "now is mute?: " + isMute); if (isMute) { mutBtn.setBackgroundResource(R.drawable.volume); mPlayer.setVolume(volumeInfo.left, volumeInfo.right); isMute = false; } else { mutBtn.setBackgroundResource(R.drawable.mute); isMute = true; } mPlayer.setMute(isMute); });
Button selectBtn = findViewById(R.id.selectFileBtn); selectBtn.setOnClickListener(v -> { Log.i(TAG, "user is choosing file"); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.setType("*/*"); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); try { startActivityForResult(Intent.createChooser(intent, "choose file"), 1); } catch (ActivityNotFoundException e) { e.printStackTrace(); Toast.makeText(PlayerActivity.this, "install file manager first", Toast.LENGTH_SHORT).show(); } });
mSwitch = findViewById(R.id.switchSr); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.i(TAG, "onActivityResult"); super.onActivityResult(requestCode, resultCode, data); if (requestCode != 1 resultCode != RESULT_OK) { makeToastAndRecordLog(Log.ERROR, "startActivityForResult failed"); return; } Uri fileuri = data.getData(); if (!DocumentsContract.isDocumentUri(this, fileuri)) { makeToastAndRecordLog(Log.ERROR, "this uri is not Document Uri"); return; } String uriAuthority = fileuri.getAuthority(); if (!uriAuthority.equals("com.android.externalstorage.documents")) { makeToastAndRecordLog(Log.ERROR, "this uri is:" + uriAuthority + ", but we need external storage document"); return; } String docId = DocumentsContract.getDocumentId(fileuri); String[] split = docId.split(":"); if (!split[0].equals("primary")) { makeToastAndRecordLog(Log.ERROR, "this document id is:" + docId + ", but we need primary:*"); return; } mFilePath = Environment.getExternalStorageDirectory() + "/" + split[1]; makeToastAndRecordLog(Log.INFO, mFilePath); }
private void initSeekBar() { mProgressBar = findViewById(R.id.seekBar); mProgressBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { u/Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { }
u/Override public void onStartTrackingTouch(SeekBar seekBar) { }
u/Override public void onStopTrackingTouch(SeekBar seekBar) { Log.d(TAG, "bar progress=" + seekBar.getProgress()); // get progress percent long seekToMsec = (long) (seekBar.getProgress() / 100.0 * mDuration); Message msg = mPlayerHandler.obtainMessage(); msg.obj = seekToMsec; msg.what = MSG_SEEK; mPlayerHandler.sendMessage(msg); } }); mTextCurMsec = findViewById(R.id.textViewNow); mTextTotalMsec = findViewById(R.id.textViewTotal);
SeekBar mVolumeSeekBar = findViewById(R.id.volumeSeekBar); AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); mVolumeSeekBar.setProgress(currentVolume); mVolumeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { u/Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser && (mPlayer != null)) { MediaPlayer.VolumeInfo volumeInfo = mPlayer.getVolume(); volumeInfo.left = (float) (progress * 0.1); volumeInfo.right = (float) (progress * 0.1); mPlayer.setVolume(volumeInfo.left, volumeInfo.right); } }
u/Override public void onStartTrackingTouch(SeekBar seekBar) { }
u/Override public void onStopTrackingTouch(SeekBar seekBar) { } }); }
private void initFwk() { if (AVPLoader.isInit()) { Log.d(TAG, "avp framework already inited"); return; } boolean ret = AVPLoader.initFwk(getApplicationContext()); if (ret) { makeToastAndRecordLog(Log.INFO, "avp framework load successfully"); } else { makeToastAndRecordLog(Log.ERROR, "avp framework load failed"); } }
protected int getPlayerType() { return MediaPlayer.PLAYER_TYPE_AV; }
protected void setGraph() { }
protected void setListener() { }
private void seek(long seekPosMs) { if (mDuration > 0 && mPlayer != null) { Log.d(TAG, "seekToMsec=" + seekPosMs); mPlayer.seek(seekPosMs); } }
private void startPlayMedia() { if (mFilePath == null) { return; } Log.i(TAG, "start to play media file " + mFilePath);
mPlayer = MediaPlayer.create(getPlayerType()); if (mPlayer == null) { return; } setGraph(); if (getPlayerType() == MediaPlayer.PLAYER_TYPE_AV) { int ret = mPlayer.setVideoDisplay(mVideoHolder.getSurface()); if (ret != 0) { makeToastAndRecordLog(Log.ERROR, "setVideoDisplay failed, ret=" + ret); return; } } int ret = mPlayer.setDataSource(mFilePath); if (ret != 0) { makeToastAndRecordLog(Log.ERROR, "setDataSource failed, ret=" + ret); return; }
mPlayer.setOnStartCompletedListener((mp, param1, param2, parcel) -> { if (param1 != 0) { Log.e(TAG, "start failed, return " + param1); mPlayerHandler.sendEmptyMessage(MSG_RELEASE); } else { mPlayerHandler.sendEmptyMessage(MSG_START_DONE); } });
mPlayer.setOnPreparedListener((mp, param1, param2, parcel) -> { if (param1 != 0) { Log.e(TAG, "prepare failed, return " + param1); mPlayerHandler.sendEmptyMessage(MSG_RELEASE); } else { mPlayerHandler.sendEmptyMessage(MSG_PREPARE_DONE); } });
mPlayer.setOnPlayCompletedListener((mp, param1, param2, parcel) -> { Message msgTime = mMainHandler.obtainMessage(); msgTime.obj = mDuration; msgTime.what = MSG_UPDATE_PROGRESS_POS; mMainHandler.sendMessage(msgTime); Log.i(TAG, "sendMessage duration"); mPlayerHandler.sendEmptyMessage(MSG_RELEASE); });
setListener(); mPlayer.prepare(); }
private void onPrepareDone() { Log.i(TAG, "onPrepareDone"); if (mPlayer == null) { return; } mPlayer.start(); }
private void onStartDone() { Log.i(TAG, "onStartDone"); mIsPlaying = true; mDuration = mPlayer.getDuration(); Log.d(TAG, "duration=" + mDuration);
mMainHandler = new Handler(Looper.getMainLooper()) { u/Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_UPDATE_PROGRESS_POS: { long currMsec = (long) msg.obj; Log.i(TAG, "currMsec: " + currMsec); mProgressBar.setProgress((int) (currMsec / (double) mDuration * 100)); mTextCurMsec.setText(msecToString(currMsec)); } case MSG_SET_DURATION: { mTextTotalMsec.setText(msecToString(mDuration)); break; } } super.handleMessage(msg); } };
mPlayerHandler.sendEmptyMessage(MSG_GET_CURRENT_POS); mMainHandler.sendEmptyMessage(MSG_SET_DURATION); }
private void stopPlayMedia() { if (mFilePath == null) { return; } Log.i(TAG, "stopPlayMedia doing"); mIsPlaying = false; if (mPlayer == null) { return; } mPlayerHandler.removeMessages(MSG_GET_CURRENT_POS); mPlayer.stop(); mPlayer.reset(); mPlayer.release(); mPlayer = null; Log.i(TAG, "stopPlayMedia done"); }
u/SuppressLint("DefaultLocale") private String msecToString(long msec) { long timeInSec = msec / 1000; return String.format("%02d:%02d", timeInSec / 60, timeInSec % 60); }
protected boolean isFastClick() { long curTime = System.currentTimeMillis(); if ((curTime - mLastClickTime) < MIN_CLICK_TIME_INTERVAL) { return true; } mLastClickTime = curTime; return false; } }
Create activity_player.xml layout and add the below code.xml version="1.0" encoding="utf-8"?>











10. To build apk and run in device, choose Build > Generate Signed Bundle/APK > Build for apk or Build and Run into connected device, follow the steps.
https://preview.redd.it/2vt5xnmg4of71.png?width=648&format=png&auto=webp&s=b9215c535043d78d18664cccc24f9dc86d647bbd
Result
Click on UI button. It will navigate to respective screen as per below images.
https://preview.redd.it/0kwn1m8j4of71.png?width=302&format=png&auto=webp&s=a9378d45445e4338405f46f60801cfce622f5e42
https://preview.redd.it/1j662lel4of71.png?width=301&format=png&auto=webp&s=0dedce800b8331e4f4ab9fedb97191cfcf17cbf0

https://preview.redd.it/7ibf76on4of71.png?width=342&format=png&auto=webp&s=c72fae8ea5e30fe3e5cc3d2f7b9cb65879ac14cf

https://preview.redd.it/ayny1d4p4of71.png?width=439&format=png&auto=webp&s=2c048eb1fb0f019c1cc0fce5bcf310dcc078fc07
Tips and Tricks
  • Always use the latest version of the library.
  • Add agconnect-services.json file without fail.
  • Add SHA-256 fingerprint without fail.
  • Make sure dependencies added in build files.
  • Make sure you have EMUI 10.1 and later versions.
Conclusion
In this article, we have learnt Object AV Pipeline in android with Java. AV Pipeline Kit is easy to use, high performing, and consumes low power. It provides pre-set pipelines that supports basic media collection, editing, and playback capabilities. You can quickly integrate these pipelines into your app.
References
Wireless Kit: https://developer.huawei.com/consumeen/doc/development/Media-Guides/introduction-0000001156025439?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.07.02 06:20 lokeshsuryan Intermediate: Inter Thread Communication in Harmony OS

Intermediate: Inter Thread Communication in Harmony OS
Introduction
When you need to process a time-consuming operation. For example, executing a download task in the current thread without blocking the thread, try out the EventHandler to achieve efficient communications between different threads in HarmonyOS. You can use EventRunner to create another thread to run time-consuming tasks without blocking the current thread. In this way, all types of tasks can run more smoothly and effectively in different threads. For example, you can use EventHandler in the main thread to create a child thread to download an image. The EventHandler will notify the main thread when the image is downloaded in child thread, and the main thread can update the UI display.

https://preview.redd.it/1rm55xhz5q871.png?width=602&format=png&auto=webp&s=aee913c591b325e5f86a5397a92abb0d2c102c9a
Limitations and Constraints
  • During inter-thread communication, the EventHandler can be bound only to the threads created by the EventRunner. When creating an EventRunner instance, ensure that the creation is successful. An EventHandler can be bounded to threads created by an EventRunner instance only when the EventRunner instance is not null.
  • An EventHandler can be bounded only one EventRunner at a time. However, an EventRunner can be bounded to multiple EventHandler instances at the same time.
When to Use
Development Scenarios of EventHandler
The EventHandler dispatches InnerEvent instances or Runnable tasks to other threads for processing, including the following situations:
  • An InnerEvent instance needs to be dispatched to a new thread and to be processed based on the priority and delay time. The priority of an InnerEvent can be IMMEDIATE, HIGH, LOW, or IDLE, and the delay time can be specified.
  • A Runnable task needs to be dispatched to a new thread and to be processed based on the priority and delay time. The priority of a Runnable task can be IMMEDIATE, HIGH, LOW, or IDLE, and the delay time can be specified.
  • An event needs to be dispatched from a new thread to the original thread for processing.
Development Overview
You need to install DevEcho studio IDE and I assume that you have prior knowledge about the Harmony OS and java.
Hardware Requirements
  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.
Software Requirements
  • Java JDK installation package.
  • DevEcho studio installed.
  • HMS Core (APK) 4.X or later.
Follows the steps.
  1. Create Unity Project.
  • Open DevEcho studio.
  • Click NEW Project, select a Project Templet.
  • Select ability template and click Next as per below image.
https://preview.redd.it/i05ac3z26q871.png?width=689&format=png&auto=webp&s=c3eaeef4eeac61f4dfbfa6791698589f43fbfeab
  • Enter Project and Package Name and click on Finish.
https://preview.redd.it/v1621yk66q871.png?width=685&format=png&auto=webp&s=c94671105cc90a08360a1688cacc6598ac967d8b
  1. Once you have created the project, DevEco Studio will automatically sync it with Gradle files. Find the below image after synchronization is successful.

https://preview.redd.it/5601fp096q871.png?width=602&format=png&auto=webp&s=0780d601d60eae90d1f8121d334a7a23184399e3
3. Update Permission and app version in config.json file as per your requirement, otherwise retain the default values

https://preview.redd.it/6mlkcldb7q871.png?width=602&format=png&auto=webp&s=81a96d98f089387482d0562a2e747e2479ccceb2
4. Create New Ability as follows.

https://preview.redd.it/7ujt2wlb7q871.png?width=690&format=png&auto=webp&s=7149623d50a34538111f2bb1319a2122c4ad0fb8
  1. Development Procedure.
Add the below code in MainAbilitySlice.java
package com.hms.interthreadcom.slice;
import com.hms.interthreadcom.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Text;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import java.util.stream.IntStream;
public class MainAbilitySlice extends AbilitySlice {
public static final int CODE_DOWNLOAD_FILE1 = 1;
public static final int CODE_DOWNLOAD_FILE2 = 2;
public static final int CODE_DOWNLOAD_FILE3 = 3;
HiLogLabel LABEL_LOG;
Text handlerTV;
Button interThreadBtn,bankingSystemBtn,delayInterThreadBtn;
EventRunner runnerA;
MyEventHandler handler;
MyEventHandler handler2;
Customer customer;
// 1. Create a class that inherits from EventHandler.
u/Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
handlerTV=(Text)findComponentById(ResourceTable.Id_text_helloworld);
interThreadBtn=(Button)findComponentById(ResourceTable.Id_inter_thread);
delayInterThreadBtn=(Button)findComponentById(ResourceTable.Id_delay_inter_thread);
bankingSystemBtn=(Button)findComponentById(ResourceTable.Id_inter_thread_banking_system);
LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");
interThreadBtn.setClickedListener(component -> executeTask());
delayInterThreadBtn.setClickedListener(component -> executeTaskWithDelay());
bankingSystemBtn.setClickedListener(component -> interThreadInBankingSystem());
// Thread A:
runnerA = EventRunner.create("downloadRunner");
handler = new MyEventHandler(runnerA);
handler2 = new MyEventHandler(runnerA);
}
private void interThreadInBankingSystem() {
customer=new Customer();
new Thread(() -> customer.withdraw(15000)).start();
new Thread(() -> customer.deposit(10000)).start();
}

private void executeTaskWithDelay() {
handler.sendEvent(CODE_DOWNLOAD_FILE1,2 , EventHandler.Priority.HIGH);
handler.sendEvent(CODE_DOWNLOAD_FILE2);
handler.sendEvent(CODE_DOWNLOAD_FILE3);
}

private void executeTask() {
// 3. Send events to thread A.
handler.sendEvent(CODE_DOWNLOAD_FILE1);
handler.sendEvent(CODE_DOWNLOAD_FILE2);
handler.sendEvent(CODE_DOWNLOAD_FILE3);
}

u/Override
public void onActive() {
super.onActive();
}

u/Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
public class MyEventHandler extends EventHandler {
MyEventHandler(EventRunner runner) {
super(runner);
}
u/Override
public void processEvent(InnerEvent event) {
super.processEvent(event);
if (event == null) {
return;
}

int eventId = event.eventId;
switch (eventId) {
case CODE_DOWNLOAD_FILE1: {
handlerTV.setText("Please wait image downloading...");
HiLog.info(LABEL_LOG, "The Image 1 is downloading please wait");
break;
}
case CODE_DOWNLOAD_FILE2: {
IntStream.rangeClosed(0, 100).forEach(i -> HiLog.info(LABEL_LOG, "The Image" + i + "is downloading please wait"));
break;
}
case CODE_DOWNLOAD_FILE3: {
handlerTV.setText("Image downloading successfully");
HiLog.info(LABEL_LOG, "The Image done");
break;
}
default:
break;
}
}
}
public class Customer {
int amount=10000;
synchronized void withdraw(int amount){
System.out.println("going to withdraw...");

if(this.amount System.out.println("Less balance; waiting for deposit...");
try{
wait();
}catch(Exception e){}
}
this.amount-=amount;
System.out.println("withdraw completed...");
}

synchronized void deposit(int amount){
System.out.println("going to deposit...");
this.amount+=amount;
System.out.println("deposit completed... ");
notify();
}
}


}
Add the below code in ability_main.xml

xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
ohos:id="$+id:inter_thread"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:mainability_interthread"
ohos:text_size="22fp"
ohos:padding="10vp"
ohos:margin="20vp"
ohos:background_element="$graphic:background_button">
ohos:id="$+id:delay_inter_thread"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:mainability_delay_interthread"
ohos:text_size="22fp"
ohos:padding="10vp"
ohos:margin="20vp"
ohos:background_element="$graphic:background_button">
ohos:id="$+id:inter_thread_banking_system"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="$string:mainability_banking_system"
ohos:text_size="22fp"
ohos:padding="10vp"
ohos:margin="20vp"
ohos:background_element="$graphic:background_button">

ohos:id="$+id:text_helloworld"
ohos:height="match_content"
ohos:width="match_content"
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text_size="40vp"
/>


  1. To build apk and run in device, choose Build > Generate Key and CSR Build for Hap(s)\ APP(s) or Build and Run into connected device, follow the steps.

https://preview.redd.it/hf1t048o6q871.png?width=693&format=png&auto=webp&s=762db077059eb3cb8c2e35b93bfc09b564c2eca7
Result
  1. Click on UI Inter Thread Communication button. It will execute an image download time-consuming operation task in the current thread without blocking the thread.

https://preview.redd.it/waupf9kq6q871.png?width=602&format=png&auto=webp&s=a0f7cb8cce5f03f4c766d81ce61338ce1ddf06cf

https://preview.redd.it/31xjknzr6q871.png?width=602&format=png&auto=webp&s=69017ac8f3f64837ab8ea5241c51b48998b0900f
Pros: You can perform time consuming operation without blocking current thread.
Cons: If you trying to execute time consuming operation without
2. Click on ‘Banking System’ button, it will communicate between two thread.

https://preview.redd.it/jh1hetdv6q871.png?width=711&format=png&auto=webp&s=6699bcf7521a3c387497835ee34ef104bfc8cefc
Pros: You can communicate between two threads. Only single thread to access the shared resource.
Cons: Increase the waiting time of the thread. Create performance problem.
Tips and Tricks
  • Always use the latest version of DevEcho Studio.
  • Use Harmony Device Simulator from HVD section.
Conclusion
In this article, we have learnt Inter Thread Management in Harmony OS. EventHandler mainly used for time-consuming operation task in current thread without blocking the thread, try out the EventHandler to achieve efficient communications between different threads in HarmonyOS.
Thanks for reading the article, please do like and comment your queries or suggestions.
References
Harmony OS: https://www.harmonyos.com/en/develop/?ha_source=hms1
Harmony OS Thread Management:
https://developer.harmonyos.com/en/docs/documentation/doc-guides/inter-thread-guidelines-0000000000038955?ha_source=hms1
Original Source: https://forums.developer.huawei.com/forumPortal/en/topic/0201605805363800032?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


2021.06.04 07:43 lokeshsuryan Intermediate: Integration Huawei Wireless Kit in Android

Intermediate: Integration Huawei Wireless Kit in Android
Introduction
Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover integration of Huawei Wireless Kits in Android.
Wireless Kit encapsulates a range of wireless transmission capabilities and network quality of experience (QoE) capabilities, allowing you to access advanced and customized 5G and Wi-Fi communication solutions, including communication resource scheduling, real-time QoE information obtainment, weak signal prediction, and Wi-Fi high-priority package transmission. Wireless Kit ensures high bandwidth, low latency, and reliable network connectivity for your apps.
Use Cases
  • Network QoE information You can integrate the Wireless SDK into your app to obtain network QoE information. After registering your app to the network QoE perception service, Wireless Kit can periodically report the network QoE information to your app, including the uplink and downlink air-interface latency, real-time bandwidth, and real-time speed, as well as the network QoE levels and uplink air-interface packet loss rate, for informed decision making.
  • App data transmission quality feedback Apps will send information such as transmission lags and transmission statistics to the wireless communication module through Wireless Kit. Therefore, the communication module can make scheduling adjustments accordingly to improve the wireless transmission efficiency for the apps. For example, if frame freezing occurs during video streaming in an app, Wireless Kit will receive this issue and report it to the wireless communication module. The communication module will then record the frame freezing information and enhance the transmission capability based on the current network status.
  • Weak signal prediction Wireless Kit uses machine learning to analyze the cellular network signal quality when a user moves along a fixed route. Based on the learning result, it will predict the time when the user is about to enter an area with poor signals, and the time when the user will move to an area with normal signals. In this way, it helps your app take measures in advance, bringing smooth and stable cellular network experience.
  • Wi-Fi high-priority package transmission You can integrate the Wireless SDK into your app to obtain Wi-Fi enhancement services. After the Wi-Fi enhancement services are registered with your app, the Wi-Fi high-priority package transmission can be enabled.
  • Dual Wi-Fi capabilities You can integrate the Wireless SDK into your app to obtain dual Wi-Fi services. After registering dual Wi-Fi services in the app, you can enable or disable Wi-Fi 2 when connecting to Wi-Fi. After connecting to Wi-Fi 2, you can obtain the connection status, network link attributes, and network port status of Wi-Fi 2.
Development Overview
You need to install Android studio IDE and I assume that you have prior knowledge about the Android and java.
Hardware Requirements
  • A computer (desktop or laptop) running Windows 10.
  • A Huawei phone (with the USB cable), which is used for debugging.
Software Requirements
  • Java JDK installation package.
  • Android studio IDE installed.
  • HMS Core (APK) 4.X or later.
Follows the steps.
  1. Create Unity Project.
  • Open Android Studio.
  • Click NEW Project, select a Project Templet.
  • Enter project and package name and click on finish.
https://preview.redd.it/z90a5t1dr6371.png?width=685&format=png&auto=webp&s=046545db6c8daa7457ebb652e4057aa3644392b2
  1. Register as Huawei developer and complete identity verification in Huawei developer’s website, refer to register a Huawei ID.
3. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > app > Tasks > android, and then click signing Report, as follows.

https://preview.redd.it/of323hhjr6371.png?width=676&format=png&auto=webp&s=03e2bc9a5d25b12b7d9940925d141ddbedb0b3f0
Also we can generate SHA-256 using command prompt.
To generating SHA-256 certificate fingerprint use below command.
keytool -list -v -keystore D:\studio\projects_name\file_name.keystore -alias alias_name
https://preview.redd.it/teenkrbmr6371.png?width=602&format=png&auto=webp&s=f0c507fcee0caeaa35fd792469d82301a4aea0db
  1. Create an App in AppGallery Connect.
  2. Download the agconnect-services.json file from AGC, copy and paste in android Project under app directory, as follows
  3. Add the below maven URL in build.gradle(Project level) file under the repositories of buildscript, dependencies, for more information refer Add Configuration.
    classpath 'com.huawei.agconnect:agcp:1.4.2.300'
    maven { url 'https://developer.huawei.com/repo/' }
    1. Add the below plugin and dependencies in build.gradle(App level)
apply plugin 'com.huawei.agconnect'
implementation 'com.huawei.hms:wireless:5.3.0.311'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
  1. Open AndroidManifest file and add below permissions.


9. Development Procedure.
  • Service binding
Obtain a NetworkQoeClient object. Obtain the intent by calling getNetworkQoeServiceIntent, and bind your app to IQoeService. If the intent fails to be obtained, your app will not be able to use IQoeService.
NetworkQoeActivity.java
package com.huawei.hms.hmswirelessdemolk;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.hms.common.ApiException;
import com.huawei.hms.wireless.IQoeCallBack;
import com.huawei.hms.wireless.IQoeService;
import com.huawei.hms.wireless.NetworkQoeClient;
import com.huawei.hms.wireless.WirelessClient;
import com.huawei.hms.wireless.WirelessResult;
/**
* Network qoe test demo
*
* u/since 2020-07-9
*/
public class NetworkQoeActivity extends AppCompatActivity {
private static final String TAG = "networkQoe";
private static final int NETWORK_QOE_INFO_TYPE = 0;
private Button getQoeButton;
private Button registerButton;
private Button unRegisterButton;
private Button showQoeDetailButton;
private Button cancelQoeButton;
private EditText getQoeStateText;
private EditText registerStateText;
private EditText unregisterStateText;
private EditText showQoeDetailsText;
private EditText callQoeDetails;
private int[] channelIndex = new int[4];
private int[] uLRtt = new int[4];
private int[] dLRtt = new int[4];
private int[] uLBandwidth = new int[4];
private int[] dLBandwidth = new int[4];
private int[] uLRate = new int[4];
private int[] dLRate = new int[4];
private int[] netQoeLevel = new int[4];
private int[] uLPkgLossRate = new int[4];
private IQoeService qoeService = null;
private ServiceConnection srcConn = new ServiceConnection() {
u/Override
public void onServiceConnected(ComponentName name, IBinder service) {
qoeService = IQoeService.Stub.asInterface(service);
getQoeStateText.setText("Connected");
}
u/Override
public void onServiceDisconnected(ComponentName name) {
qoeService = null;
Log.i(TAG, "onServiceDisConnected.");
getQoeStateText.setText("Disconnected");
}
};
private IQoeCallBack callBack = new IQoeCallBack.Stub() {
u/Override
public void callBack(int type, Bundle qoeInfo) throws RemoteException {
if (qoeInfo == null type != NETWORK_QOE_INFO_TYPE) {
Log.e(TAG, "callback failed.type:" + type);
return;
}
int channelNum = 0;
if (qoeInfo.containsKey("channelNum")) {
channelNum = qoeInfo.getInt("channelNum");
}
String channelQoe = String.valueOf(channelNum);
for (int i = 0; i < channelNum; i++) {
uLRtt[i] = qoeInfo.getInt("uLRtt" + i);
dLRtt[i] = qoeInfo.getInt("dLRtt" + i);
uLBandwidth[i] = qoeInfo.getInt("uLBandwidth" + i);
dLBandwidth[i] = qoeInfo.getInt("dLBandwidth" + i);
uLRate[i] = qoeInfo.getInt("uLRate" + i);
dLRate[i] = qoeInfo.getInt("dLRate" + i);
netQoeLevel[i] = qoeInfo.getInt("netQoeLevel" + i);
uLPkgLossRate[i] = qoeInfo.getInt("uLPkgLossRate" + i);
channelIndex[i] = qoeInfo.getInt("channelIndex" + i);
channelQoe += "," + channelIndex[i] + "," + uLRtt[i] + "," + dLRtt[i] + "," + uLBandwidth[i] + ","
+ dLBandwidth[i] + "," + uLRate[i] + "," + dLRate[i] + "," + netQoeLevel[i] + ","
+ uLPkgLossRate[i];
}
Log.i(TAG, channelQoe);
callQoeDetails.setText(channelQoe);
}
};
u/Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network_qoe);
this.setTitle("Network qoe");
initWidget();
// Bind QoeService
bindQoeService();
// Register network qoe callback
registerButton.setOnClickListener(new View.OnClickListener() {
u/Override
public void onClick (View view) {
int ret = 0;
if (qoeService != null) {
try {
ret = qoeService.registerNetQoeCallBack("com.huawei.hms.hmswirelessdemolk", callBack);
registerStateText.setText(Integer.toString(ret));
} catch (RemoteException ex) {
Log.e(TAG, "no registerNetQoeCallback api");
}
}
}
});
// Unregister network qoe callback
unRegisterButton.setOnClickListener(new View.OnClickListener() {
u/Override
public void onClick (View view) {
int ret = 0;
if (qoeService != null) {
try {
ret = qoeService.unRegisterNetQoeCallBack("com.huawei.hms.hmswirelessdemolk", callBack);
unregisterStateText.setText(Integer.toString(ret));
} catch (RemoteException ex) {
Log.e(TAG, "no unregisterNetQoeCallback api");
}
}
}
});
// Query real time qoe information
showRealTimeQoeInfo();
// Unbind QoeService
cancelQoeButton.setOnClickListener(new View.OnClickListener() {
u/Override
public void onClick (View view) {
if (qoeService != null) {
NetworkQoeActivity.this.unbindService(srcConn);
qoeService = null;
getQoeStateText.setText("Disconnected");
}
}
});
}
private void initWidget() {
getQoeButton = findViewById(R.id.ConnectQoe);
registerButton = findViewById(R.id.registerQoe);
unRegisterButton = findViewById(R.id.unRegisterQoe);
showQoeDetailButton = findViewById(R.id.getQoeData);
cancelQoeButton = findViewById(R.id.cancleService);
getQoeStateText = findViewById(R.id.ConnectQoeState);
registerStateText = findViewById(R.id.registerState);
unregisterStateText = findViewById(R.id.unregisterState);
showQoeDetailsText = findViewById(R.id.getQoeDataContext);
callQoeDetails = findViewById(R.id.callQoeDetails);
}
private void bindQoeService() {
getQoeButton.setOnClickListener(new View.OnClickListener() {
u/Override
public void onClick(View view) {
NetworkQoeClient networkQoeClient = WirelessClient.getNetworkQoeClient(NetworkQoeActivity.this);
if (networkQoeClient != null) {
networkQoeClient.getNetworkQoeServiceIntent()
.addOnSuccessListener(new OnSuccessListener() {
u/Override
public void onSuccess(WirelessResult wirelessResult) {
Intent intent = wirelessResult.getIntent();
if (intent == null) {
Log.i(TAG, "intent is null.");
return;
}
NetworkQoeActivity.this.bindService(intent, srcConn, Context.BIND_AUTO_CREATE);
}
})
.addOnFailureListener(new OnFailureListener() {
u/Override
public void onFailure(Exception exception) {
if (exception instanceof ApiException) {
ApiException ex = (ApiException) exception;
int errCode = ex.getStatusCode();
Log.e(TAG, "Get intent failed:" + errCode);
}
}
});
}
}
});
}
private void showRealTimeQoeInfo() {
showQoeDetailButton.setOnClickListener(new View.OnClickListener() {
u/Override
public void onClick (View view) {
if (qoeService != null) {
try {
Bundle qoeInfo = qoeService.queryRealTimeQoe("com.huawei.hms.hmswirelessdemolk");
if (qoeInfo == null) {
Log.e(TAG, "queryRealTimeQoe is empty.");
return;
}
int channelNum = 0;
if (qoeInfo.containsKey("channelNum")) {
channelNum = qoeInfo.getInt("channelNum");
}
String channelQoe = String.valueOf(channelNum);
for (int i = 0; i < channelNum; i++) {
uLRtt[i] = qoeInfo.getInt("uLRtt" + i);
dLRtt[i] = qoeInfo.getInt("dLRtt" + i);
uLBandwidth[i] = qoeInfo.getInt("uLBandwidth" + i);
dLBandwidth[i] = qoeInfo.getInt("dLBandwidth" + i);
uLRate[i] = qoeInfo.getInt("uLRate" + i);
dLRate[i] = qoeInfo.getInt("dLRate" + i);
netQoeLevel[i] = qoeInfo.getInt("netQoeLevel" + i);
uLPkgLossRate[i] = qoeInfo.getInt("uLPkgLossRate" + i);
channelIndex[i] = qoeInfo.getInt("channelIndex" + i);
channelQoe += "," + channelIndex[i] + "," + uLRtt[i] + "," + dLRtt[i] + ","
+ uLBandwidth[i] + "," + dLBandwidth[i] + "," + uLRate[i] + ","
+ dLRate[i] + "," + netQoeLevel[i] + "," + uLPkgLossRate[i];
}
Log.i(TAG, channelQoe);
showQoeDetailsText.setText(channelQoe);
} catch (RemoteException exception) {
Log.e(TAG, "no unregisterNetQoeCallback api");
}
}
}
});
}
}
  • Callback registration for Network QoE informatio Register the network QoE information callback. The callback includes the parsing of key network QoE data
// Add related Android classes as required.
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.hms.common.ApiException;
import com.huawei.hms.wireless.IQoeCallBack;
import com.huawei.hms.wireless.IQoeService;
import com.huawei.hms.wireless.NetworkQoeClient;
import com.huawei.hms.wireless.WirelessClient;
import com.huawei.hms.wireless.WirelessResult;
public class NetworkQoeActivity extends AppCompatActivity {
private static final String TAG = "networkQoe";
private static final int NETWORK_QOE_INFO_TYPE = 0;
private int[] channelIndex = new int[4];
private int[] uLRtt = new int[4];
private int[] dLRtt = new int[4];
private int[] uLBandwidth = new int[4];
private int[] dLBandwidth = new int[4];
private int[] uLRate = new int[4];
private int[] dLRate = new int[4];
private int[] netQoeLevel = new int[4];
private int[] uLPkgLossRate = new int[4];
private IQoeService qoeService;
private IQoeCallBack callBack = new IQoeCallBack.Stub() {
u/Override
public void callBack(int type, Bundle qoeInfo) throws RemoteException {
if (qoeInfo == null type != NETWORK_QOE_INFO_TYPE) {
Log.e(TAG, "callback failed.type:" + type);
return;
}
int channelNum = 0;
if (qoeInfo.containsKey("channelNum")) {
channelNum = qoeInfo.getInt("channelNum");
}
String channelQoe = String.valueOf(channelNum);
for (int i = 0; i < channelNum; i++) {
uLRtt[i] = qoeInfo.getInt("uLRtt" + i);
dLRtt[i] = qoeInfo.getInt("dLRtt" + i);
uLBandwidth[i] = qoeInfo.getInt("uLBandwidth" + i);
dLBandwidth[i] = qoeInfo.getInt("dLBandwidth" + i);
uLRate[i] = qoeInfo.getInt("uLRate" + i);
dLRate[i] = qoeInfo.getInt("dLRate" + i);
netQoeLevel[i] = qoeInfo.getInt("netQoeLevel" + i);
uLPkgLossRate[i] = qoeInfo.getInt("uLPkgLossRate" + i);
channelIndex[i] = qoeInfo.getInt("channelIndex" + i);
// channelQoe can be displayed on the user interface via EditText.
channelQoe += "," + channelIndex[i] + "," + uLRtt[i] + "," + dLRtt[i] + "," + uLBandwidth[i] + ","
+ dLBandwidth[i] + "," + uLRate[i] + "," + dLRate[i] + "," + netQoeLevel[i] + ","
+ uLPkgLossRate[i];
}
}
};
u/Override
protected void onCreate(Bundle savedInstanceState) {
if (qoeService != null) {
try {
int ret = qoeService.registerNetQoeCallBack("com.huawei.hms.wirelessdemo",callBack);
} catch (RemoteException ex) {
// You can add a print task here.
}
}
}
}
  • Unregister the network QoE callback. The callback must be the same as that during registration. After unregistration, the callback will not be executed.
public class NetworkQoeActivity extends AppCompatActivity {
u/Override
protected void onCreate(Bundle savedInstanceState) {
int ret = 0;
if (qoeService != null) {
try {
ret = qoeService.unRegisterNetQoeCallBack("com.huawei.hms.wirelessdemo", callBack);
} catch (RemoteException ex) {
// You can add a print task here.
}
}
}
}
10. To build apk and run in device, choose Build > Generate Signed Bundle/APK > Build for apk or Build and Run into connected device follow the steps.

https://preview.redd.it/0bvqgcz6s6371.png?width=670&format=png&auto=webp&s=1b4e2c64f113dcf4ee738f980ca79af7fd104a41
Result
Touch NETWORKQOE to access the Network qoe screen.

https://preview.redd.it/zuf2rs89s6371.png?width=310&format=png&auto=webp&s=ae14f50717ba32d404f98674e513fe9a84d7cda6
  • Touch BIND SERVICE. If Connected is displayed in the TextView, it indicates that the binding is successful.
  • Touch REGISTER CALLBACK. If the value 0 is displayed in the TextView, it indicates that the callback registration is successful. At this time, a string consisting of characters such as numbers, commas, and minus signs will be displayed in the TextView above UNBIND SERVICE. The meanings of the character strings are as follows:
1. The number before the first comma indicates the number of channels that the phone is connected to.
2. The value 0 indicates that there is no valid channel.
3. The valid value ranges from 1 to 4. A channel group has nine parameters, which refer to the identifier, uplink latency, downlink latency, uplink bandwidth, downlink bandwidth, uplink rate, downlink rate, QoE level, and uplink packet loss rate, respectively. For details about the parameters, see the description in the API Reference.
4. Touch QUERY REAL TIME QOE. In the registered state, the same character string as that during registration will be displayed in the TextView under QUERY REAL TIME QOE. In the unregistered state, 0 will be displayed.

https://preview.redd.it/382luq1cs6371.png?width=231&format=png&auto=webp&s=31f1c7d52cbf9d666d0846e5b59ee17cbea1ae62
Touch REPORTAPPQUALITY to access the Report app quality screen. This screen will display the data transmission quality of the app.

https://preview.redd.it/4mo5zs8es6371.png?width=234&format=png&auto=webp&s=32b5ef11f0a39809a9f6091d499218a02e8ee133
Tips and Tricks
  • Always use the latest version of the library.
  • Add agconnect-services.json file without fail.
  • Add SHA-256 fingerprint without fail.
  • Make sure dependenciesadded in build files.
  • Make sure you have EMUI 10.1 and later versions.
Conclusion
In this article, we have learnt integration of Huawei Wireless sdk and how to obtain network QoE feedback, wireless transmission capabilities and network quality of experience (QoE) capabilities, allowing you to access advanced and customized 5G and Wi-Fi communication solutions, including communication resource scheduling, real-time QoE information obtainment, weak signal prediction, and Wi-Fi high-priority package transmission.
References
Wireless Kit:
https://developer.huawei.com/consumeen/hms/huawei-wirelesskit/
Original Source:
https://forums.developer.huawei.com/forumPortal/en/topic/0202581626219410033 ?ha_source=hms1
submitted by lokeshsuryan to HuaweiDevelopers [link] [comments]


http://activeproperty.pl/