Tumgik
#now to find one for android artem
awalkthroughstellis · 6 months
Text
Artificial Blossoming Of Natural Emotions
Warnings: Spoilers for Artem’s MR card “Imitation”, Halloween Special (AU)
Summary: As an elf, Harmony believes solely in the power of nature. Unfortunately, the world around her has turned to the advancements of technology. When she ends up with an android named Artem, her view of the modern world unexpectedly begins to shift.
Tumblr media
Nature and technology are two elements that will never belong together. The ever advancing threat of modern day machinery has been slowly taking over the world inch by inch, and the forest that used to cover this land has lost almost all rights to the soil. The cause? A brand new city full of skyscrapers and humans that dreamed of things that shouldn’t exists.
I’ve been fighting this battle for years. Of all the forest dwellers that used to live here I’m the only one left. The others gave up and fled to a new habit, hoping to find a place the humans won’t steal and build on. If I didn’t care so deeply for my home, I would have gone with them.
If my old friends were here now, I wonder what they would say about the android standing in my kitchen, using the appliances to cook food like a person.
“Good Morning.” The robotic man greeted, his voice monotone and void of emotion, yet somehow it held warmth. “Breakfast is almost ready. Please, have a seat.”
Several days ago, the mayor and I had a meeting to discuss my agreeing to release the remainder of the forest. I would never agree to it of course, and although I made it perfectly clear, he just smiled and offered to send me an android free of charge.
“Just try it out. Who knows? Maybe you’ll finally see and enjoy the impressive knowledge found within technology.”
I almost laughed in his face. I told him the offer wasn’t necessary but surely enough, he sent this man, this android, to my door that same evening.
The android is undoubtedly handsome with his dark hair, bright blue eyes and perfectly ironed suit. His facial features were too perfect; another give away that he wasn’t a creature created by nature. His programming left him with a polite nature but as nice as he seemed to be, I still kept my distance and avoided him.
I’m an elf, for goodness sakes. What am I supposed to do with an android?
“What is it?” He asked, placing a cup of coffee on the table in front of me.
Only now did I realize I had been staring. “Nothing, it’s just… you’re the first of your kind I’ve met. I never thought you would look so…”
Perhaps it was because he looked so much like a living, breathing human that I found myself being careful with my vocabulary. Machinery doesn’t have feelings, so really, there’s no need for me to be so worried about it.
“Androids are made of machinery, but our appearances are designed to resemble a human as closely as possible.” He explained, returning to the counter to pile the finished food onto a plate.
“I see. I apologize, I didn’t mean to stare.”
“There is no need for an apology. You are my owner. You can look as much as you want.”
For some strange reason, his words made my cheeks grow hot. Cupping the warm mug in my hands, I brought the rim to my lips and took a sip.
“Oh, wow.” I said, blinking in surprise. “How did… You put the perfect amount of milk in.”
The corner of his lips pulled up a little as he set the plate in front of me. “I’ve taken note of your habits.”
Again, feeling surprised, I blinked. Did he just smile? Smiles are caused by emotion, something a machine shouldn’t be able to experience. Could it he that his programming has given him emotional response intelligence?
“Your name is Artem, isn’t it?” I asked, to which he nodded in response. “When the mayor sent you here, did he happen to also send an… um…” ‘What’s the most polite way to ask for his instruction manual?’
“No, he sent nothing else with me. Why do you ask?”
I circled the rim of the mug with my index finger. A childhood habit. “Well, I’ve never been responsible for an android before. If you were to start feeling unwell, I’m not sure what to do. The herbal medicine I use won’t work on you, right?”
“That is correct. What you are inquiring about is an ‘Abnormal Response Test.” Artem suddenly crouched next to my chair and began undoing his tie.
My entire body flushed. “W-What are you doing?”
He undid the top button of his shirt, revealing a small, luminescent core embedded in his chest. “Scratches on the skin indicate a malfunction. They will first appear closest to my power core. Detecting early signs will make repairs easier.”
Something about the blue light was hypnotizing. Perhaps it was how gentle the glow was, or maybe it was simply because I’ve never seen anything like it before, but I found myself itching to reach out and touch it.
I didn’t realize I was giving in to the desire until the pads of my fingers made contact with his skin. The texture was interesting; it was smooth, somewhat rubbery and cool to the touch.
Artem suddenly recoiled and I yanked my hand to my chest. “I’m sorry! Did I hurt you?”
He shook his head and stood up, setting the button back in place and fixing his tie. “No, I don’t feel pain. I don’t know why I reacted in such a way. However, I did feel something when you touched me.”
I titled my head a little. “You felt something, but it wasn’t pain… perhaps I made you feel uncomfortable?”
“No, I wouldn’t say I was uncomfortable. Rather, I would have liked you to continue.”
My heart thumped harder against my ribcage, my body growing so warm I could envision steam rising from my skin.
Artem pinched his chin between his thumb and index finger. “I seem to be growing increasingly abnormal. If this concerns you, you can dispose of me at the laboratory and request a new product from the mayor.”
Despair rushed through me with incredible speed. ‘Dispose? New Product?’ It’s clear to me now that androids don’t view the concept of life clearly, but hearing him speak of terminating his own existence so easily was making me uneasy.
“I’m not just going to… dispose of you for being a little different, Artem.” I said, rising from the chair and taking a step towards him. “Humans, elves, creatures born from a natural life, we refer to it was being ‘unique’, and there’s nothing wrong with that.”
“I understand. However, should abnormalities continue to arise, there comes a risk of me losing control of my functions. Should I fall under the effect of a virus, there is a possibility I could harm you.”
Smiling up at him, I shrugged. “What’s the difference? People hurt each other all the time. Everyone is capable of hurting one another.” I paused for a moment. “You’re capable of thinking, speaking, feeling, to some degree. It’s difficult to look at you now and not accept you are alive, even if it is an artificial one. So, I’m gonna to respect your life the same as I do anyone else’s. I’m not gonna throw you away, Artem.”
He watched me for a moment, this brilliant blue eyes of his shifting back and forth between mine. I wonder what he’s searching for? “If this is your choice, I will not argue.”
“Good.” Satisfied, I placed my hands on my hips. “So, you’re capable of cooking and making coffee. Is there any other skills I should know about?”
~~~~~~~~
I tried my best to avoid venturing into the futuristic city but unfortunately, I couldn’t grow everything in my garden. Trips to the supermarket for ingredients such as flour, cheese, and milk were necessary every once in a while. Having Artem accompany me was a pleasant change.
“Are you sure you don’t want me to carry a bag or two?” I asked, eyeing his armful. “I’m sure they’re not that heavy…”
He gave me a reassuring smile. “It’s alright. My job is to aid you in whatever way I can. Will you allow me to do this for you?”
I sighed and relented. It was becoming harder and harder to say no to him, especially when he phrased things so politely.
I quickly realized I had gotten ahead of him. Expecting him to be right behind me I looked back, but to my surprise, he wasn’t there. “Artem?”
I glanced around frantically, and while I couldn’t spot him, I did notice a familiar grocery bag peeking out from around a brick corner. Racing towards it and turning down the corresponding alley, I found him. He was resting on his knees, his back to me as he leaned against a steel post for support.
“Artem? What’s wrong?” I asked, circling around and crouching in front of him.
I almost gasped. The first thing I noticed was that the top button of his shirt was undone, the power core that usually hid behind it visible and changing in brightness. One second it was glowing so intensely it was almost blinding, and the next it so dim it barely shined at all. The circuit system on the side of his neck was reacting the same way, glowing and dimming beneath his rubber-like skin.
“I apologize for disappearing on you, Miss. Castel. I sensed an abnormal response in my body and had little time to get off the street.” Artem’s apology was sincere, much so that it was painful to be on the receiving end of it. “If I were to be discovered like this, I would likely be taken and disposed of by force.”
I cupped his cheeks between my hands. “Look at me. No one is getting disposed of, okay? Not today, not tomorrow, never.”
I shifted my gaze to the street behind him. The city was known for being crowded but at this hour it didn’t seem as terrible. Unless we hid here until nightfall, we likely wouldn’t get another decent chance like this.
“I have an idea. Can you stand?” I asked.
Artem nodded and, while it took him some time, managed to pull himself onto his feet. I picked up the grocery bags - they weren’t very heavy - and loaded them onto one arm, then wrapped the other around Artem’s waist. I could have sworn I felt his body tense.
“Sorry, Artem, but this is the only way to get you to safety without drawing too much attention.” I said, unable to look him in the eyes. My cheeks were burning far too much for that. “If we pretend we are in a relationship, no one will question us. Um, you should put your arm around my shoulders so it doesn’t look one sided.”
“I see.” He went to do as I said, but hesitated. “Are you sure about this? If you are uncomfortable-”
I shook my head. “I’m comfortable with it. We should get moving as soon as possible.”
“Yes, you’re right. Forgive me.”
His arm slid across my shoulders and the sensation sent my heart pounding and encouraged butterflies to swirl like a cyclone in my stomach. Artem insisted on taking a few of the bags to make it look more realistic, and while I wanted to argue, to tell him not to push himself too hard, we were running out of time. I gave him the lightest bags and we headed back to the main road.
“How are you feeling?” I whispered, keeping an eye out for anyone who might have been suspicious. So far, no one’s spared us a second glance. Surprising, considering my pointed ears often drew unwanted attention.
“My software protection has begun the process to fight the virus. It will take time to remove it.”
I nodded and, without meaning to, I squeezed his waist a little. “Artem?”
“Yes?”
“This might be a ridiculous question, but once the virus is gone, does that mean you will… behave differently?”
My knowledge of technology was limited, but I knew a virus for machines was equivalent to an illness in people. To be free of a virus was to be healthy, but if Artem’s personality and humane kindness was the result of a virus…
‘What has gotten into me?’
The truth of my feelings was clear: the thought of losing him filled me with fear and sorrow.
“We’re being watched.” Artem’s voice snapped me out of my trance.
“We’ll have to pretend a little better.” I said, using my thumb to stroke his side in a display of affection. “Maybe we can… um…”
“Harmony, will you allow me to try something?”
His question was vague, but I didn’t think to ask him to elaborate. I trusted him enough to not need further specifics. “I trust you.”
Slowly, gently, Artem pulled me in a little closer and pressed his lips against the temple of my head. His innocent, respectful kiss caught me off guard, made my mind go blank for several seconds. I was so sure my legs would give out but they kept on moving forward.
“They’ve turned away. We won’t need to worry about them any longer.” His monotone voice sounded like honey in my ears.
“Good. That’s good.” I cleared my throat, a poor attempt to shake off the feeling blooming within me. “We’ll be home soon. Can you make it?”
“I can.” His eyes met mine and my breath hitched in my throat. “So long as I am with you, I will find the strength to persevere.”
It was then that I made up my mind, though really, I had made it up a while ago. I’ll fight to protect Artem just as I fought for the forest, and if anyone tried to take him, they’d have to go through me first.
Tumblr media
5 notes · View notes
Text
Chapter 6: People Live Here
Tw // slight nudity
They have been walking for a while now in the foliage. Then up ahead, Riko and Reg see the village. They rush forward to the nearest house to relax outside and take their breath. While relaxing, Riko comments, “Hey Reg, That was pretty good fighting all the way back there.”Reg reacts to the comment, “Thanks, it’s just a natural skill I have programmed to me.”
Riko replies, “Oh yeah, forgot your technically part robot.” Reg questions, “What do you mean?” Riko responds, “I mean, despite being told you’re a robot, you exhibit human-like qualities that I’ve seen in no other machine.” Reg protested, “But there are machines that are designed to look and behave human, how am I any different?” Riko explains, “True as that may be, you exhibit the most human features I’ve seen, and compared to how the androids behave, you react to things more humanly.” Reg gives in, “Well, I guess that’s true then.” “But … How much does this humanity extend?” Before Riko could answer, The whirring buzz of a saw breaks the conversation. Coming from every direction, small laborers armed  rush and surround the two teens. Reg grabs Riko and puts her behind him, putting himself between her and the armed menaces. The machines extend their saws and walk towards them. Reg managed to handle three vovas, but a group of laborers is a little above his level. He fears the machines have the upper hand at this moment. Then, a shotgun blasts through the air, the silence is broken and the machines have halted their aggression. Suddenly, an old man from the house the teens were hanging outside came out and saw them. He alerts, “Quickly!, the machines would have heard that by now, quickly!” Without hesitation, the boy and girl rush their way to the inside of the house.
“Please, make yourself at home,”the old man greets them, the teens observe their surroundings, everything seems to be neat other than in one corner of the living room is a pile of machine parts. “I could see that you’ve been busy,” Reg commented. The old man turned around and sees what he was talking about, “Oh yeah, I’ve been keeping parts around to give to Nora, but she’s a bit of a cranky ol’ bot.” The old man turned back and grabbed two cans, “foods ready!” The two teens sat down on the coach in the living room, and the old man set down the cans on the table in front of them. They’re opened, revealing its contents, beef. Reg grabbed his can, smelled it, then he grabbed a spoon and proceeded to eat. Riko pushed hers aside and asked a question, “Sir, what’s your name?” The old man sat down on his chair and answered, “Name is Artem, I’m a farmer in these parts.” Riko asked again, “What exactly did you farm?” Artemis explains, “I used to farm chickens, but … they long died out and I couldn’t find any as of recently.” “But that’s why I sort of adopted the Laborers.” Riko's face turned confused, “Why?” Artem explains, “Well, ever since my chickens died, I used Laborers as a replacement, everyone laughed at me keeping them around as pets, but I’ve built a sort of connection to them,” he continues, “I cared and treated them as if they were my own children.” He then concludes, “Then the machines … they went insane, started killing everyone left and right, I tripped and fell while running away from a vova, then my laborers came to my rescue, sawed the bastard to pieces.” “They cared for me, I didn’t know why, but they did.” Riko stared at him, Reg stopped eating and stared in awe too. Artem laments, “I used to think the phrase ‘treat others how you wanted to be treated’ only applied to people, but I’m shocked to realize that applies to robots too!”
After the story, Artem looks up and notices Reg’s oil covered clothes. “Sheesh kid, you fell into the America’s,” he joked. Reg looked down on his clothes and realized how messy they were. Embarrassed, he never realized how rough he was on those vovas. Riko doesn’t seem to mind, but Artem does. “It’s alright, you just need to go take a shower and get cleaned up.” Reg stared confusedly. Riko stepped in to explain, “Sorry Artem, my good friend here doesn’t know anything about a shower, he just woke up yesterday.” Artem was confused, “What do you mean?” Riko bluntly says, “He’s part robot, and doesn’t know how most of the world works yet.” Artem replies, “Ah, that makes sense,” he adds, “Alright, you come with me and I’ll tell you how showering works.”
While Reg is with Artem as he explains the functions of a shower and what to do in it, Riko is outside, hoping to communicate with Artem’s robots. She wanders around in the front yard, not spotting any laborers anywhere. Then from the corner of her eye, she spots one. The small critter is hiding in the dark, but as Riko squats and beckons for it to come, the laborer steps out of the shadows and towards Riko. As it approached Riko, she extended her hand to pet it. The laborer sees this and does a warning spur. Riko was shocked by this reaction, but it doesn’t deter her from petting it. She extends her hand again, this time the laborer doesn’t scare her off, it instead allows Riko to touch it. She pats the robot, and begins to stroke it, making sure to avoid the blade. She becomes surprised when the laborer starts purring, as if it’s enjoying it. Soon, more laborers follow, wanting the affection shared by Riko. Riko ponders, “These robots are just like Reg; tough and brutal, but kind and caring!” She still ponders, “I wonder if there are any other robots like Reg, somewhere?”
The shower is nice. Reg thinks as the warm water soothes him from his head to his chest and to his … “um,” reg thinks, “Is that supposed to be there?” As he gets done washing, cleaning, drying himself, he puts on the clothes Artem left on a box in the washroom. He puts them on and alerts Artem, who was waiting outside. “Well kid, ya look mighty fine and dandy,” he says, commenting on Reg’s blue shirt and green pants. “Thanks,” Reg says, “Artem sir, I have some questions.” Artem looks in intrigue, “Oh, and what might that be?”  Reg, took the time to blurt out his first question,”Does a robot need … genitals?” Artem was taken aback by the question, “Oh, um…” he says uncomfortably. After a while, Reg carefully explained his questions while Artem, despite being uncomfortable explaining human anatomy to a child, willingly answered all his questions. “So, does that make me human?” Asked Reg. Artem responds, “I don’t know, you explained very clearly your human qualities, but you’ve also mentioned your robotic traits as well,” he the jokes, “It’s not often you meet a kid equipped with grappling hands, programmed combat maneuvers, and a fuckin’ heat cannon.” He continues, “Most importantly, Robots are usually dead set on commands, you were commanded to protect Riko and here you are doing so.” Reg looks down, further thinking of his validity as a human or a robot. Artem makes light, “If it helps, maybe you should talk to this Sechenov guy and get further answers.” Reg then looks up, and says, “Thanks.”
Reg steps outside of the house where he reunites with Riko, who just got done playing with the laborers. Riko runs up to Reg and praises the clothes he��s wearing. Reg blushed and smiled from the praise. Artem steps outside and sits down on his porch chair, “Hey kids, before you go out again, wanna hear a song I’ve been playing?” “Yeah!,” Riko and Reg shouted as they rushed toward Artem and sat down on the wooden floor. The laborers follow suit, also wanting to hear the song. Artem adjusted his position, tunes the strings, and once ready, begins to play a song.
This is the song Artem plays: https://www.youtube.com/watch?v=nLYELS5LSMM
1 note · View note
my-soul-sings · 3 years
Text
defectively human (pt. 1)
Fandom: Tears of Themis Characters: Artem x Reader 
Summary: With an android in your house and no way to return it, you could only learn to live with it. But as time went by, you found yourself coming to like it. Love it, even. 
And, as it turned out, so did he.
A/N: i was angy so i wrote this
anyway this might be a one shot or a very short series. I’m not sure yet. 
***
For as long as you could remember, Kiki had always been consistent in picking up the worst gifts for her friends, and you were no exception. 
Over the years, you had received some very strange things, including a cosplay outfit for some anime character you didn’t even know about (apparently she had mixed you up with another friend), a bottle of perfume that made you gag after just one sniff, and an alarm clock that played the songs of her favourite band every morning. Kiki still thought that you liked the band just because you would let her go on and on about them, and you had never bothered to correct her. 
Apparently though, you hadn’t seen the worst of her gifts yet. 
“Kiki? Did you just send a coffin to my home? On my birthday?” you asked over the phone. In response, she promptly burst into laughter as if you had just cracked the funniest joke she had ever heard. 
You weren’t exactly joking; the package was taller than you were and the delivery guy had to wheel it into your house for you. Knowing Kiki’s penchant for sending weird gifts, you immediately called her, wanting to know if she had a return receipt for this, just in case. The size of it certainly made you think it was something expensive.
“Have you opened it yet?” she asked, and you shook your head, eyeing the package warily. “Not yet.” 
“Well? Go on!”
“Where did you get this from? It’s huge. Did you spend a lot of money on this? I told you, you shouldn’t—”
“Don’t worry. I got it for a good price; this was from an Anazon return store. I know you don’t like me spending too much on gifts, so I didn’t, like I promised.” 
“And I also said that you didn’t have to send me a gift. Your birthday wishes are enough for me.” 
“Nonsense. You’re one of my closest friends, of course I have to spoil you!” 
You sighed inwardly. This was probably going to be another wacky gift, but you couldn’t find it in yourself to be upset in any way. You were lucky to have a friend who cared this much, even if she tended to express it in... unique ways. 
“Tell me what you think of it! I’m so excited! I’m a bit busy with something right now so I’ll call you back later. Happy birthday! Love you!”
“Thank—” You barely got the word out before she hung up on you and the line went dead. 
So much for getting some answers. Returning your attention to the box, you clicked your tongue as you made a few guesses at what she could have gotten you that would warrant such a huge box. 
Nothing came to mind… other than it being a coffin. That was probably as good a guess as you’d ever make. Who knew? Maybe you would actually guess right for the first time after all these years. 
Five minutes later, you finally managed to get the package open, and what stood before you was a long, rectangular black box. It was plain and simple, and the shape didn’t look much like a coffin, but it certainly looked big enough to house a body. You, at least, would easily fit inside. Maybe this was a newer, more modern design? You didn’t think coffins of all things had design trends to keep up with, but it wasn’t a bad idea to go out in style. 
While examining the box, you spotted a single, round button on the side. So coffins had buttons now? Out of sheer curiosity, you pressed it.
The lid began to open automatically, much like a fridge door opening, but without the cold mist. 
Interesting. You took a step back, intrigued by the contraption. This just might be the most useful gift Kiki had given you so far; now you wouldn’t have to spend money on a coffin. 
But, you should have known better. Kiki had never failed to surprise you, and it seemed that this year, she had chosen to go with the most outrageous gift yet. 
The door of the box opened, revealing the single most insane, horrifying thing you had ever seen: 
A handsome man dressed in a suit and tie, lying motionless in the coffin. 
And so it seemed, Kiki had gotten you a dead body as your birthday gift this year.
***
“Kiki. Kiki!” 
“What? Did you open it? Do you like it?” She sounded excited. You, on the other hand, were feeling the exact opposite at the moment. 
“Kiki. What the hell is that thing?” 
“What do you think?” She didn’t seem to be catching on to the edge in your tone. 
“Look, I’m freaking out in my room right now. Did you just send me a dead body? Did you kill someone and ship the preserved body to me?” 
“What? No! It’s not a dead body. Why would I gift you a dead body?”  
“Then what is it?” 
“It’s an android! I picked him because he’s so handsome—and his looks are exactly your type.” 
You took a good few seconds to process this. An android? Of all the things to buy... “Why an android?” was the only question you could ask, weariness plain in your voice.
“You said you wanted a boyfriend,” Kiki replied cheerily, sounding quite proud of herself for remembering the fact that you were single. “What do you think? It’s the perfect gift, right?” 
Pinching the bridge of your nose, you took a few seconds to steady your voice before replying slowly, enunciating every word with care. “When I said I wanted a boyfriend, I meant a human one. Not… whatever this is.” Warily, you opened your door and peeked outside, straining to hear any sound. All you heard was pin-drop silence in the apartment that you lived in alone. 
“It’ll be fine,” Kiki’s voice continued over the phone while you approached the living room once more, where the open box and the sleeping android was. “Just treat it like a toy. You know, like Barbie dolls. He’s your Ken now. Have some fun with it.” 
“Kiki—”
“Ah, I gotta go. Grabbing some food. Text me! I’ll reply later!” Before you could add anything more, she hung up, once again leaving you with a monotonous beeping as your answer. 
With little options at your disposal, you stepped closer to the box, bracing yourself in case the android suddenly got up and gave you a jumpscare. Thankfully, it remained still and you safely made it all the way to the front of the box without a hitch. 
You studied its black wavy hair, chiselled features, its tall, lanky figure… At least Kiki remembered your type right. You would have been happy to meet a man who looked like this any day, but knowing this was an android only made things really creepy. It might look exceptionally lifelike, but there were no signs of breathing and no pulse when you touched its neck (you tried to ignore how much it felt like actual human skin), which easily confirmed that it wasn’t human. 
Was there an instruction manual with this? Was it just going to keep sleeping or was there a way to wake it up? 
Then again, did you even want it to wake up? You had a bad feeling that this would take a sharp turn for the worse if it did, horror-movie style. 
While deliberating, you felt around inside the box to see if there was an instruction manual somewhere that could teach you how to work this thing. Maybe there was a way to programme it to do certain things, like house chores. The thought had you perking up almost immediately. 
Eventually, you found a small pocket on the inside of the box, and retrieved a small, metal item from it. It looked somewhat like a tie clip, and it looked exquisite with its beautiful golden colour and the light blue crystal at the end of it. 
What you failed to realise was that the blue crystal was actually a button, until you accidentally pressed down on it while examining it. 
You didn’t know what that did, but a minute passed, then two, as you watched the android with big, round eyes, mentally bracing for it to move. However, nothing happened.
With a shrug, you placed the tie clip on the table, intending to return to your room to Google how to operate an android. 
But then you didn’t even take three steps in the direction of your room when you heard a deep, smooth male voice come from behind you. 
“Good afternoon.” 
Your body froze, blood turning cold. Was… Was it awake? Why was it awake? You couldn’t even find the power button before! 
When you finally mustered the courage to turn around, the android had already emerged from the box. It was standing up straight, wearing a polite smile on his face and his bright blue eyes trained squarely on you. 
“My name is Artem Wing. Pleased to meet you.” 
He approached, extending a hand towards you. 
In hindsight, he had probably intended to shake your hand. However, in your shock and near-paralysing fear, your brain didn’t register it as a harmless gesture. Within a split second, your fight-or-flight instincts were engaged. 
In this case, it was fight-and-flight. 
With one swift motion, you raised your hand and delivered a hard, resounding slap across his cheek. 
Then you screamed, bolting towards your room and locking the door behind you. 
Amidst the chaos in your mind, all you could think of was one thing: 
This would be the last time you ever accepted a gift from Kiki. 
49 notes · View notes
actualbird · 2 years
Text
Tumblr media
been seeing the Art vs. Artist meme getting popular on twt again and i wanted to do it myself too!! but im a writer so....
Writer vs. Writing HAHA. heres my personal favorite lines from ao3 fics i wrote and posted this year of 2021!!! all the quotes with the fic are under the cut just in case it's hard to see on the image (click for better visibility!!) :DDD
---
"Harvey watches a leaf wash up onto the small river, blocked by a rock. This leaf will likely never reach the ocean, destined to stay in that crevice and rot, and he knows. He places a hand to his chest.
He knows."
-that’s what seasons do, stardew valley (game)
---
"The sensation of a bluescreen for most androids isn’t a pleasant one. Many he’s spoken to had compared a bluescreen to something like death. When Artem had told Ria about this, she was horrified and despite the fact that that had never happened to him, she immediately got to work making something safer, softer. She made him a place his mind can go, one that isn’t cold or frightening. One that’s warm; something more like the human sensation of sleep.
When Artem sees blue, he knows he’s drifted off into a place of her design."
-it’s time for your routine system maintenance, tears of themis (game)
---
"Destiny or not, they are inextricably linked.
Iron to lodestone.
Yearning and coming home."
-our endless and impossible journey toward home is in fact our home, genshin impact (game)
---
"As he falls asleep, he wonders what Luke is dreaming about. He hopes it’s good. And then Marius lets rest whisk him away as too, because he takes the opportunity to sleep whenever he can get it.
The opportunity to dream, though? Well, he’s only really started doing that with Luke."
-go the fuck to sleep (and dream a little dream of me), tears of themis (game)
---
"And I understand you don’t have time right now, but the way you have been writing to me…
Giann, are you having trouble making time? Or are you running out of it?"
-you can run, you can hide, but this email WILL find you!, tears of themis (game)
---
"Strings can control, but more than anything, they can connect.
As Vyn walks over to join the group—mostly to make fun of Marius along with them—he realizes that this whole team is getting more and more tangled in strings as the days go by."
-filler episodes of the lost gold, tears of themis (video game)"
---
"The hesitation inside him makes a home in his chest. It makes itself comfortable.
And Luke lets it stay."
-it's only ever a seed planted from outside in, tears of themis (game)
---
“"Luke,” She says, and how she says his name feels he’s like coming home. “It’s good to see you again.”
Luke didn’t know he was allowed to come back home."
-but little do we know, the stars welcome him with open arms, tears of themis (game)
18 notes · View notes
oatbrew · 2 years
Note
have you ever thought about some artemrosa aus? Like just hypothetically
yes!!!! thinking up aus even though im not necessarily going to write them is my fave
rosa as an orphaned scholarship kid who befriends and becomes professor an’s ward/assistant before entering college, meeting artem much earlier and in a more casual light than canon. she develops an unrequited crush while he remains oblivious. it’s only when they’re both older that he starts seriously considering her in a new light
rosa as a somewhat eccentric and talented singer/musician who got discovered pretty young in her career. however she soon stumbles into problems not only with her first artistic block after the release of a widely successful album but with a legal battle against her producer. her agent hires artem. because her vibe is his complete opposite, she both repels and charms him in equal turn. (she and marius are platonic besties in this au and get frequently paired in the tabloids bc i couldn’t resist lol)
based on the android artem card. a down-on-her-luck mechanic, rosa finds and fixes an inoperable, high class android from a junkyard, not realizing he and his original inventor and guardian (neil) are entangled in a darker conspiracy. artem falls in love despite his original programming.
a widowed rosa now in her mid thirties (who married and lost luke sorry luke 🥺) finds a potential new love with her long-term partner in themis, not realizing he once held a deep unrequited love for her a decade ago.
au where they both chose an artistic path! artem becomes a sought after, no-nonsense stage manager. during his theatre’s seasonal operetta, he befriends and falls in love with one of the violinists in the orchestra pit
rosa moves to a quiet neighborhood at the edge of stellis and meets artem, her serious and unassuming next-door neighbor. artem dropped out from law school when he was younger due to Mysterious Circumstances (see: trauma) and now moonlights as a cult classic writer of sci-fi novels with horror elements under the pseudonym, mockingbird. rosa is his unwitting huge fan who loves sharing commentary and theories with him on where his stories will go. when his next book features softer, even romantic subplots, she openly wonders what could have caused the change.
parfumerie/you’ve got mail au. rosa and artem get secretly paired as each other’s anonymous correspondent in a friendship/matchmaking pen pal service app that they’ve both joined out of loneliness. rosa and artem correspond on-and-off for four years, both nurturing a casual and supportive friendship that has slowly developed into them mutually catching serious feelings. both are too scared to meet and reveal their identities, while unbeknownst to them both, rosa is celestine’s pick for themis’s new attorney. things get off to a rocky start when rosa finds out that she wasn’t artem’s first choice and opposed her hiring (which was an ultimate it’s not personal it’s strictly business move but has now permanently cast him in a less endearing light to rosa lol sorry artem)
somewhat but not really legally blonde musical au. sheltered and chronically ill but well-meaning rosa gains admission to a prestigious and rigorous law university out of a bet against her overprotective father. her first faltering months are helped by her overworked, over-ambitious ta, who seems to be the only one who seems to believe in her success.
and my fave where everything is the same except artem is a lesbian
5 notes · View notes
takenews-blog1 · 6 years
Text
Pixel 2 XL customers report new crackling audio subject
New Post has been published on https://takenews.net/pixel-2-xl-customers-report-new-crackling-audio-subject/
Pixel 2 XL customers report new crackling audio subject
Whereas it stays a well-liked telephone, the Pixel 2 XL has had its fair proportion of technical issues. A number of customers have reported muted colours, show burn-in, and faint clicking sounds coming from the earpiece. Now, one other audio subject has been found: rattling audio system.
Numerous house owners have taken to the Pixel User Community boards to report speaker distortion and rattling/buzzing sounds. It is mentioned to start out when the quantity stage reaches round 70 – 75 %.
Most customers have reported the issue arising from the handset’s backside speaker, however a small quantity declare the earpiece speaker is affected by the identical subject. And whereas most individuals say their Pixel 2 XL is affected, a number of have reported the identical audio distortion within the Pixel 2.
Take a look at the video beneath, recorded by Android Police’s Artem Russakovskii, to listen to the issue. For those who flip it up and pay attention intently, you can also make out the identical sort of rattling sounds that seem in low cost audio system when boosted to their most quantity; not one thing you’ll look forward to finding in Google’s high-end smartphone.
Again in November, Google released the primary software program replace designed to repair the Pixel 2 XL’s colour, burn-in, and audio points, together with a safety patch for the KRACK (Key Reinstallation Assaults) vulnerability.
Google has but to launch an official assertion concerning this new downside. Affected house owners are being suggested to strive booting into Secure Mode or performing a manufacturing unit reset to see if that fixes the audio, nevertheless it doesn’t appear to be serving to. It seems that an RMA, whereas inconvenient, is the one possibility proper now.
0 notes
iyarpage · 6 years
Text
Android Intents Tutorial with Kotlin
Update note: This tutorial has been updated to Kotlin, Android 26 (Oreo), and Android Studio 3.0 by Steven Smith. The original tutorial was written by Darryl Bayliss. Previous update by Artem Kholodnyi.
People don’t wander around the world aimlessly; most of everything they do – from watching TV, to shopping, to coding the next killer app – has some sort of purpose, or intent, behind it.
Android works in much the same way. Before an app can perform an action, it needs to know what that actions purpose, or intent, is in-order to carry out that action properly.
It turns out humans and Android aren’t so different after all. :]
In this intents tutorial, you are going to harness the power of Intents to create your very own meme generator. Along the way, you’ll learn the following:
What an Intent is and what its wider role is within Android.
How you can use an Intent to create and retrieve content from other apps for use in your own.
How to receive or respond to an Intent sent by another app.
If you’re new to Android Development, it’s highly recommended that you work through Beginning Android Development and Kotlin for Android to get a grip on the basic tools and concepts. You’ll also need Android Studio 3.0 or later.
Get your best meme face ready. This tutorial is about to increase your Android Developer Level to over 9000!!! :]
Getting Started
Begin by downloading the starter project for this tutorial.
Inside, you will find the XML Layouts and associated Activities containing some boilerplate code for the app, along with a helper class to resize Bitmaps, and some resources such as Drawables and Strings that you’ll use later on in this tutorial.
If you already have Android Studio open, click File\Import Project and select the top-level project folder you just downloaded. If not, start up Android Studio and select Open an existing Android Studio project from the welcome screen, again choosing the top-level project folder for the starter project you just downloaded. Be sure to accept any prompts to update to the latest Gradle plugin or to download the correct build tools.
Take some time to familiarize yourself with the project before you carry on. TakePictureActivity contains an ImageView which you can tap to take a picture using your device’s camera. When you tap LETS MEMEIFY!, you’ll pass the file path of the bitmap in the ImageView to EnterTextActivity, which is where the real fun begins, as you can enter your meme text to turn your photo into the next viral meme!
Creating Your First Intent
Build and run. You should see the following:
It’s a bit sparse at the moment; if you follow the instructions and tap the ImageView, nothing happens!
You’ll make it more interesting by adding some code.
Open TakePictureActivity.kt and add the following to the companion object at the bottom of the Class:
const private val TAKE_PHOTO_REQUEST_CODE = 1
This will identify your intent when it returns — you’ll learn a bit more about this later in the tutorial.
Note: This tutorial assumes you are familiar with handling import warnings, and won’t explicitly state the imports to add. As a quick refresher, if you don’t have on-the-fly imports set up, you can import by pressing option + return on a Mac or Alt + Enter on a PC while your cursor is over a class with an import warning.
Add the following just below onClick(), along with any necessary imports:
private fun takePictureWithCamera() { // 1 val captureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) // 2 val imagePath = File(filesDir, "images") val newFile = File(imagePath, "default_image.jpg") if (newFile.exists()) { newFile.delete() } else { newFile.parentFile.mkdirs() } selectedPhotoPath = getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", newFile) // 3 captureIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, selectedPhotoPath) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) } else { val clip = ClipData.newUri(contentResolver, "A photo", selectedPhotoPath) captureIntent.clipData = clip captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) } }
There’s quite a bit going on in this method, so look at it step-by-step.
The first block of code declares an Intent object. That’s all well and good, but what exactly is an intent?
An intent is an abstract concept of work or functionality that can be performed by your app sometime in the future. In short, it’s something your app needs to do. The most basic intents are made up of the following:
Actions: This is what the intent needs to accomplish, such as dialing a telephone number, opening a URL, or editing some data. An action is simply a string constant describing what is being accomplished.
Data: This is the resource the intent operates on. It is expressed as a Uniform Resource Identifier or Uri object in Android — it’s a unique identifier for a particular resource. The type of data required (if any) for the intent changes depending on the action. You wouldn’t want your dial number intent trying to get a phone number from an image! :]
This ability to combine actions and data lets Android know exactly what the intent is intending to do and what it has to work with. It’s as simple as that!
Head back to takePictureWithCamera() and you’ll see the intent you created uses the ACTION_IMAGE_CAPTURE action. You’ve probably already guessed this intent will take a photo for you, which is just the thing a meme generator needs!
The second block of code focuses on getting a temporary File to store the image in. The starter project handles this for you, but take a look at the code in the activity if you want to see how this works.
Note: You may notice the selectedPhotoPath variable being appended with a .fileprovider string. File Providers are a special way of providing files to your App and ensure it is done in a safe and secure way. If you check the Android Manifest you can see Memeify makes use of one. You can read more about them here.
Exploring the Extras
The third block of code in your method adds an Extra to your newly created intent.
What’s an extra, you say?
Extras are a form of key-value pairs that give your intent additional information to complete its action. Just like humans are more likely to perform better at an activity if they are prepared for it, the same can be said for intents in Android. A good intent is always prepared with the extras it needs!
The types of extras an intent can acknowledge and use change depending on the action; this is similar to the type of data you provide to the action.
A good example is creating an intent with an action of ACTION_WEB_SEARCH. This action accepts an extra key-value called QUERY, which is the query string you wish to search for. The key for an extra is usually a string constant because its name shouldn’t change. Starting an intent with the above action and associated extra will show the Google Search page with the results for your query.
Look back at the captureIntent.putExtra() line; EXTRA_OUTPUT specifies where you should save the photo from the camera — in this case, the Uri location of the empty file you created earlier.
Putting Your Intent in Motion
You now have a working intent ready to go, along with a full mental model of what a typical intent looks like:
There’s not much left to do here except let the intent fulfill what it was destined to do with the final line of takePictureWithCamera(). Add the following to the bottom of the method:
startActivityForResult(captureIntent, TAKE_PHOTO_REQUEST_CODE)
This line asks Android to start an activity that can perform the action captureIntent specifies: to capture an image to a file. Once the activity has fulfilled the intent’s action, you also want to retrieve the resulting image. TAKE_PHOTO_REQUEST_CODE, the constant you specified earlier, will be used to identify the intent when it returns.
Next, in the onClick() function, replace the empty closure in the when statement for the R.id.picture_imageview branch condition with a call to the takePictureWithCamera() function. The resulting line of code should look like the following:
R.id.pictureImageview -> takePictureWithCamera()
This calls takePictureWithCamera() when you tap the ImageView.
Time to check the fruits of your labor! Build and run. Tap the ImageView to invoke the camera:
You can take pictures at this point; you just can’t do anything with them! You’ll handle this in the next section.
Note: If you are running the app in the Emulator you may need to edit the camera settings on your AVD. To do this, click Tools\Android\AVD Manager, and then click the green pencil to the right of the virtual device you want to use. Then click Show Advanced Settings in the bottom left of the window. In the Camera section, ensure all enabled camera dropdowns are set to Emulated or Webcam0.
Implicit Intents
If you’re running the app on a physical device with a number of camera-centric apps, you might have noticed something unexpected:
You get prompted to choose which app should handle the intent.
When you create an intent, you can be as explicit or as implicit as you like with what the intent should use to complete its action. ACTION_IMAGE_CAPTURE is a perfect example of an Implicit Intent.
Implicit intents let Android developers give users the power of choice. If they have a particular app they like to use to perform a certain task, would it be so wrong to use some of its features for your own benefit? At the very least, it definitely saves you from reinventing the wheel in your own app.
An implicit Intent informs Android that it needs an app to handle the intent’s action when it starts. The Android system then compares the given intent against all apps installed on the device to see which ones can handle that action, and therefore process that intent. If more than one can handle the intent, the user is prompted to choose one:
If only one app responds, the intent automatically takes the user to that app to perform the action. If there are no apps to perform that action, then Android will return nothing, leaving you with a null value that will cause your app to crash! :[
You can prevent this by checking the result to ensure that at least one app responded to the action before attempting to start it, or in this case you can also state the app can only be installed on devices that have a camera by declaring the necessary hardware requirements by adding the following line to AndroidManifest.xml:
<uses-feature android:name="android.hardware.camera" />
The starter project opts for the device restriction method.
So you have an implicit intent set up to take a photo, but you don’t yet have a way to access that photo in your app. Your meme generator isn’t going to get far without photos!
Add the following new method just below takePictureWithCamera() in TakePictureActivity:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == TAKE_PHOTO_REQUEST_CODE && resultCode == Activity.RESULT_OK) { //setImageViewWithImage() } }
The above method only executes when an activity started by startActivityForResult() in takePictureWithCamera() has finished and returns to your app.
The if statement above matches the returned requestCode against the constant you passed in (TAKE_PHOTO_REQUEST_CODE) to ensure this is your intent. You also check that the resultCode is RESULT_OK; this is simply an Android constant that indicates successful execution.
If everything does go well, then you can assume your image is ready for use, so you call setImageViewWithImage().
Time to define that method!
First, at the top of TakePictureActivity, add the following boolean variable:
private var pictureTaken: Boolean = false
This tracks whether you have taken a photo, which is useful in the event you take more than one photo. You’ll use this variable shortly.
Next, add the following right after onActivityResult():
private fun setImageViewWithImage() { val photoPath: Uri = selectedPhotoPath ?: return pictureImageview.post { val pictureBitmap = BitmapResizer.shrinkBitmap( this@TakePictureActivity, photoPath, pictureImageview.width, pictureImageview.height ) pictureImageview.setImageBitmap(pictureBitmap) } lookingGoodTextView.visibility = View.VISIBLE pictureTaken = true }
BitmapResizer is a helper class bundled with the starter project to make sure the Bitmap you retrieve from the camera is scaled to the correct size for your device’s screen. Although the device can scale the image for you, resizing it in this way is more memory efficient.
With setImageViewWithImage() now ready, uncomment this line that calls it, within onActivityResult():
// setImageViewWithImage()
Build and run. Select your favorite camera app – if prompted – and take another photo.
This time, the photo should scale to the appropriate size given your display and show up in the ImageView:
You’ll also see a TextView underneath that compliments you on your excellent photography skills. It’s always nice to be polite. :]
Explicit Intents
It’s nearly time to build phase two of your meme generator, but first you need to get your picture over to the next activity since you’re a little strapped for screen real estate here.
In the Constants.kt, add the following constants just below the comment line:
const val IMAGE_URI_KEY = "IMAGE_URI" const val BITMAP_WIDTH = "BITMAP_WIDTH" const val BITMAP_HEIGHT = "BITMAP_HEIGHT"
These will be used as keys for the extras you’ll pass to an intent on the next screen.
Now, add the following method to the bottom of TakePictureActivity, adding any imports as necessary:
private fun moveToNextScreen() { if (pictureTaken) { val nextScreenIntent = Intent(this, EnterTextActivity::class.java).apply { putExtra(IMAGE_URI_KEY, selectedPhotoPath) putExtra(BITMAP_WIDTH, pictureImageview.width) putExtra(BITMAP_HEIGHT, pictureImageview.height) } startActivity(nextScreenIntent) } else { Toaster.show(this, R.string.select_a_picture) } }
Here you check pictureTaken to see if it’s true, which indicates your ImageView has a Bitmap from the camera. If you don’t have a Bitmap, then your activity will briefly show a Toast message telling you to go take a photo – method show from the Toaster class makes showing toasts just a tiny bit easier. If pictureTaken is true then you create an intent for the next activity, and set up the necessary extras, using the constants you just defined as the keys.
Next, in the onClick() function, replace the empty closure in the when statement for the R.id.enter_text_button branch condition with a call to the moveToNextScreen() function. The resulting line of code should look like the following:
R.id.enterTextButton -> moveToNextScreen()
Build and run. Tap LETS MEMEIFY! without first taking a photo and you’ll see the toast appear:
If a photo is taken, then moveToNextScreen() proceeds to create an intent for the text entry activity. It also attaches some Extras to the intent, such as the Uri path for the Bitmap and the height and width of the Bitmap as it’s displayed on the screen. These will come in useful in the next activity.
You’ve just created your first explicit Intent. Compared to implicit intents, explicit intents are a lot more conservative; this is because they describe a specific component that will be created and used when the intent starts. This could be another activity that is a part of your app, or a specific Service in your app, such as one that starts to download a file in the background.
This intent is constructed by providing the Context from which the intent was created (in this case, this) along with the class the intent needs to run (EnterTextActivity::class.java). Since you’ve explicitly stated how the intent gets from A to B, Android simply complies. The user has no control over how the intent is completed:
Build and run. Repeat the process of taking a photo, but this time tap LETS MEMEIFY!. Your explicit intent will kick into action and take you to the next activity:
The starter project has already has this activity created and declared in AndroidManifest.xml, so you don’t have to create it yourself.
Handling Intents
Looks like that intent worked like a charm. But where are those Extras you sent across? Did they take a wrong turn at the last memory buffer? Time to find them and put them to work.
Add the following code at the end of onCreate() in the EnterTextActivity:
pictureUri = intent.getParcelableExtra<Uri>(IMAGE_URI_KEY) val bitmapWidth = intent.getIntExtra(BITMAP_WIDTH, 100) val bitmapHeight = intent.getIntExtra(BITMAP_HEIGHT, 100) pictureUri?.let { val selectedImageBitmap = BitmapResizer.shrinkBitmap(this, it, bitmapWidth, bitmapHeight) selectedPictureImageview.setImageBitmap(selectedImageBitmap) }
When you create the activity, you assign the Uri passed from the previous activity to pictureUri by accessing the Intent via intent. Once you have access to the intent, you can access its Extra values.
Since variables and objects come in various forms, you have multiple methods to access them from the intent. To access the Uri object above, for example, you need to use getParcelableExtra(). Other Extra methods exist for other variables such as strings and primitive data types.
getIntExtra(), similarly to other methods that return primitives, also allows you to define a default value. These are used when a value isn’t supplied, or when the key is missing from the provided Extras.
Once you’ve retrieved the necessary Extras, create a Bitmap from the Uri sized by the BITMAP_WIDTH and BITMAP_HEIGHT values you passed. Finally, you set the ImageView image source to the bitmap to display the photo.
In addition to displaying the ImageView, this screen also contains two EditText views where the user can enter their meme text. The starter project does the heavy lifting for you by taking the text from those views and compositing it onto the photo.
The only thing you need to do is to flesh out onClick(). Update the line to the R.id.write_text_to_image_button branch condition:
R.id.writeTextToImageButton -> createMeme()
Drumroll please. Build and Run. Repeat the usual steps to take a photo, and then enter your incredibly witty meme text on the second screen and tap LETS MEMEIFY!:
You’ve just created your own meme generator! Don’t celebrate too long, though — there are a few bits of polish that you need to add to the app.
Broadcast Intents
It would be nice to save your shiny new meme so you can share it with the world. It’s not going to go viral all on its own! :]
Fortunately the starter project has got it covered for you — you only need to tie things together.
Add the following code to saveImageToGallery(), just below the try block before the second Toaster.show() call:
val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) mediaScanIntent.data = Uri.fromFile(imageFile) sendBroadcast(mediaScanIntent)
This intent uses the ACTION_MEDIA_SCANNER_SCAN_FILE action to ask the Android’s media database to add the image’s Uri. That way, any apps that access the media database can use the image via its Uri.
The ACTION_MEDIA_SCANNER_SCAN_FILE action also requires the intent to have some attached data in the form of a Uri, which comes from the File object to which you save the Bitmap.
Finally, you broadcast the intent across Android so that any interested parties — in this case, the media scanner — can act upon it. Since the media scanner doesn’t have a user interface, you can’t start an activity so you simply broadcast the intent instead.
Now, update the R.id.save_image_button branch condition in the onClick() function to the following:
R.id.saveImageButton -> askForPermissions()
When the user hits SAVE IMAGE the above code checks for WRITE_EXTERNAL_STORAGE permission. If it’s not granted on Android Marshmallow and above, the method politely asks the user to grant it. Otherwise, if you are allowed to write to the external storage, it simply passes control to saveImageToGallery().
The code in saveImageToGallery() performs some error handling and, if everything checks out, kicks off the intent.
Build and run. Take a photo, add some stunningly brilliant meme text, tap LETS MEMEIFY!, and then tap SAVE IMAGE once your image is ready.
Now close the app and open the Photos app. If you’re using the emulator then open the Gallery app. You should be able to see your new image in all its meme-ified glory:
Your memes can now escape the confines of your app and are available for you to post to social media or share in any manner of your choosing. Your meme generator is complete!
Intent Filtering
By now you should have a good idea of how to use the right intent for the right job. However, there’s another side to the story of the faithful intent: how your app knows which intent requests to respond to when an implicit intent is sent.
Open AndroidManifest.xml found in app/manifests, and in the first activity element you should see the following:
<activity android:name=".TakePictureActivity" android:label="@string/app_name" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
The key here is the intent-filter element. An Intent Filter enables parts of your app to respond to implicit intents.
These behave like a banner when Android tries to satisfy an implicit intent sent by another app. An app can have multiple intent filters, which it waves about wildly, hoping its intent filter satisfies what Android is looking for:
It’s kind of like online dating for intents and apps. :]
To make sure it’s the right app for the intent, the intent filter provides three things:
Intent Action: The action the app can fulfill; this is similar to the way the camera app fulfills the ACTION_IMAGE_CAPTURE action for your app.
Intent Data: The type of data the intent can accept. This ranges from specific file paths, to ports, to MIME types such as images and video. You can set one or more attributes to control how strict or lenient you are with the data from an intent that your app can handle.
Intent Category: The categories of intents that are accepted; this is an additional way to specify which Actions can respond to an implicit Intent.
It would be AWESOME to offer Memeify as an implicit intent to interacting with images from other apps — and it’s surprisingly simple to do.
Add the following code directly underneath the first intent filter in your AndroidManifest.xml file:
<intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="@string/image_mime_type" /> </intent-filter>
Your new intent filter specifies that your app will look for SEND action from an implicit intent. You use the default category as you don’t have any special use cases, and you’re looking only for image MIME data types.
Now open TakePictureActivity.kt and add the following to the end of the class:
private fun checkReceivedIntent() { val imageReceivedIntent = intent val intentAction = imageReceivedIntent.action val intentType = imageReceivedIntent.type if (Intent.ACTION_SEND == intentAction && intentType != null) { if (intentType.startsWith(MIME_TYPE_IMAGE)) { selectedPhotoPath = imageReceivedIntent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM) setImageViewWithImage() } } }
Here you get the Intent that started the activity and retrieve its action and type. Then you compare these to what you declared in your intent filter, which is a data source with the MIME type of an image.
If it’s a match, then you get the image’s Uri, query the Uri for the Bitmap using a helper method included with the starter project, and the finally ask the ImageView to display the retrieved Bitmap.
Next add the following line at the end of onCreate():
checkReceivedIntent()
The above code ensures that you will check if there is an intent every time the activity is created.
Build and run. Then back out to the home screen, and go to the Photos app, or the Gallery app if you’re using the emulator. Choose any photo, and tap the share button. You should see Memeify among the presented options:
Memeify is ready and waiting to receive your photo! Tap Memeify and see what happens – Memeify launches with the selected photo already displayed in the ImageView.
Your app is now receiving intents like a boss!
Where to Go From Here?
You can download the completed project here.
Intents are one of the fundamental building blocks of Android. Much of the openness and intercommunication that Android takes pride in just wouldn’t be possible without them. Learn how to use intents well and you will have made a very powerful ally indeed.
If you want to learn more about intents and intent filters then check out Google’s Intents documentation.
If you have any questions or comments on this tutorial, feel free to post your comments below!
The post Android Intents Tutorial with Kotlin appeared first on Ray Wenderlich.
Android Intents Tutorial with Kotlin published first on http://ift.tt/2fA8nUr
0 notes
iyarpage · 7 years
Text
Android Animation Tutorial with Kotlin
Update note: This tutorial has been updated to Kotlin and Android Studio 3.0 by Lisa Luo. The original tutorial was written by Artem Kholodnyi.
It’s hard to imagine the mobile experience without animated elements–they’re fun, beautiful and hold the power of not only guiding users gracefully through an app, but also bringing screens to life.
Building animations that make on-screen objects seem alive may look like aerospace engineering at first, but fear not! Android has quite a few tools to help you create animations with relative ease.
You’ll learn to get comfortable with some essential animation tools in this tutorial as you work through launching Doge on a rocket into space (maybe even to the moon) and hopefully get it back safely on the ground :]
By creating these Doge animations, you’ll learn how to:
Create property animations — the most useful and simple Android animations
Move and fade Android Views
Combine animations in a sequence or start them simultaneously
Repeat and reverse animations
Adjust the animations’ timing
Become a bit of a rocket scientist. :]
Prerequisites: This Android tutorial is all about animation, so you need basic knowledge of Android programming and familiarity with Kotlin, Android Studio and XML layouts.
If you’re completely new to Android, you might want to first check out Beginning Android Development Part One.
Many animation. Such code. Fast rocket.
Getting Started
Animations are such a fun topic to explore! The best way to master building animations is by getting your hands dirty in code. :]
First, download the Rocket Launcher Starter. Import it into Android Studio 3.0 Beta 7 or later, then run it on your device. You’ll find everything you need to get going quickly.
Your device will display a list of all the animations you’ll implement.
Click any item on the list.
You should see two static images: Doge and the rocket, and Doge is ready to take a ride. For now, all the screens are the same and none are yet animated.
How do Property Animations Work?
Before you work with the first animation, let’s take a walk down theory road so that you’re clear on the logic behind the magic. :]
Imagine that you need to animate a rocket launch from the bottom edge to the top edge of the screen and that the rocket should make it exactly in 50 ms.
Here’s a plotted graph that shows how the rocket’s position changes over time:
The animation above appears to be smooth and continuous. However, smartphones are digital and work with discrete values. Time does not flow continuously for them; it advances by tiny steps.
Animation consists of many still images, also known as frames, that are displayed one by one over a specified time period. The concept today is the same as it was for the first cartoons, but the rendering is a little different.
Elapsed time between frames is named frame refresh delay — it’s 10 ms by default for property animations.
Here’s where animation is different than it was in the early days of film: when you know the rocket moves at a constant speed, you can calculate the position of the rocket at any given time.
You see six animation frames shown below. Notice that:
In the beginning of the animation, the rocket is at the bottom edge of the screen.
The rocket’s position moves upward by the same fraction of its path with every frame.
By the end of the animation, the rocket is at the top edge of the screen.
TL/DR: When drawing a given frame, you calculate the rocket’s position based on the duration and frame refresh rate.
Fortunately, you don’t have to do all the calculations manually because ValueAnimator is happy to do it for you. :]
To set up an animation, you simply specify the start and end values of the property being animated, as well as the duration. You’ll also need to add a listener to call, which will set a new position for your rocket for each frame.
Time Interpolators
You probably noticed that your rocket moves with constant speed during the entire animation — not terribly realistic. Material Design encourages you to create vivid animations that catch the user’s attention while behaving in a more natural way.
Android’s animation framework makes use of time interpolators. ValueAnimator incorporates a time interpolator – it has an object that implements TimeInterpolator interface. Time interpolators determine how the animated value changes over time.
Have a look again at the graph of position changes over time in the simplest case — a Linear Interpolator:
Here is how this LinearInterpolator responds to time change:
Depending on the time, the rocket position changes at a constant speed, or linearly.
Animations can also have non-linear interpolators. One such example is the AccelerateInterpolator, which looks much more interesting:
It squares the input value, making the rocket start slowly and accelerate quickly — just like a real rocket does!
That’s pretty much all the theory you need to know to get started, so now it’s time for…
Your First Animation
Take some time to familiarize yourself with the project before you move on. The package com.raywenderlich.rocketlauncher.animationactivities contains BaseAnimationActivity and all other activities that extend this class.
Open activity_base_animation.xml file in the res/layout folder.
In the root, you’ll find a FrameLayout that contains two instances of ImageView with images: one has rocket.png and the other has doge.png. Both have android:layout_gravity set to bottom|center_horizontal to render the images at the bottom-center of the screen.
Note: You’ll do a lot of file navigation in this tutorial. Use these handy shortcuts in Android Studio to move between things easily:
Navigate to any file with command + shift + O on Mac / Ctrl + Shift + N on Linux and Windows
Navigate to a Kotlin class with command + O on Mac / Ctrl + N on Linux and Windows
BaseAnimationActivity is a super class of all other animation activities in this app.
Open BaseAnimationActivity.kt and have a look inside. At the top are View member variables that are accessible from all animation activities:
rocket is the view with the image of the rocket
doge is the view that contains the Doge image
frameLayout is the FrameLayout that contains both rocket and doge
screenHeight will equal the screen height for the sake of convenience
Note that rocket and doge are both a type of ImageView, but you declare each as a View since property animations work with all Android Views. Views are also declared as lateinit values since they are null until the layout is inflated and bound in the appropriate lifecycle event, e.g. onCreate() in an Activity.
Take a look at onCreate() to observe the code:
// 1 super.onCreate(savedInstanceState) setContentView(R.layout.activity_base_animation) // 2 rocket = findViewById(R.id.rocket) doge = findViewById(R.id.doge) frameLayout = findViewById(R.id.container) // 3 frameLayout.setOnClickListener { onStartAnimation() }
Here is what you’ve got going on with this code:
Call onCreate() on the superclass and then setContentView(...) with the layout file.
Apply XML layout and bind FrameLayout, rocket and doge to their corresponding views
Set onClickListener on FrameLayout.
Call onStartAnimation() whenever the user taps the screen. This is an abstract method defined by each of the activities that extend BaseAnimationActivity.
This basic code is shared by all of the Activities you will be editing in this tutorial. Now that you’re familiar with it, it’s time to start customizing!
Launch the Rocket
Doge isn’t going anywhere unless you initiate the rocket launch, and it’s the best animation to start with because it’s pretty easy. Who’d have thought that rocket science is so simple?
Open LaunchRocketValueAnimatorAnimationActivity.kt, and add the following code to the body of onStartAnimation():
//1 val valueAnimator = ValueAnimator.ofFloat(0f, -screenHeight) //2 valueAnimator.addUpdateListener { val value = it.animatedValue as Float rocket.translationY = value } //5 valueAnimator.interpolator = LinearInterpolator() valueAnimator.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION //6 valueAnimator.start()
Create an instance of ValueAnimator by calling the static method ofFloat. It accepts the floating point numbers that’ll apply to the specified property of the animated object over time. In this case, the values start at 0f and end with -screenHeight. Android starts screen coordinates at the top-left corner, so the rocket’s Y translation changes from 0 to the negative of the screen height — it moves bottom to top.
Call addUpdateListener() and pass in a listener. ValueAnimator calls this listener with every update to the animated value — remember the default delay of 10 ms.
Get the current value from the animator and cast it to float; current value type is float because you created the ValueAnimator with ofFloat.
Change the rocket’s position by setting its translationY value
Set up the animator’s duration and interpolator.
Start the animation.
Build and run. Select Launch a Rocket in the list. You’ll get a new screen. Tap it!
That was fun, right? :] Don’t worry about Doge getting left behind — he’ll catch his rocketship to the moon a bit later.
Put a Spin on It
How about giving the rocket a little spin action? Open RotateRocketAnimationActivity.kt and add the following to onStartAnimation():
// 1 val valueAnimator = ValueAnimator.ofFloat(0f, 360f) valueAnimator.addUpdateListener { val value = it.animatedValue as Float // 2 rocket.rotation = value } valueAnimator.interpolator = LinearInterpolator() valueAnimator.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION valueAnimator.start()
Can you spot the difference?
Changing the valueAnimator values to go from 0f to 360f causes the rocket to make a full turn. Note that you could create a U-turn effect with 0f to 180f.
Instead of setting translationY, you set the rocket’s rotation because that’s what needs to change.
Build, run and select Spin a rocket. Tap on the new screen:
Accelerate the Launch
Open AccelerateRocketAnimationActivity.kt and add the following code to your old friend onStartAnimation():
// 1 val valueAnimator = ValueAnimator.ofFloat(0f, -screenHeight) valueAnimator.addUpdateListener { val value = it.animatedValue as Float rocket.translationY = value } // 2 - Here set your favorite interpolator valueAnimator.interpolator = AccelerateInterpolator(1.5f) valueAnimator.duration = BaseAnimationActivity.DEFAULT_ANIMATION_DURATION // 3 valueAnimator.start()
The above code is identical to onStartAnimation() in LaunchRocketValueAnimationActivity.kt except for one line: the interpolator used to set valueAnimator.interpolator.
Build, run and select Accelerate a rocket in the list. Tap on the new screen to see how your rocket behaves.
Again, we see that poor Doge doesn’t catch the rocket to the moon…poor fella. Hang in there, buddy!
Since you used AccelerateInterpolator, you should see your rocket accelerating after liftoff. Feel free to play around with interpolators if you’d like. I’ll sit here and wait. I promise :]
Which Properties Can You Animate?
Until now, you’ve only animated position and rotation for View, but ValueAnimator doesn’t care what you do with the value that it supplies.
You can tell ValueAnimator to animate the value using any of the following types:
float if you create ValueAnimator instance with ofFloat
int if you do it with ofInt
ofObject is for the cases when float or int is not enough — it’s often used to animate colors
You can also animate any property of View. Some examples are:
scaleX and scaleY – these allow you to scale the view by x-axis or y-axis independently, or you can call both with the same value to animate the view’s size.
translationX and translationY – these allow you to change the view’s on-screen position.
alpha – animate view’s transparency; 0 stands for completely transparent and 1 for completely opaque.
rotation – rotates the view on screen; the argument is in degrees, so 360 means a full clockwise turn. You may specify negative values as well, for instance, -90 means a counterclockwise quarter-turn.
rotationX and rotationY – the same as rotation but along the x-axis and y-axis. These properties allow you to rotate in 3D.
backgroundColor – lets you set a color. The integer argument must specify a color as Android constants Color.YELLOW, Color.BLUE do.
ObjectAnimator
Meet ObjectAnimator, a subclass of ValueAnimator. If you only need to animate a single property of a single object, ObjectAnimator may just be your new best friend.
Unlike ValueAnimator, where you must set a listener and do something with a value, ObjectAnimator can handle those bits for you almost automagically. :]
Go to LaunchRocketObjectAnimatorAnimationActivity.kt class and enter the following code:
// 1 val objectAnimator = ObjectAnimator.ofFloat(rocket, "translationY", 0f, -screenHeight) // 2 objectAnimator.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION objectAnimator.start()
Here’s what you’re doing:
Creating an instance of ObjectAnimator (like you did with ValueAnimator) except that the former takes two more parameters:
rocket is the object to animate
The object must have a property corresponding to the name of the property you wish to change, which in this example is “translationY”. You’re able to do this because rocket is an object of class View, which, in its base Java class, has an accessible setter with setTranslationY().
You set the duration for the animation and start it.
Run your project. Select Launch a rocket (ObjectAnimator) in the list. Tap on the screen.
The rocket behaves the same as it did with ValueAnimator, but with less code. :]
Note: There’s a limitation to ObjectAnimator — it can’t animate two objects simultaneously. To work around it, you create two instances of ObjectAnimator.
Consider your use cases and the amount of coding required when you decide to use ObjectAnimator or ValueAnimator.
Animating Color
Speaking of use cases, there’s animating colors to consider. Neither ofFloat() nor ofInt() can construct your animator and get good results with colors. You’re better off using ArgbEvaluator.
Open ColorAnimationActivity.kt and put this code into onStartAnimation():
//1 val objectAnimator = ObjectAnimator.ofObject( frameLayout, "backgroundColor", ArgbEvaluator(), ContextCompat.getColor(this, R.color.background_from), ContextCompat.getColor(this, R.color.background_to) ) // 2 objectAnimator.repeatCount = 1 objectAnimator.repeatMode = ValueAnimator.REVERSE // 3 objectAnimator.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION objectAnimator.start()
In the code above, you:
Call ObjectAnimator.ofObject() and give it the following arguments:
frameLayout — the object with the property to be animated
"backgroundColor" — the property you want to animate
ArgbEvaluator() — an additional argument that specifies how to interpolate between two different ARGB (alpha, red, green, blue) color values
Start and end color values — here you make use of ComtextCompat.getColor() to get the color resource id of a custom color specified in your colors.xml.
Set the number of times the animation will repeat by setting the object’s repeatCount value. Then you set its repeatMode to define what the animation does when it reaches the end. More on this soon!
Set duration and start the animation.
Build and run. Pick the Background color item and tap on the screen.
That’s amazing! Hey, you’re getting the hang of this pretty quickly. That’s a buttery-smooth background color change :]
Combining Animations
Animating a view is pretty awesome, but so far you’ve changed only one property and one object at a time. Animations need not be so restrictive.
It’s time to send Doge to the moon! :]
AnimatorSet allows you to play several animations together or in sequence. You pass your first animator to play(), which accepts an Animator object as an argument and returns a builder.
Then you can call the following methods on that builder, all of which accept Animator as an argument:
with() — to play the Animator passed as the argument simultaneously with the first one you specified in play()
before() — to play it before
after() — to play it after
You can create chains of calls such as these.
Open LaunchAndSpinAnimatorSetAnimatorActivity.kt in your editor, and put the following code into onStartAnimation():
// 1 val positionAnimator = ValueAnimator.ofFloat(0f, -screenHeight) // 2 positionAnimator.addUpdateListener { val value = it.animatedValue as Float rocket.translationY = value } // 3 val rotationAnimator = ObjectAnimator.ofFloat(rocket, "rotation", 0f, 180f) // 4 val animatorSet = AnimatorSet() // 5 animatorSet.play(positionAnimator).with(rotationAnimator) // 6 animatorSet.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION animatorSet.start()
Here’s what you’re doing in this block:
Create a new ValueAnimator.
Attach an AnimatorUpdateListener to the ValueAnimator that updates the rocket’s position.
Create an ObjectAnimator, a second animator that updates the rocket’s rotation.
Create a new instance of AnimatorSet.
Specify that you’d like to execute positionAnimator together with rotationAnimator.
Just as with a typical animator, you set a duration and call start().
Build and run again. Select the Launch and spin (AnimatorSet). Tap the screen.
Doge defies the laws of physics with this one.
There’s a nifty tool to simplify animating several properties of the same object. The tool is called…
ViewPropertyAnimator
One of the greatest things about animation code that uses ViewPropertyAnimator is that it’s easy to write and read — you’ll see.
Open LaunchAndSpinViewPropertyAnimatorAnimationActivity.kt and add the following call to onStartAnimation():
rocket.animate() .translationY(-screenHeight) .rotationBy(360f) .setDuration(BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION) .start()
In here, animate() returns an instance of ViewPropertyAnimator so you can chain the calls.
Build and run, select Launch and spin (ViewPropertyAnimator), and you’ll see the same animation as in the previous section.
Compare your code for this section to the AnimatorSet code snippet that you implemented in the previous section:
val positionAnimator = ValueAnimator.ofFloat(0f, -screenHeight) positionAnimator.addUpdateListener { val value = it.animatedValue as Float rocket?.translationY = value } val rotationAnimator = ObjectAnimator.ofFloat(rocket, "rotation", 0f, 180f) val animatorSet = AnimatorSet() animatorSet.play(positionAnimator).with(rotationAnimator) animatorSet.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION animatorSet.start()
ViewPropertyAnimator may provide better performance for multiple simultaneous animations. It optimizes invalidated calls, so they only take place once for several properties — in contrast to each animated property causing its own invalidation independently.
Animating the Same Property of Two Objects
A nice feature of ValueAnimator is that you can reuse its animated value and apply it to as many objects as you like.
Test it out by opening FlyWithDogeAnimationActivity.kt and putting the following code in onStartAnimation():
//1 val positionAnimator = ValueAnimator.ofFloat(0f, -screenHeight) positionAnimator.addUpdateListener { val value = it.animatedValue as Float rocket.translationY = value doge.translationY = value } //2 val rotationAnimator = ValueAnimator.ofFloat(0f, 360f) rotationAnimator.addUpdateListener { val value = it.animatedValue as Float doge.rotation = value } //3 val animatorSet = AnimatorSet() animatorSet.play(positionAnimator).with(rotationAnimator) animatorSet.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION animatorSet.start()
In the above code you just created three animators:
positionAnimator — for changing positions of both rocket and doge
rotationAnimator — for rotating Doge
animatorSet — to combine the first two animators
Notice that you set translation for two objects at once in the first animator.
Run the app and select Don’t leave Doge behind (Animating two objects). You know what to do now. To the moon!
Animation Listeners
Animation typically implies that a certain action has occurred or will take place. Typically, whatever happens usually comes at the end of your fancy animation.
You don’t get to observe it, but know that the rocket stops and stays off screen when the animation ends. If you don’t plan to land it or finish the activity, you could remove this particular view to conserve resources.
AnimatorListener — receives a notification from the animator when the following events occur:
onAnimationStart() — called when the animation starts
onAnimationEnd() — called when the animation ends
onAnimationRepeat() — called if the animation repeats
onAnimationCancel() — called if the animation is canceled
Open WithListenerAnimationActivity.kt and add the following code to onStartAnimation():
//1 val animator = ValueAnimator.ofFloat(0f, -screenHeight) animator.addUpdateListener { val value = it.animatedValue as Float rocket.translationY = value doge.translationY = value } // 2 animator.addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) { // 3 Toast.makeText(applicationContext, "Doge took off", Toast.LENGTH_SHORT) .show() } override fun onAnimationEnd(animation: Animator) { // 4 Toast.makeText(applicationContext, "Doge is on the moon", Toast.LENGTH_SHORT) .show() finish() } override fun onAnimationCancel(animation: Animator) {} override fun onAnimationRepeat(animation: Animator) {} }) // 5 animator.duration = 5000L animator.start()
The structure of the code above, with the exception of the listener part, should look the same as the previous section. Here’s what you’re doing in there:
Create and set up an animator. You use ValueAnimator to change the position of two objects simultaneously — you can’t do the same thing with a single ObjectAnimator.
Add the AnimatorListener.
Show a toast message when the animation starts
And another toast when it ends
Start the animation as usual
Run the app. Select Animation events. Tap on the screen. Look at the messages!
Note: You also can add a listener to ViewPropertyAnimator by adding a setListener to a call chain before calling start():
rocket.animate().setListener(object : Animator.AnimatorListener { // Your action })
Alternatively, you can set start and end actions on your View by calling withStartAction(Runnable) and withEndAction(Runnable) after animate(). It’s the equivalent to an AnimatorListener with these actions.
Animation Options
Animations are not one-trick ponies that simply stop and go. They can loop, reverse, run for a specific duration, etc.
In Android, you can use the following methods to adjust an animation:
repeatCount — specifies the number of times the animation should repeat after the initial run.
repeatMode — defines what this animation should do when it reaches the end
duration — specifies the animation’s total duration
Open up FlyThereAndBackAnimationActivity.kt, and add the following to onStartAnimation().
// 1 val animator = ValueAnimator.ofFloat(0f, -screenHeight) animator.addUpdateListener { val value = it.animatedValue as Float rocket.translationY = value doge.translationY = value } // 2 animator.repeatMode = ValueAnimator.REVERSE // 3 animator.repeatCount = 3 // 4 animator.duration = 500L animator.start()
In here, you:
Create an animator, as usual
You can set the repeatMode to either of the following:
RESTART — restarts the animation from the beginning.
REVERSE — reverses the animation’s direction with every iteration.
In this case, you set it to REVERSE because you want the rocket to take off and then go back to the same position where it started. Just like SpaceX! :]
…Except you’ll do it twice.
Set a duration and start the animation, as usual.
Note: So why does the third section specify the repeat count at three? Each up-and-down motion consumes two repetitions, so you need three to bring Doge back to earth twice: one to land the first time, and two to launch and land again. How many times would you like to see Doge bounce? Play around with it!
Run the app. Select Fly there and back (Animation options) in the list. A new screen is opened. Tap on the screen.
You should see your rocket jumping like a grasshopper! Take that, Elon Musk. :]
Declaring Animations in XML
You’ve made it to the best part of this tutorial. In this final section, you’ll learn how to declare once and use everywhere — yes, that’s right, you’ll be able to reuse your animations with impunity.
By defining animations in XML, you allow reuse of animations throughout your code base.
Defining animations in XML bears some resemblance to composing view layouts.
The starter project has an animation XML in res/animator named jump_and_blink.xml. Open the file in the editor, you should see this:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://ift.tt/1bfIhL2; android:ordering="together"> </set>
The following XML tags are available to you:
set — the same as AnimatorSet
animator — the same as ValueAnimator
objectAnimator — you guessed correctly; it stands for ObjectAnimator
When using an AnimatorSet in XML, you nest the ValueAnimator and ObjectAnimator objects inside it, similar to how you nest View objects inside ViewGroup objects (RelativeLayout, LinearLayout, etc.) in layout XML files.
Replace the contents of jump_and_blink.xml with the following code:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://ift.tt/1bfIhL2; android:ordering="together"> <objectAnimator android:propertyName="alpha" android:duration="1000" android:repeatCount="1" android:repeatMode="reverse" android:interpolator="@android:interpolator/linear" android:valueFrom="1.0" android:valueTo="0.0" android:valueType="floatType"/> <objectAnimator android:propertyName="translationY" android:duration="1000" android:repeatCount="1" android:repeatMode="reverse" android:interpolator="@android:interpolator/bounce" android:valueFrom="0" android:valueTo="-500" android:valueType="floatType"/> </set>
Here you declare a root element, set tag. Its ordering attribute can be either together or sequential. It’s together by default, but you may prefer to specify it for clarity. The set tag has two child XML tags, each of which is an objectAnimator.
Take a look at the following attributes of objectAnimator:
android:valueFrom and android:valueTo — specify start and end values like you did when you created an instance of ObjectAnimator
android:valueType — value type; either floatType or intType
android:propertyName — the property you want to animate without the set part
android:duration — duration of the animation
android:repeatCount — the same as with setRepeatCount
android:repeatMode — the same as with setRepeatMode
android:interpolator — specify interpolator; it usually starts with @android:interpolator/. Start typing this and Android Studio will show all available interpolators under autocomplete options
You can’t specify your target object here, but you can do it later in Kotlin
In the last block, you added two instances of objectAnimator to the AnimatorSet, and they will play together. Now, it’s time to use them.
Go to XmlAnimationActivity.kt and add the following code to onStartAnimation():
// 1 val rocketAnimatorSet = AnimatorInflater.loadAnimator(this, R.animator.jump_and_blink) as AnimatorSet // 2 rocketAnimatorSet.setTarget(rocket) // 3 val dogeAnimatorSet = AnimatorInflater.loadAnimator(this, R.animator.jump_and_blink) as AnimatorSet // 4 dogeAnimatorSet.setTarget(doge) // 5 val bothAnimatorSet = AnimatorSet() bothAnimatorSet.playTogether(rocketAnimatorSet, dogeAnimatorSet) // 6 bothAnimatorSet.duration = BaseAnimationActivity.Companion.DEFAULT_ANIMATION_DURATION bothAnimatorSet.start()
In the above code, you’re doing a few things:
First, you load AnimatorSet from R.animator.jump_and_blink file, just like you normally would to inflate a view layout
Then you set rocket as the target for just-loaded animator
Load the animator from the same file once again
Rinse and repeat for doge object
Now you create a third AnimatorSet and set it up to play the first two simultaneously
Set the duration for the root animator and start
Whew! Rest just a little bit :]
Build and run. Select Jump and blink (Animations in XML) in the list. Tap to see your handiwork.
You should see Doge jumping, disappearing and then returning back to the ground safely :]
Where To Go From Here
You can grab the final project here.
During this tutorial you:
Created and used property animations with ValueAnimator and ObjectAnimator
Set up time interpolator of your choice for your animation
Animated position, rotation and color for View
Combined animations together
Used the spectacular ViewPropertyAnimator with the help of animate()
Repeated your animation
Defined the animation in XML for reuse across the project
Basically, you just gained Android animation super-powers.
If you’re hungry for more, check out the available time interpolators in Android’s documentation (see Known Indirect Subclasses). If you’re not happy with either of them, you can create your own. You can also set Keyframes for your animation to make them very sophisticated.
Android has other animations systems like View animations and Drawable Animations. You can also make use of Canvas and OpenGL ES APIs to create animations. Stay tuned :]
I hope you enjoyed the Introduction to Android Animations tutorial. Chime in with your questions, ideas and feedback in the forums below!
The post Android Animation Tutorial with Kotlin appeared first on Ray Wenderlich.
Android Animation Tutorial with Kotlin published first on http://ift.tt/2fA8nUr
0 notes
iyarpage · 7 years
Text
Reactive Programming with RxAndroid in Kotlin: An Introduction
Update note: This tutorial has been updated to Kotlin, Android 26 (Oreo), and Android Studio 3.0 Beta 5 by Irina Galata. The original tutorial was written by Artem Kholodnyi.
They say you should develop a proactive mindset in life, not a reactive one. That does not apply to Android programming, however! :]
Reactive programming is not just another API. It’s a whole new paradigm and a very useful one. RxJava is a reactive implementation used on Android. Android is a perfect place to start your exploration of the reactive world. It’s made even easier with RxAndroid, a library that wraps asynchronous UI events to be more RxJava like.
Don’t be scared — I’ll bet the basic concept of reactive programming is known to you even if you are not aware of it yet. :]
Note: This tutorial requires good knowledge of Android and Kotlin. To get up to speed, check out our Android Development Tutorials first and return to this tutorial when you’re ready.
In this RxAndroid tutorial you will learn how to do the following:
understand what Reactive Programming is
define an observable
turn asynchronous events like button clicks and text field context changes into observables
transform observable items
filter observable items
specify the thread on which code should be executed
combine several observables into one
I hope you like cheese — because you’re going to build a cheese-finding app as you learn the concepts above! :]
Getting Started
Download the starter project for this tutorial and open it in Android Studio 3.0 Beta 5 or above.
You’ll be working exclusively in CheeseActivity.kt. The CheeseActivity class extends BaseSearchActivity; take some time to explore BaseSearchActivity and check out the following features ready for your use:
showProgress(): A function to show a progress bar…
hideProgress(): … and a function to hide it.
showResult(result: List): A function to display a list of cheeses.
cheeseSearchEngine: A field which is an instance of CheeseSearchEngine. It has a search function which you call when you want to search for cheeses. It accepts a text search query and returns a list of matching cheeses.
Build and run the project on your Android device or emulator. You should see a gloriously empty search screen:
What is Reactive Programming?
Before creating your first observable, indulge yourself with a bit of a theory first. :]
In imperative programming, an expression is evaluated once and a value is assigned to a variable:
var x = 2 var y = 3 var z = x * y // z is 6 x = 10 // z is still 6
On the other hand, reactive programming is all about responding to value changes.
You have probably done some reactive programming — even if you didn’t realize it at the time.
Defining cell values in spreadsheets is similar to defining variables in imperative programming.
Defining cell expressions in spreadsheets is similar to defining and operating on observables in reactive programming.
Take the following spreadsheet that implements the example from above:
The spreadsheet assigns cell B1 with a value of 2, cell B2 with a value of 3 and a third cell, B3, with an expression that multiplies the value of B1 by the value of B2. When the value of either of the the components referenced in the expression changes, the change is observed and the expression is re-evaluated automagically in B3:
Difference between RxJava and RxKotlin
As you probably know, it’s possible to use Java libraries in Kotlin projects thanks to Kotlin’s language compatibility with Java. If that’s the case, then why was RxKotlin created in the first place? RxKotlin is a Kotlin wrapper around RxJava, which also provides plenty of quite useful extension functions. Effectively, RxKotlin makes working with RxJava more Kotlin-y.
In this article, we’ll focus on using RxJava, since it’s critical to understand the core concepts of this approach, however everything you will learn applies to RxKotlin as well.
Note: Take a look at the build.gradle file and the project dependencies especially. Except for the UI libraries, it contains RxKotlin and RxAndroid packages. We don’t need to specify RxJava here explicitly since RxKotlin already contains it.
RxJava Observable Contract
RxJava make use of the Observer pattern.
Note: To refresh your memory about the Observer pattern you can visit Common Design Patterns for Android with Kotlin.
In the Observer pattern, you have objects that implement two key RxJava interfaces: Observable and Observer. When an Observable changes state, all Observer objects subscribed to it are notified.
Among the methods in the Observable interface is subscribe(), which an Observer will call to begin the subscription.
From that point, the Observer interface has three methods which the Observable calls as needed:
onNext(T value) provides a new item of type T to the Observer
onComplete() notifies the Observer that the Observable has finished sending items
onError(Throwable e) notifies the Observer that the Observable has experienced an error
As a rule, a well-behaved Observable emits zero or more items that could be followed by either completion or error.
That sounds complicated, but some marble diagrams may clear things up.
The circle represents an item that has been emitted from the observable and the black block represents a completion or error. Take, for example, a network request observable. The request usually emits a single item (response) and immediately completes.
A mouse movement observable would emit mouse coordinates but will never complete:
Here you can see multiple items that have been emitted but no block showing the mouse has completed or raised an error.
No more items can be emitted after an observable has completed. Here’s an example of a misbehaving observable that violates the Observable contract:
That’s a bad, bad observable because it violates the Observable contract by emitting an item after it signaled completion.
How to Create an Observable
There are many libraries to help you create observables from almost any type of event. However, sometimes you just need to roll your own. Besides, it’s a great way to learn!
You’ll create an Observable using Observable.create(). Here is its signature:
Observable<T> create(ObservableOnSubscribe<T> source)
That’s nice and concise, but what does it mean? What is the “source?” To understand that signature, you need to know what an ObservableOnSubscribe is. It’s an interface, with this contract:
public interface ObservableOnSubscribe<T> { void subscribe(ObservableEmitter<T> e) throws Exception; }
Like an episode of a J.J. Abrams show like “Lost” or “Westworld,” that answers some questions while inevitably asking more. So the “source” you need to create your Observable will need to expose subscribe(), which in turn requires whatever’s calling it to provide an “emitter” as a parameter. What, then, is an emitter?
RxJava’s Emitter interface is similar to the Observer one:
public interface Emitter<T> { void onNext(T value); void onError(Throwable error); void onComplete(); }
An ObservableEmitter, specifically, also provides a means to cancel the subscription.
To visualize this whole situation, think of a water faucet regulating the flow of water. The water pipes are like an Observable, willing to deliver a flow of water if you have a means of tapping into it. You construct a faucet that can turn on and off, which is like an ObservableEmitter, and connect it to the water pipes in Observable.create(). The outcome is a nice fancy faucet. :]
An example will make the situation less abstract and more clear. It’s time to create your first observable! :]
Observe Button Clicks
Add the following code inside the CheeseActivity class:
// 1 private fun createButtonClickObservable(): Observable<String> { // 2 return Observable.create { emitter -> // 3 searchButton.setOnClickListener { // 4 emitter.onNext(queryEditText.text.toString()) } // 5 emitter.setCancellable { // 6 searchButton.setOnClickListener(null) } } }
Your imports should look as follows after entering the above code:
import io.reactivex.Observable import kotlinx.android.synthetic.main.activity_cheeses.*
You’ve imported the correct Observable class and you’re using the Kotlin Android Extensions to get references to view objects.
Here’s what’s going on in the code above:
You declare a function that returns an observable that will emit strings.
You create an observable with Observable.create(), and supply it with a new ObservableOnSubscribe.
Set up an OnClickListener on searchButton.
When the click event happens, call onNext on the emitter and pass it the current text value of queryEditText.
Keeping references can cause memory leaks in Java or Kotlin. It’s a useful habit to remove listeners as soon as they are no longer needed. But what do you call when you are creating your own Observable? For that very reason, ObservableEmitter has setCancellable(). Override cancel(), and your implementation will be called when the Observable is disposed, such as when the Observable is completed or all Observers have unsubscribed from it.
For OnClickListener, the code that removes the listener is setOnClickListener(null).
Now that you’ve defined your Observable, you need to set up the subscription to it. Before you do, you need to learn about one more interface, Consumer. It’s a simple way to accept values coming in from an emitter.
public interface Consumer<T> { void accept(T t) throws Exception; }
This interface is handy when you want to set up a simple subscription to an Observable.
The Observable interface requires several versions of subscribe(), all with different parameters. For example, you could pass a full Observer if you like, but then you’d need to implement all the necessary methods.
If all you need out of your subscription is for the observer to respond to values sent to onNext(), you can use the version of subscribe() that takes in a single Consumer (the parameter is even named onNext, to make the connection clear).
You’ll do exactly that when you subscribe in your activity’s onStart(). Add the following code to CheeseActivity.kt:
override fun onStart() { super.onStart() // 1 val searchTextObservable = createButtonClickObservable() searchTextObservable // 2 .subscribe { query -> // 3 showResult(cheeseSearchEngine.search(query)) } }
Here’s an explanation of each step:
First, create an observable by calling the method you just wrote.
Subscribe to the observable with subscribe(), and supply a simple Consumer.
Finally, perform the search and show the results.
Build and run the app. Enter some letters and press the Search button. After a simulated delay (see CheeseSearchEngine), you should see a list of cheeses that match your request:
Sounds yummy! :]
RxJava Threading Model
You’ve had your first taste of reactive programming. There is one problem though: the UI freezes up for a few seconds when the search button is pressed.
You might also notice the following line in Android Monitor:
> 08-24 14:36:34.554 3500-3500/com.raywenderlich.cheesefinder I/Choreographer: Skipped 119 frames! The application may be doing too much work on its main thread.
This happens because search is executed on the main thread. If search were to perform a network request, Android will crash the app with a NetworkOnMainThreadException exception. It’s time to fix that.
One popular myth about RxJava is that it is multi-threaded by default, similar to AsyncTask. However, if not otherwise specified, RxJava does all the work in the same thread it was called from.
You can change this behavior with the subscribeOn and observeOn operators.
subscribeOn is supposed to be called only once in the chain of operators. If it’s not, the first call wins. subscribeOn specifies the thread on which the observable will be subscribed (i.e. created). If you use observables that emit events from an Android View, you need to make sure subscription is done on the Android UI thread.
On the other hand, it’s okay to call observeOn as many times as you want in the chain. observeOn specifies the thread on which the next operators in the chain will be executed. For example:
myObservable // observable will be subscribed on i/o thread .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map { /* this will be called on main thread... */ } .doOnNext{ /* ...and everything below until next observeOn */ } .observeOn(Schedulers.io()) .subscribe { /* this will be called on i/o thread */ }
The most useful schedulers are:
Schedulers.io(): Suitable for I/O-bound work such as network requests or disk operations.
Schedulers.computation(): Works best with computational tasks like event-loops and processing callbacks.
AndroidSchedulers.mainThread() executes the next operators on the UI thread.
The Map Operator
The map operator applies a function to each item emitted by an observable and returns another observable that emits results of those function calls. You’ll need this to fix the threading issue as well.
If you have an observable called numbers that emits the following:
And if you apply map as follows:
numbers.map { number -> number * number }
The result would be the following:
That’s a handy way to iterate over multiple items with little code. Let’s put it to use!
Modify onStart() in CheeseActivity class to look like the following:
override fun onStart() { super.onStart() val searchTextObservable = createButtonClickObservable() searchTextObservable // 1 .subscribeOn(AndroidSchedulers.mainThread()) // 2 .observeOn(Schedulers.io()) // 3 .map { cheeseSearchEngine.search(it) } // 4 .observeOn(AndroidSchedulers.mainThread()) .subscribe { showResult(it) } }
Going over the code above:
First, specify that code down the chain should start on the main thread instead of on the I/O thread. In Android, all code that works with Views should execute on the main thread.
Specify that the next operator should be called on the I/O thread.
For each search query, you return a list of results.
Finally, make sure that the results are passed to the list on the main thread
Build and run your project. Now the UI should be responsive even when a search is in progress.
Show Progress Bar with doOnNext
It’s time to display the progress bar!
For that you’ll need a doOnNext operator. doOnNext takes a Consumer and allows you do something each time an item is emitted by observable.
In the same CheeseActivity class modify onStart() to the following:
override fun onStart() { super.onStart() val searchTextObservable = createButtonClickObservable() searchTextObservable // 1 .observeOn(AndroidSchedulers.mainThread()) // 2 .doOnNext { showProgress() } .observeOn(Schedulers.io()) .map { cheeseSearchEngine.search(it) } .observeOn(AndroidSchedulers.mainThread()) .subscribe { // 3 hideProgress() showResult(it) } }
Taking each numbered comment in turn:
Ensure that the next operator in chain will be run on the main thread.
Add the doOnNext operator so that showProgress() will be called every time a new item is emitted.
Don’t forget to call hideProgress() when you are just about to display a result.
Build and run your project. You should see the progress bar appearing when you initiate the search:
Observe Text Changes
What if you want to perform search automatically when the user types some text, just like Google?
First, you need to subscribe to TextView text changes. Add the following function to the CheeseActivity class:
// 1 private fun createTextChangeObservable(): Observable<String> { // 2 val textChangeObservable = Observable.create<String> { emitter -> // 3 val textWatcher = object : TextWatcher { override fun afterTextChanged(s: Editable?) = Unit override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit // 4 override fun onTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { s?.toString()?.let { emitter.onNext(it) } } } // 5 queryEditText.addTextChangedListener(textWatcher) // 6 emitter.setCancellable { queryEditText.removeTextChangedListener(textWatcher) } } // 7 return textChangeObservable }
Here’s the play-by-play of each step above:
Declare a function that will return an observable for text changes.
Create textChangeObservable with create(), which takes an ObservableOnSubscribe.
When an observer makes a subscription, the first thing to do is to create a TextWatcher.
You aren’t interested in beforeTextChanged() and afterTextChanged(). When the user types and onTextChanged() triggers, you pass the new text value to an observer.
Add the watcher to your TextView by calling addTextChangedListener().
Don’t forget to remove your watcher. To do this, call emitter.setCancellable() and overwrite cancel() to call removeTextChangedListener()
Finally, return the created observable.
To see this observable in action, replace the declaration of searchTextObservable in onStart() of CheeseActivity as follows:
val searchTextObservable = createTextChangeObservable()
Build and run your app. You should see the search kick off when you start typing text in the TextView:
Filter Queries by Length
It doesn’t make sense to search for queries as short as a single letter. To fix this, let’s introduce the powerful filter operator.
filter passes only those items which satisfy a particular condition. filter takes in a Predicate, which is an interface that defines the test that input of a given type needs to pass, with a boolean result. In this case, the Predicate takes a String and returns true if the string’s length is two or more characters.
Replace return textChangeObservable in createTextChangeObservable() with the following code:
return textChangeObservable.filter { it.length >= 2 }
Everything will work exactly the same, except that text queries with length less than 2 won’t get sent down the chain.
Run the app; you should see the search kick off only when you type the second character:
Debounce operator
You don’t want to send a new request to the server every time the query is changed by one symbol.
debounce is one of those operators that shows the real power of reactive paradigm. Much like the filter operator, debounce, filters items emitted by the observable. But the decision on whether the item should be filtered out is made not based on what the item is, but based on when the item was emitted.
debounce waits for a specified amount of time after each item emission for another item. If no item happens to be emitted during this wait, the last item is finally emitted:
In createTextChangeObservable(), add the debounce operator just below the filter so that the return statement will look like the following code:
return textChangeObservable .filter { it.length >= 2 } .debounce(1000, TimeUnit.MILLISECONDS) // add this line
Run the app. You’ll notice that the search begins only when you stop making quick changes:
debounce waits for 1000 milliseconds before emitting the latest query text.
Merge Operator
You started by creating an observable that reacted to button clicks and then implemented an observable that reacts to text field changes. But how do you react to both?
There are a lot of operators to combine observables. The most simple and useful one is merge.
merge takes items from two or more observables and puts them into a single observable:
Change the beginning of onStart() to the following:
val buttonClickStream = createButtonClickObservable() val textChangeStream = createTextChangeObservable() val searchTextObservable = Observable.merge<String>(buttonClickStream, textChangeStream)
Run your app. Play with the text field and the search button; the search will kick off either when you finish typing two or more symbols or when you simply press the Search button.
RxJava and Activity/Fragment lifecycle
Remember those setCancellable methods you set up? They won’t fire until the observable is unsubscribed.
The Observable.subscribe() call returns a Disposable. Disposable is an interface that has two methods:
public interface Disposable { void dispose(); // ends a subscription boolean isDisposed(); // returns true if resource is disposed (unsubscribed) }
Add the following property to CheeseActivity:
private lateinit var disposable: Disposable
In onStart(), set the returned value of subscribe() to disposable with the following code (only the first line changes):
disposable = searchTextObservable // change this line .observeOn(AndroidSchedulers.mainThread()) .doOnNext { showProgress() } .observeOn(Schedulers.io()) .map { cheeseSearchEngine.search(it) } .observeOn(AndroidSchedulers.mainThread()) .subscribe { hideProgress() showResult(it) }
Since you subscribed to the observable in onStart(), onStop() would be a perfect place to unsubscribe.
Add the following code to CheeseActivity.kt:
@Override override fun onStop() { super.onStop() if (!disposable.isDisposed) { disposable.dispose() } }
And that’s it! Build and run the app. You won’t “observe” any changes yourself, but now the app is successfully avoiding RxJava memory leaks. :]
Where to Go From Here?
You can download the final project from this tutorial here.
You’ve learned a lot in this tutorial. But that’s only a glimpse of the RxJava world. For example, there is RxBinding, a library that includes most of the Android View APIs. Using this library, you can create a click observable by just calling RxView.clicks(viewVariable).
To learn more about RxJava refer to the ReactiveX documentation.
What’s new in RxJava 2
The second version of RxJava is quite different from the first one, since RxJava 2 was completely rewritten. You should get acquainted with some entirely new classes like Flowable and Maybe.
With Flowable, you can now avoid getting such well-known problems as MissingBackpressureException or OutOfMemoryError. You can use it to handle a flow of 10k+ elements.
Maybe is a combination of Single and Completable. Like Single, it can receive at most one item or fail, and like Completable it can finish successfully without any received items or fail.
Find some time to skim all the changelog of RxJava2 :]
If you have any comments or questions, don’t hesitate to join the discussion below!
The post Reactive Programming with RxAndroid in Kotlin: An Introduction appeared first on Ray Wenderlich.
Reactive Programming with RxAndroid in Kotlin: An Introduction published first on http://ift.tt/2fA8nUr
0 notes