I'm making an Android whack a mole game. I have the main activity which is basically the launcher, when you press the Play button the game activity starts. This works fine as it shows the background image and all molehills but I don't know how to call the method to start the game.
I've tried to call it from inside onCreate() but this ends up "playing the game" itself.
I've tried to call it right after the startActivity(intent) but the app crashes. And also I've tried to create an instance of the game class and call the play() method after the start activity but it doesn't work aswell. I don't know how to start the game method once the game activity is loaded.
I hope I explained well, thank you.
public class MainActivity extends AppCompatActivity {
ImageButton btnStart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide TitleBar
try { this.getSupportActionBar().hide();}
catch (NullPointerException e){}
setContentView(R.layout.activity_main);
btnStart = (ImageButton)findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), GameView.class);
startActivity(intent);
}
});
}
And this is the code for the game_activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide TitleBar
try { this.getSupportActionBar().hide();}
catch (NullPointerException e){}
setContentView(R.layout.activity_game_view);
game();
}
The game() method is a typical game loop.
public void game() {
Random random = new Random();
int index;
/*
* Casting array to store all ImageView on the game
*/
imgViewArray[0] = (ImageView)findViewById(R.id.img1);
imgViewArray[1] = (ImageView)findViewById(R.id.img2);
imgViewArray[2] = (ImageView)findViewById(R.id.img3);
imgViewArray[3] = (ImageView)findViewById(R.id.img4);
imgViewArray[4] = (ImageView)findViewById(R.id.img5);
imgViewArray[5] = (ImageView)findViewById(R.id.img6);
imgViewArray[6] = (ImageView)findViewById(R.id.img7);
imgViewArray[7] = (ImageView)findViewById(R.id.img8);
imgViewArray[8] = (ImageView)findViewById(R.id.img9);
imgViewArray[9] = (ImageView)findViewById(R.id.img10);
int j=0;
while (j < 10) {
// Get a random image to animate
index = random.nextInt(10);
switch(index) {
case 0: imgViewArray[0].setImageResource(images[6]);
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
imgViewArray[0].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imgViewArray[0].setImageResource(images[0]);
}
});
}
},
300 // The code executes after 300ms
);
break;
I think you should put the game() call inside onResume().
There are many ways to solve the problem:
Using EventBus
Send the start game Event from Main Activity and register for the Event in the Game activity.
This is my favorite way to handle the problem. It's because the simplicity and prevent us from tightly coupled code. The major problem with using EventBus is we will lost in the sea of Event if there are too much Event in the the app.
How to do:
First, create the Event. This is just a simple class:
public class StartGameEvent {
}
Second, register for the event in the game activity:
public class GameActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
EventBus.getDefault().register(this);
}
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
Third, subscribe for the event:
public class GameActivity extends Activity {
...
#Subscribe
public void onMessageEvent(StartGameEvent event) {
game();
}
}
Last, send the event from Main activity:
EventBus.getDefault().post(new StartGameEvent());
Using LocalBroadcastManager
You need to create the message and broadcast it in from your Main activity:
Intent intent = new Intent("playEvent");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Then, in the game activity, you need to register as receiver:
#Override
public void onCreate(Bundle savedInstanceState) {
// register for the event
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver,
new IntentFilter("playEvent"));
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
game();
}
};
#Override
protected void onDestroy() {
// Unregister here
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(mReceiver);
super.onDestroy();
}
I slightly modifying the code from How to use LocalBroadcastManager? for your case.
Using a static method in Game activity
This is the simplest way but highly discouraged. Because we can't ensure the state of the activity. Do not use this in production code. This is for learning sake only.
You can make the game() method as a static method like this:
public class GameActivity extends Activity {
...
public static void game() {
// game logic.
}
}
Then call the method when you want with:
GameActivity.game();
Related
I am making an app where bgm start from main page. But I couldn't find a way to turn it off when starts learning.
Can I remotely switch off bgm from different java file
This is my 1st java,mainmenu.class
public class mainmenu extends AppCompatActivity {
MediaPlayer bkgrdmsc;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainmenu);
Button btn = (Button) findViewById(R.id.mula);
assert btn != null;
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent ke_belajar_latihan = new Intent(getApplicationContext(), taqi.mengaji.belajar_latihan.class);
startActivity(ke_belajar_latihan);
}
});
bkgrdmsc = MediaPlayer.create(this, R.raw.song);
bkgrdmsc.setLooping(true);
bkgrdmsc.start();
}
}
This is the other file I want to remotely off the bgm when starting the learning session(as student start to learn)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.belajar_hija_baris);
Button btn=(Button) findViewById(R.id.hijaiyyah);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent ke_hijaiyah=new Intent(getApplicationContext(),taqi.mengaji.hijaiyyah.class);
startActivity(ke_hijaiyah);
}
});
}
I want R.id.hijaiyyah to navigate to learn xml also stop bgm
Please help I'm a newbie XD
Make an singleton class and add you music playing code into it for stopping and starting and use that singleton class in all your 2 activities for eg:
public class MusicManager {
private static MusicManager refrence = null;
public static MusicManager getInstance(){
if(refrence == null){
refrence = new MusicManager ();
}
return refrence;
}
}
Add a public method to this singleton class to start and stop music
public void initalizeMediaPlayer(Context context, int musicId){
// add initalization of media player in it and loop it
MediaPlayer bkgrdmsc;
bkgrdmsc = MediaPlayer.create(this, R.raw.song);
bkgrdmsc.setLooping(true);
}
public void startPlaying(){
bkgrdmsc.start();
}
public void stopPlaying(){
bkgrdmsc.stop();
}
//Add stuff like pausing and resuming if you desire
To use this class add this to any activity you want to play music:
MusicManager.getInstance().initalizeMediaPlayer(this, R.raw.menu); // to initalize of media player
MusicManager.getInstance().startPlaying();// to start playing music
MusicManager.getInstance().stopPlaying(); // to stop playing music
You can also use service to perform this task as service runs in background. You can start and stop service any time in your code.
Is there a way to make an alert only appear when the app is opened? I'm creating an alert in onStart() in my MainActivity and whenever I go back to that activity in the app, it shows the alert again which can be annoying to the user. Or is there a way to create a "got it" button and then turn off the alert? Here is my code:
protected void onStart() {
super.onStart();
new AlertDialog.Builder(this)
.setTitle("Instructions")
.setMessage("Hello! To begin, select a map from the list to train with. Make sure" +
" you are on the correct floor.")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.setIcon(R.drawable.ic_launcher)
.show();
}
This is because when another activity comes to foreground upon your MainActivity makes your activity goes to OnPause().
Then when you go back to your MainActivity. The system calls
onStart() again. See The activity life cycle
-First Solution
public class TestActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
showAlertDialog();
}
}
private void showAlertDialog() {
// code to show alert dialog.
}
}
-Second Solution
public class TestActivity extends ActionBarActivity {
private static boolean isAlertDialogShownBefore = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isAlertDialogShownBefore) {
showAlertDialog();
isAlertDialogShownBefore = true;
}
}
private void showAlertDialog() {
// code to show alert dialog.
}
#Override
public void onBackPressed() {
isAlertDialogShownBefore = false;
super.onBackPressed();
}
}
Put that code in onCreate method of your activity. Check for saveInstanceState for null, if it is then show your alertDialog
I have problem with one of my games. This is time based puzzle game and I have problem with it. When user press on/off button on Android device game doesn`t stop, but timer goes on and on till game over. When user turn on screen again, he can see game over screen. But I want to make scenario when user press on/off button game will pause.
Any suggestions? I`m pretty new in programming so please explain me very basic method to do this.
Thanks all!
Edit. Timer code
private void initializeProgressBar() {
//initialize progressbar
progress = ApplicationConstants.GAME_TIME;
mProgress = (ProgressBarDetermininate) findViewById(R.id.progressDeterminate);
mProgress.setMax(progress);
mProgress.setProgress(progress );
timer = new Timer();
progressBarUpdateTask = new ProgressBarUpdateTask();
timer.schedule(progressBarUpdateTask, 20, 20);
}
class ProgressBarUpdateTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable(){
#Override
public void run() {
progress-=1;
if(progress==0)
{
TimeOver();
}
mProgress.setProgress(progress);
}
});
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
this.timer.cancel();
}
Pause your game in onStop() or onPause() (depending on your need) in the Activity context your game is running in.
I am assuming you are using android's activity...
#Override
protected void onResume() {
super.onResume();
// Resume the timer or show a button for the user to press when ready
// !!! Also check if timer exits because onResume is called before onCreate!!!
}
#Override
protected void onPause() {
super.onPause();
// Pause the timer
}
When you press screen off or Power button onPause method of the application will be called and when you again press Power button, applications onResume method will be called, you should pause timer in onPause and resume it in onResume.
One way to do this is to detect the user presence, here's an example
At beginning of your game start the LockService
startService(new Intent(getApplicationContext(), LockService.class));
LockService.java
public class LockService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
final BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
public class LocalBinder extends Binder {
LockService getService() {
return LockService.this;
}
}
}
Then finally the BroadcastReceiver where you can stop your game.
ScreenReceiver.java
public class ScreenReceiver extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(final Context context, final Intent intent) {
Log.e("LOB","onReceive");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// do whatever you need to do here
wasScreenOn = false;
/* PAUSE THE GAME HERE*/
Log.e("LOB","wasScreenOn"+wasScreenOn);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// and do whatever you need to do here
wasScreenOn = true;
}else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
}
}
}
As correctly mentioned in other answers, you can also use the onPause() method
#Override
protected void onPause() {
super.onPause();
// stop the game
}
I'm working on my first app for android - snake. Right now I'm trying to implement 'game over' for that app. So basically when the snake hits the wall, app should ask your name and put it witch your score on HiScore. Well i'm stuk on hitting the wall fragment. Im experimenting with threads and so far I've found no way to stop it without getting errors.
I googled a lot, and everyone is saying that thread.join(); is waiting for thread to end, so how long does it take to end the thread that is drawing simple squares once per half second? When im hitting the back button on my phone while playing, pause(); function works perfectly. Log "game has ended" appears on LogCat.
So the problem is that i cant stop this activity when snake hits the wall, Log "game has ended" never occurs. Why is that?
My code:
public class SnakeCage extends SurfaceView implements Runnable{
// blah blah .. functions that draw and stuff ..
public void pause() {
isRunning = false;
while(true){
try {
aThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
aThread = null;
Log.d("pause()","game has ended"); // <<<<<<<<<THIS ONE>>>>>>>>>
}
public void resume() {
isRunning = true;
aThread = new Thread(this);
aThread.start();
}
public void init(){
// blah blah...
}
private void gameOver() {
int pHeadX = snakeHead.posX;
int pHeadY = snakeHead.posY;
Log.d("gameOver()", "checking");
if(pHeadY<0 || pHeadX<0 || pHeadX>23 || pHeadY>19){
Log.d("gameOver()", "game now will end");
gameOver = true;
}
}
public void run() {
while (isRunning){
if(!aHolder.getSurface().isValid())
continue;
canvas = aHolder.lockCanvas();
// drawing
gameOver();
if(gameOver) break;
// more drawing
aHolder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(gameOver){
pause();
}
}
and the activity class:
public class PlayingActivity extends Activity implements OnClickListener{
SnakeCage v;
Button snakeGoUp;
Button snakeGoDown;
Button snakeGoLeft;
Button snakeGoRight;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_layout);
v = (SnakeCage)findViewById(R.id.sView);
// listeners and stuff
}
#Override
protected void onPause() {
super.onPause();
v.pause();
}
#Override
protected void onResume() {
super.onResume();
v.resume();
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.snakeUp:
v.move(1);
break;
case R.id.snakeDown:
v.move(2);
break;
case R.id.snakeLeft:
v.move(3);
break;
case R.id.snakeRight:
v.move(4);
break;
}
}
}
i just did:
Context context = getContext();
((PlayingActivity)context).finish();
from:
How can I end an activity from inside a SurfaceView class or nested thread
although it does not satisfy me... its enough for now
I would suggest using a LocalBroadcastManager to send a message to the Activity, to notify it to kill itself. You can have an inner class in the Activity to receive the broadcast and call a private method in the Activity which will end it.
public class MyActivity extends Activity {
public void onCreate(Bundle state) {
LocalBroadcastManager.getInstance(this).registerReceiver(new MessageHandler(),
new IntentFilter("kill"));
}
private void killActivity() {
finish();
}
public class MessageHandler extends BroadcastReceiver {
onReceive(Context context, Intent intent) {
killActivity();
}
}
Then in your SurfaceView all you need to do is:
Intent intent = new Intent("kill");
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
Its a little more code but its a lot cleaner IMHO.
I have three images with me and i want them to appear on first layout xml like a splash view so that they can be viewed only once i.e that activity will be called only once when app get's installed or if app get's a new update otherwise app should always start from the Second activity, i don't know how should i begin with this :
Can any one tell me any idea how this can be done.
To show splash for only once.
Next part of this question is here
Coding will be much appreciated.
Save a flag in the Preferences when you start up the application, after you've done the welcome screen stuff. Check for this flag before you show the welcome screen. If the flag is present (in other words, if it's not the first time), don't show it.
In your activity:
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
// the code below will display a popup
String whatsNewTitle = getResources().getString(R.string.whatsNewTitle);
String whatsNewText = getResources().getString(R.string.whatsNewText);
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(whatsNewTitle).setMessage(whatsNewText).setPositiveButton(
R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
Try this :
public class MainActivity extends Activity {
private Thread mSplashThread;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
final MainActivity sPlashScreen = this;
mSplashThread = new Thread() {
#Override
public void run() {
try {
synchronized (this) {
wait(4000);
}
} catch (InterruptedException ex) {
}
finish();
Intent intent = new Intent();
intent.setClass(sPlashScreen, StartNewActivity.class);// <-- Activity you want to start after Splash
startActivity(intent);
}
};
mSplashThread.start();
} catch (Exception e) {
}
}
#Override
public boolean onTouchEvent(MotionEvent evt) {
try {
if (evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized (mSplashThread) {
mSplashThread.notifyAll();
}
}
} catch (Exception e) {
}
return true;
}
}
you put an Image in splash.xml to show
to do this you have to detect the first launch of your application. To do so you can store a boolean value as #Nirav suggested.
And for the splash screen, You can consider using Fragments and ViewPager to create an activity which will only be shown for the first time