BirdFriend is an Android app inspired by "Tabikaeru" - a mobile game about a travelling frog. Bird himself is inspried by "Haikyuu" - a volleyball sports anime.
Bird is either home or away, while bird is away, he will send users post cards (notifications) about his adventures.
Tech Stack: Kotlin and Android SDK
⭐️ Notifications of post cards from bird
⭐️ Put a bird on it (user's own photo)
⭐️ Share post card and photo to instagram or other apps
WorkManger was used to schedule tasks on logging bird's latest status of home or away to log_state_table. And if away it will also queue for adding a new post card to trigger notification for users by changing image status to TRUE. Two OneTimeWorkRequest are triggered when user click on packing luggage with a delay of 1 to 2 hours.
- HomeAwayWorker - will randomly assign Home or Away to database with timestamp
- AddPostWorker - if away from above, it will schedul adding new post card to database and send notification to users
Dependencies added for Work to build.gradle
def work_version = "2.3.4"
// (Java only)
implementation "androidx.work:work-runtime:$work_version"
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"Room database was used to create user_cards_table and log_state_table (for local storage). 3 main components of room: Entity, Dao and Database.
Dependencies added for Room to build.gradle
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"NotificationCompat APIs was used to set up notification to inform users of new post card from bird!
Dependencies added for Work to build.gradle
//noinspection GradleCompatible
implementation "com.android.support:support-compat:28.0.0"The task of adding a bird's image on top of a user's photo requires some image manipulation and media storage of user's phone
- Create empty Bitmap and Canvas to draw user's image and bird image
- When user selects a photo, use ImageDecoder to transform image to Bitmap and draw on copy of created Bitmap
- Transform drawable bird image into bitmap and draw on canvas
- In order to share to external app, the new image of bird and user's image requires storage to MediaStore.Images.Media
Intent was used to share post cards to other apps (Instagram, messages etc.) It was also used to access user's photo
Example code
shareButton.setOnClickListener{
var imageName = card.imgname
val imageURI = Uri.parse("android.resource://com.example.birdfriend/"+resourceID)
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, imageURI)
putExtra(Intent.EXTRA_TEXT, "My bird friend went on an adventure today! $imageName")
type = "image/jpg"
}
val shareIntent = Intent.createChooser(sendIntent, "Send your image:")
startActivity(shareIntent)
}AnimationDrawable was used to create frame-by-frame animations of bird.
Example animation xml file in drawable folder
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/fly_p1"
android:duration="200"/>
<item android:drawable="@drawable/fly_p2"
android:duration="200"/>
<item android:drawable="@drawable/fly_p3"
android:duration="200"/>
</animation-list>Manifest.permission was used to access exteranl photo of user's for bird and user image process.
Add following to AnroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>| App View | Actions |
|---|---|
![]() |
|
![]() |
|
![]() |
|
- Notifications of post cards from bird is triggered by scheduled task from WorkManager
- Notification is only sent when bird's latest status is away and with new post card added to database (logged by workManager with status FALSE)
- Once clicked on Add, post card's status will be flagged to TRUE which will show up in post cards collections and disappear from mail box
![]() |
![]() |
|---|
- Users can access their own photos when click on select your photos
- Once photo is selected, the bird will show up on the selected photo (see Bitmap and Canvas)
- User can click on share to share their new photo with bird on it (see Intent)
![]() |
![]() |
|---|
-
Why did I code BirdFriend?
- BirdFriend is a Capstone project I worked on during Ada Developers Academy Cohort 13! (3 weeks project July 2020)
-
What is cool about this app?
- Bird decides to go on trips on his own. As a user, we can only wait and be surprised by his new post card in the mail!
-
What is the hardest part of this project for me?
- Setting up bird's home or away status from backend. I used the WorkManager to queue for work request on logging bird's latest new status of away or home (see WorkManager)
- Adding bird's image to user's photo and sharing it to other apps (see Bitmap and Canvas).
-
What you learned?
- Kotlin! And it is very fun to create an App











