Hi Guys Welcome to Proto Coders Point. In this android tutorial we will learn how to create a simple dice roller app
A dnd dice roller app using android-studio. who want to learn and gain more knowledge in developing an android application.
This tutorial is not be a fancy 3D dice roller but it’ll be a simple dice that roller with some animation effect and generate a random number from 1 – 6 and show similar image of dice roller to the user.
The main moto of this android tutorial is just to build programming skill and logic.
Demo of how the final Dice Roller dnd android app looks
All the image given below are free to use .
dice vector images Download from tekeye.uk
The sound of a dice roll is stored in shake_dice.mp3. It is by Mike Koenig and is from SoundBilble.com.
dnd dice roller android studio tutorial mini project.
let’s start with creating a new project in android-studio
File > New > New Project
Give a proper name to project ( Dice Roller ) , Select a project storage destination , select minimum API : 22 ,Android 5.1 (Lollipop), all set android project will be get ready in several seconds.
Add the dice resources (from above) to the project by copying them to the res folder in android – studio.
Optional Changes
To set a icon from this dice roller app project go to AndroidManifest.xml file
android:icon="@drawable/dice3d" and android:roundIcon="@mipmap/dice3d_rounded".
Designing a UI Layout spin the dice roller
main_activity.xml
Copy the below code in main_activity.xml file
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="131dp" android:layout_height="121dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/dice3d160" /> <TextView android:id="@+id/dice_no" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Dice Number : ? Spin it " android:textSize="25sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView" app:layout_constraintVertical_bias="0.157" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#0184FC" android:textSize="25sp" android:textStyle="italic|bold" android:text="Click on the Dice to Spin it" app:layout_constraintBottom_toTopOf="@+id/imageView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Android Dice Roller Source Code
ActivityMain.java
package protocoderspoint.com.androiddicerollertutorial; import android.media.AudioAttributes; import android.media.SoundPool; import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.Bundle; import android.view.View; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.ImageView; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.util.Random; import java.util.Timer; import java.util.TimerTask; import protocoderspoint.PreLollipopSoundPool; public class MainActivity extends AppCompatActivity { ImageView dice_picture; //reference to dice picture Random rng=new Random(); //generate random numbers SoundPool dice_sound; //For dice sound playing int sound_id; //Used to control sound stream return by SoundPool Handler handler; //Post message to start roll Timer timer=new Timer(); //Used to implement feedback to user boolean rolling=false; //Is die rolling? RotateAnimation rotate; int soundplay; TextView dice_no; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Our function to initialise sound playing dice_no=(TextView)findViewById(R.id.dice_no); InitSound(); //Get a reference to image widget dice_picture = (ImageView) findViewById(R.id.imageView); dice_picture.setOnClickListener(new HandleClick()); rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(3000); rotate.setInterpolator(new LinearInterpolator()); //link handler to callback handler=new Handler(callback); } //User pressed dice, lets start private class HandleClick implements View.OnClickListener { public void onClick(View arg0) { if (!rolling) { rolling = true; //Show rolling image dice_picture.setImageResource(R.drawable.dice3d160); //Start rolling sound soundplay= dice_sound.play(sound_id, 1.0f, 1.0f, 0, 0, 1.0f); //Pause to allow image to update dice_picture.startAnimation(rotate); timer.schedule(new Roll(), 3000); } } } //New code to initialise sound playback void InitSound() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //Use the newer SoundPool.Builder //Set the audio attributes, SONIFICATION is for interaction events //uses builder pattern AudioAttributes aa = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build(); //default max streams is 1 //also uses builder pattern dice_sound= new SoundPool.Builder().setAudioAttributes(aa).build(); } else { //Running on device earlier than Lollipop //Use the older SoundPool constructor dice_sound= PreLollipopSoundPool.NewSoundPool(); } //Load the dice sound sound_id=dice_sound.load(this,R.raw.shake_dice,1); } //When pause completed message sent to callback class Roll extends TimerTask { public void run() { handler.sendEmptyMessage(0); } } //Receives message from timer to start dice roll Handler.Callback callback = new Handler.Callback() { public boolean handleMessage(Message msg) { //Get roll result //Remember nextInt returns 0 to 5 for argument of 6 //hence + 1 switch(rng.nextInt(6)+1) { case 1: rotate.cancel(); dice_no.setText("Dice Number : 1"); dice_picture.setImageResource(R.drawable.one); break; case 2: rotate.cancel(); dice_no.setText("Dice Number : 2"); dice_picture.setImageResource(R.drawable.two); break; case 3: rotate.cancel(); dice_no.setText("Dice Number : 3"); dice_picture.setImageResource(R.drawable.three); break; case 4: rotate.cancel(); dice_no.setText("Dice Number : 4"); dice_picture.setImageResource(R.drawable.four); break; case 5: rotate.cancel(); dice_no.setText("Dice Number : 5"); dice_picture.setImageResource(R.drawable.five); break; case 6: rotate.cancel(); dice_no.setText("Dice Number : 6"); dice_picture.setImageResource(R.drawable.six); break; default: } rolling=false; //user can press again return true; } }; //Clean up protected void onPause() { super.onPause(); dice_sound.pause(sound_id); } protected void onDestroy() { super.onDestroy(); timer.cancel(); } }
To support APIs pre Lollipop add a new class called PreLollipopSoundPool,java
package protocoderspoint; import android.media.AudioManager; import android.media.SoundPool; /** * Created a pre Lollipop SoundPool */ public final class PreLollipopSoundPool { @SuppressWarnings("deprecation") public static SoundPool NewSoundPool() { return new SoundPool(1, AudioManager.STREAM_MUSIC,0); } }
Explanation of the above ActivityMain.java Code
Random number
Random java – user to generate a random number from 1 to 6
Random rng=new Random(); //Get roll result //Remember nextInt returns 0 to 5 for argument of 6 //hence + 1 rng.nextInt(6)+1
Rotate a imageView in android-studio
RotateAnimation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
Set Duration for the rotator in milli-sec like (1 sec = 1000milli sec )
rotate.setDuration(3000); rotate.setInterpolator(new LinearInterpolator());
Learn more about setInterpolator ( new LinearInterpolator())
Soundpool
In Android-studio Java Soundpool is used to play a sound like in our project we have used a dice roller sound effect to feel like a real dice is spinning. Code below
SoundPool dice_sound; //For dice sound playing int sound_id; //Used to control sound stream return by SoundPool
New code to initialise sound playback
//New code to initialise sound playback void InitSound() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //Use the newer SoundPool.Builder //Set the audio attributes, SONIFICATION is for interaction events //uses builder pattern AudioAttributes aa = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build(); //default max streams is 1 //also uses builder pattern dice_sound= new SoundPool.Builder().setAudioAttributes(aa).build(); } else { //Running on device earlier than Lollipop //Use the older SoundPool constructor dice_sound= PreLollipopSoundPool.NewSoundPool(); } //Load the dice sound sound_id=dice_sound.load(this,R.raw.shake_dice,1); }
As java codes runs within a fraction of seconds, it will be hard to view the image is getting spinned or an real animation effect, i have made use of Timer method with will help programmer to show dice rolling effect.
Timer timer=new Timer(); //Used to implement Time to spin
Timer is used to provide a delay in roll.
timer.schedule(new Roll(), 3000);
above snippet code timer is set to 3 sec’s where the viewer will be above to see the animation effect for 3 sec.