Android Dice Roller Source Code for Apps
An Android Dice Roller tutorial with source code for a basic dice roller app. OK it might not be a fancy 3D dice roller but it'll get you going. You can always upgrade your dice roller code later. Simply add the example source code to any app that requires a dice roll. Dice face images and a 3D dice icon image are provided, all the images and code are free to use and royalty free. The code here is for a six sided dice but can be adapted for larger dice or more than one dice. There are no restrictions placed upon the code or the dice face images (all the images are free as they are in the public domain).
By the way (BTW) I know that dice is the plural and means two or more die, but it is common to refer to one die as a dice so we will be doing that here.
(This Android dice roller tutorial assumes that Android Studio is installed, a basic App can be created and run, and the code in this article can be correctly copied into Android Studio. The example code can be changed to meet your own requirements. When entering code in Studio add import statements when prompted by pressing Alt-Enter.)
The Dice Face Images and Sound
The code given in this article is for a common six sided dice. A dice is a cube, and each side of the cube (each face) has one of the numbers from one to six. Here six PNG images are used to show the dice roll result. Plus there is a 3D image shown for the dice roll. The same 3D image is used for the app icon. The dice images are from Open Clip Art Library user rg1024.
The sound of a dice roll is stored in shake_dice.mp3. It is by Mike Koenig and is from SoundBilble.com.
All the resources ready to add into a Android Studio project are available from this dice resources Zip file.
Android Studio Dice Roller Project
For this tutorial start a new Android Studio project. Here the Application name is Dice and an Empty Activity is used with other settings left at default values. Add the dice resources (from above) to the project by copying them to the res folder. Studio will update the Project explorer automatically (or use the Synchronize option).
Optionally change the app icon entries in the AndroidManifest.xml file to dice3d and dice3d_rounded.png, i.e. android:icon="@drawable/dice3d"
and android:roundIcon="@mipmap/dice3d_rounded"
.
Android Dice Roller Project Layout
The screen for the dice roller is very simple. Just an ImageView
which when pressed the roll is performed. If using the basic starting empty screen then open the activity_main.xml layout file. Delete the Hello World! default TextView
(if present). From the widget Pallete, under Images, drag and drop an ImageView onto the layout and select dice3droll on the Resources chooser dialog. (Add the constraints if using a ConstraintLayout
.)
The layout source should be similar to the following:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.example.dice.MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:contentDescription="Press for Dice Roll"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/dice3droll" />
</android.support.constraint.ConstraintLayout>
Android Dice Roller Source Code
A Java Random
class (to generate the dice numbers) is declared along with an Android SoundPool
(to play the dice roll sound). To load the right picture for each roll a switch statement is used. Some feedback is provided to the user so that they can see that a new roll has occurred. An identical number can be rolled in succession. To provide the feedback a 3D dice image will be displayed. However, because the roll happens so fast (unlike a real dice) the 3D image would not be seen. Therefore a Timer
is used to provide a delay. This allows the UI to update. The Timer sends a Handler
message signal to a Callback
to perform the roll (the same method as described in the post Why Your TextView or Button Text Is Not Updating). Finally the roll value is used to update the UI.
Update: The creation of the SoundPool object has changed due to the deprecation of the constructor in Android API 21 and later. The code has been changed to allow for this, using a SoundPool.Builder
. To support pre-Lollipop Android versions a new class is added to the project called PreLollipopSoundPool. The code for this new class follows this MainActivity class:
package com.example.dice;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
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?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Our function to initialise sound playing
InitSound();
//Get a reference to image widget
dice_picture = (ImageView) findViewById(R.id.imageView);
dice_picture.setOnClickListener(new HandleClick());
//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.dice3droll);
//Start rolling sound
dice_sound.play(sound_id, 1.0f, 1.0f, 0, 0, 1.0f);
//Pause to allow image to update
timer.schedule(new Roll(), 400);
}
}
}
//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:
dice_picture.setImageResource(R.drawable.one);
break;
case 2:
dice_picture.setImageResource(R.drawable.two);
break;
case 3:
dice_picture.setImageResource(R.drawable.three);
break;
case 4:
dice_picture.setImageResource(R.drawable.four);
break;
case 5:
dice_picture.setImageResource(R.drawable.five);
break;
case 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 in the same folder as the MainActivity class. Creating it as a separate class supports Java lazy loading, ensuring the app works when the deprecated method is removed from Android.
package com.example.dice;
import android.media.AudioManager;
import android.media.SoundPool;
/**
* Created a pre Lollipop SoundPool
*/
final class PreLollipopSoundPool {
@SuppressWarnings("deprecation")
public static SoundPool NewSoundPool() {
return new SoundPool(1, AudioManager.STREAM_MUSIC,0);
}
}
The Android dice roller source code is now ready to run, either in an AVD or an actual Android device.
The complete source code is available in android_dice_roller.zip or from the Android Example Projects page. The code can be seen running using Dice.apk, also available from the projects page.
See Also
- The dice images were from the Open Clip Art Library by rg1024.
- The dice roll sound is from the SoundBible.com.
- See the other Android Studio example projects to learn Android app programming.
Archived Comments
Phil said on 27/09/2014: Nice code. I’m hoping to write a more complex Roller, and this is very useful!
Cesar said on 18/07/2013: I don't get it. I have tried and tried, but I don't get it. Line handler=new Handler(callback);
shows me an error. callback execution doesn't enter handleMessage(Message msg)
. If I initialize new Handler(callback);
in other ways the app crashes. Can you help me, please? Thanks a lot!
Tek Eye said, in reply to Cesar, on 18/07/2013: Hi, the Handler class used here is from android.os and not java.util.logging, Callback is from android.os as well, though you probably used the correct imports. To help I’ve added a zip file with all the source code to the Android Example Projects page as well as a link in this article. You can import the code from the Zip file into a new Android project and run it to see it working. Failing that there is an APK file on the same page to install onto a device to see the code working (link to APK in article as well). Note you may need to change your device settings temporarily to allow the APK to be installed, only install APKs from trusted sources.
Author:Daniel S. Fowler Published: Updated: