I've been trying to get the Robotium tester to work for the Android project in libGDX, but got some problems.
First I want to test my games buttons (that are imageButtons), but for that I need the imageButton index in Android.
How can I get that?
My button is in the main project:
ImageButtonStyle style = new ImageButtonStyle();
style.imageUp = buttonsImagesUp;
style.imageDown = buttonsImagesDown;
ImageButton newgameButton = new ImageButton(style);
newgameButton.setPosition(425,330);
This is the button I would like to test in JUnit.
My JUnit code:
public class ButtonTest extends ActivityInstrumentationTestCase2<MainActivity> {
private Solo solo;
#SuppressWarnings("deprecation")
public ButtonTest() {
super("com.me.myGame", MainActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
public void testMenu(){
solo.assertCurrentActivity("First menu selected", MainActivity.class);
solo.clickOnImageButton(index); //need index
}
}
My game is set up like this:
First there is the main Game class that handles the resources and sets the first screen to the main Menu:
#Override
public void create() {
playSound = userPref.getBoolean("playSounds");
setScreen(mainMenuScreen);
}
And after this it goes to the MainMenuScreen.js and thats were the buttons are that I want to test with JUnit
Robotium's idea of an ImageButton is very, very different from Libgdx. Robotium is expecting an image button that is defined as part of the standard Android UI infrastructure (see Android ImageButton). The Libgdx ImageButton is a Java object with an OpenGL texture reference (see Libgdx ImageButton). From the Android UI infrastructure point of view, a Libgdx app is just a full-screen OpenGL view, and has very little meta-data for Robotium to use.
You may be able to use the raw "clickOnScreen" infrastructure, but you will have to manually compute and track the location of your buttons on the screen. Additionally, I would be surprised if Robotium did not contain other dependencies on the Android UI infrastructure that are not there in a Libgdx app.
Related
So I am making a scrolling platformer game, and I want the player to jump when the screen is tapped. However, I have tried many many answers on Stack overflow such as android:onClick,
ImageButton imgButton;
imgButton = (ImageButton)findViewById(R.id.imageButton);
imgButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Gameview", "clicked");
}
});
and I suspect it does not work due to some sort of interaction between the gameView hiding the base screen and being displayed over it. How can I detect taps in my gameView or in general for game purposes?
Any help is much appreciated :D pulling my hair out over this
I would create an app for get the double tap also if the app is in background.
I create this code:
public class MainActivity extends Activity implements
GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener
{
private static final String DEBUG_TAG = "Gestures";
private GestureDetectorCompat mDetector;
private int counter = 0;
// Called when the activity is first created.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetector = new GestureDetectorCompat(this,this);
mDetector.setOnDoubleTapListener(this);
}
#Override
public boolean onDoubleTap(MotionEvent event)
{
counter++;
Log.d(DEBUG_TAG, String.valueOf(counter));
return true;
}
//..........................
}
if the app is open in the log i see the number of count of double tap increase, if the app work in background the number is blocked.
There is a way for fix it? or i have to create a services? i need a grafic app and service, there is a way for create just one with both things?
Thanks
There isn't an easy answer to this. Normally it is NOT possibile because an App cannot interact with other pieces of Android interface that is OUTSIDE the App itselfs. But if the device has Root Permissions it's possibile to directly read the Touchscreen and intercept all touch events.
An alternative method that not requires Root exists but I discurage to use it: place a fullscreen View that acts as a transparent layer and that intercepts all the events. However this method has few disadvantages: slows down graphic performance of WHOLE device (expecially while running games), could interfere with user experience while touching interactive areas (buttons, checkboxes, etc...) and however could not work well by loosing some touching events.
I am creating a basic camera app as a small project I'm doing to get started with Android development.
When I click on the button to take a picture, there is about a 1-second delay in which the preview freezes before unfreezing again. There is no issue with crashing - just the freezing issue. Why is this happening and how can I fix it?
Below is the method where the camera is instantiated, as well as my SurfaceView class.
private void startCamera() {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
cameraPreviewLayout = (FrameLayout) findViewById(R.id.camera_preview);
camera = checkDeviceCamera();
camera.setDisplayOrientation(90);
mImageSurfaceView = new ImageSurfaceView(MainActivity.this, camera);
cameraPreviewLayout.addView(mImageSurfaceView);
ImageButton captureButton = (ImageButton)findViewById(R.id.imageButton);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
camera.takePicture(null, null, pictureCallback);
camera.stopPreview();
camera.startPreview();
}
});
}
public class ImageSurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
private Camera camera;
private SurfaceHolder surfaceHolder;
public ImageSurfaceView(Context context, Camera camera) {
super(context);
this.camera = camera;
this.surfaceHolder = getHolder();
this.surfaceHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
this.camera.setPreviewDisplay(holder);
this.camera.startPreview();
this.camera.setDisplayOrientation(90);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
EDIT: There is currently nothing in the pictureCallback.
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
}
You don't need to call stopPreview() after takePicture(). And you don't need startPreview() on the next line. You do need startPreview() inside your onPictureTaken() callback (not in onClick() as in the posted code!!) if you want live preview to restart after the picture is captured into a Jpeg stream.
To keep your UI responsive while using camera, you should do all work with the camera on a background thread. But it is not enough to call Camera.open() or Camera.close() on some background thread. You must create a Handler thread and use it for Camera.open(). The same Looper will be used for all camera callbacks, including PictureCallback.onPictureTaken(). See my detailed walkthrough about the use of HandlerThread.
As I explained elsewhere, you can achieve even better performance if you use the new camera2 API on devices that fully support this API (but better use the old API with devices that provide only LEGACY level of camera2 support).
But if you want to get maximum from the camera ISP, this kind of freeze may be inevitable (this depends on many hardware and firmware design choices, made by the manufacturer). Some clever UI tweaks may help to conceal this effect.
You’ll need to enable access to the hidden “Developer options” menu on
your Android phone. To do that, simply tap the “About phone” option in
Settings. Then tap “Build number” seven times and you’re done. Now you
can just back out to the main Settings menu and you’ll find Developer
options somewhere near the bottom of the list.
==>Now that you’re done with that part, let the real fun begins. Tap the new Developer options menu you just enabled and scroll until you
see the following three settings (note that they may be located within
an “Advanced” subsection):
Window animation scale Transition animation scale Animator animation
scale
==>Did you see them? By default, each of those three options is set to “1x” but tapping them and changing them to “.5x” will dramatically
speed up your phone. This harmless tweak forces the device to speed up
all transition animations, and the entire user experience is faster
and smoother as a result
i'm new of libgdx and this is my first app, but i have the problem with screen switch.
i have set main class like this:
public class MyClass extends Game {
MenuClass menuClass;
ActionGame actionGame;
#Override
public void create() {
menuClass = new MenuClass(this);
actionGame = new ActionGame(this);
setScreen(actionGame);
}
}
and method of ActionGame class like this:
....
#Override
public void pause() {
game.setScreen(game.menuClass);
}
#Override
public void resume() {
this.show();
this.render(Gdx.graphics.getDeltaTime());
}
....
and method of menuClass.java like this, when touch Play button:
....
#Override
public void resume() {
game.actionGame.resume();
}
....
When i touch play button i wish that actionGame class return in action render, but the render don't start.
I have try with setScreen, but this restart my screen, this not good.
Help
Thanks
You're using resume incorrectly. It is something that is always called when your app is brought back to screen. You should never call resume() on any of your classes yourself. It is called by Libgdx when your app is brought back to the foreground.
It is correct that you should switch to the menu screen in the pause method, because gamers expect the game to automatically go to a menu or pause screen when the app goes off screen. But you do not want to be automatically switching back to the game when the app comes back on screen.
The resume method would only be used for reloading stuff that you unloaded in pause (which you probably don't need to do), or to restart music, or something like that.
Your Play button definitely should not be calling resume. It should be calling setScreen(actionGame);. And there should be nothing in any of your resume methods as you have currently designed it.
I have multiple classes that implement Screen.
I want to, say, have the Main Menu screen portrait, then the Play Screen landscape. Is there anyway of changing the orientation dynamically?
I thought I could just start another Activity and have the Play Screen extend Game. And the new Activity would intialize the Play Screen. But it appears that you can't call startActivity or the like, obviously, as LibGDX is platform independent.
I use Gdx.graphics.getWidth() and Gdx.graphics.getHeight() to align Sprites and Actors, so it looks "right" on different devices.
I've also tried swapping the Gdx.graphics.getWidth() and Gdx.graphics.getHeight(), respectively, but can't seem to get the position of sprites and actors correct.
Also, in my manifest I have orientation="landscape".
Here are some images that should make more sense.
So this is my Main Menu in landscape:
And this is my Main Menu in portrait:
The position and size of Actors and Sprites are all based on Gdx.graphics.getWidth() and Gdx.graphics.getHeight(). The only thing that changes between the two images is orientation="landscape" and orientation="portrait" in my manifest.
Now I want my Main Menu in portrait but the Play Screen, where the game is on, should be in landscape.
I initially started working on the Play Screen and the sizes and positions where set based on orientation="landscape", and now that I am working on the Main Menu it is based on orientation="portrait". Hence why I want to change the orientation dynamically.
This is a good question :) I develop noone's answer (which is correct)
How to set lanscape screen with Android sdk specific classes ?
And how to import android classes in a libgdx project ?
First of all note that Android classes can only be imported in the android project and not in the core. So there we save the Activity in a platform dependant object. Here is my AndroidLauncher:
import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.mygdx.game.MyGdxGame;
import com.mygdx.game.util.Platform;
public class AndroidLauncher extends AndroidApplication {
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
PlatformAndroid platform = new PlatformAndroid();
platform.setActivity(this);
initialize(new MyGdxGame((Platform) platform ), cfg);
}
}
PlatformAndroid implements Platform. These two classes are made to access platform specific objects. Let's look at them :
public interface Platform {
public void SetOrientation(String string);
}
and
package com.mygdx.game.android;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.mygdx.game.util.Platform;
public class PlatformAndroid extends AndroidApplication implements Platform {
private Activity activity;
#Override
public void SetOrientation(String string) {
if (string == "landscape"){
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
public void setActivity(Activity activity){ this.activity = activity; }
}
You can also create a PLatformDesktop called by the desktop launcher. Anyway, keep the platform variable in your classes and when you want to set the screen to landscape just call:
platform.SetOrientation("landscape");
You should not have multiple Activities. To learn how to switch the orientation programmatically you can have a look at this link.
As you said, LibGDX is platform-independent. That's why you cannot access your Android-Activity from your "core" code. To learn how to workaround that, have a look at Interfacing with platform specific code.
When you call your interface to change the orientation from your game when doing a Screen transition, LibGDX will automatically call resize(width, height) with the new values and you can align your Stage and so on according to the new values.
I had the same problem and this solved it:
#Override
public void resize(int width, int height) {
stage.getViewport().setScreenSize(width, height);
}
For some reason, even though the screen resolution changed, the stage didn't know that. So I've told it to the stage.
Just create a interface in core project and and declare a method with any name than implement that interface in your AndroidLauncher class. Give definition of your method.
For me GameOrien.java is interface having method declaration
public interface GameOrien {
public static final int PORTRAIT=1;
public static final int LANDSCAPE=2;
void setOrientation(int orientation);
}
In AndroidLauncher.java class which is in Android project.
public class AndroidLauncher extends AndroidApplication implements GameOrien {
**...**
#Override
public void setOrientation(int orientation) {
if(orientation==PORTRAIT)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
else if(orientation==LANDSCAPE)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
When you want to change orientation for GamePlay just call setOrientaion() method of interface. Your orientation changed.