I am looking to make a game and I need to involve native android sdk features such as toast, dialog, in app billing, other google Api, gcm ..etc
I am pretty experienced with android sdk when I built tools apps and I used animations and very briefly surface view.
However I have looked into libdgx and looks promising but the only downside I find is the "not so easy integration with Android native sdk". Ie, I can't just start my own activity or call native api unless I am missing it
So I was wondering, should I go with libgdx in this case or should I go with the native route?
Thank you
If you're sure you're not going to target other platforms, you can just move your code from the default core project into your Android project and work from there, calling any API as you please. But you would lose the ability to test on desktop.
To maintain portability to other platforms and ability to test on desktop, you can create an interface listing all the Android API methods you would like to call. Pass an instance of this interface into your game's constructor in your Android project, so your game can indirectly call them. Your desktop project can pass in an instance of this interface with empty or system logging methods.
Example:
public class MyGdxGame extends ApplicationAdapter {
public interface AndroidAPIAdapter {
public void makeToast(String msg);
public void startActivity(int activityNumber);
}
AndroidAPIAdapter androidAPIAdapter;
public MyGdxGame (AndroidAPIAdapter androidAPIAdapter){
this.androidAPIAdapter = androidAPIAdapter;
}
//Call this from game code in core project as needed
public void makeToast(String msg){
if (androidAPIAdapter!=null)
androidAPIAdapter.makeToast(msg);
}
//Call thisfrom game code in core project as needed
public void startActivity(int activityNumber){
if (androidAPIAdapter!=null)
androidAPIAdapter.startActivity(activityNumber);
}
//...
}
with:
public class MyGameActivity extends AndroidApplication implements AndroidAPIAdapter {
public static final int ACTIVITY_SETTINGS = 0;
public static final int ACTIVITY_ABOUT = 1;
//etc.
public void onCreate (Bundle bundle) {
super.onCreate(bundle);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useImmersiveMode = true;
initialize(new MyGdxGame(this), config);
}
#Override
public void makeToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT);
}
#Override
public void startActivity(int activityNumber) {
switch (activityNumber){
case ACTIVITY_SETTINGS:
startActivity(this, MySettingsActivity.class);
break;
case ACTIVITY_ABOUT:
startActivity(this, MyAboutActivity.class);
break;
}
}
}
Related
I am not sure of the terminology for what I'm looking to do, so sorry in advance!
I've found a FilePicker plugin for Xamarin.Forms (https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows) that implements device-specific functionality for selecting files via the CrossFilePicker class.
The way to use leverage this functionality would be something like
CrossFilePicker.Current.OpenFile("Filename.txt");
The most important part of this for me is that CrossFilePicker.Current is static and can be accessible from anywhere in the shared layer of my Xamarin.Forms app.
I need to implement a class with the same characteristics. I want to leverage device Accessibility functionality (i.e. determining if a screen reader is enabled) and I need to be able to do so with a static class.
My eventual plan is to then wrap this static class so that I can use it for unit tests too.
I don't want to import device libraries into my shared project.
TLDR: I need a static class that implements device-specific functionality.
Any help would be greatly appreciated! Thank you :)
EDIT:
Here are the files I have currently implemented in my project
IAccessibilityService Located in the shared .NET project
namespace Bitspace.Services
{
public interface IAccessibilityService
{
public bool IsScreenReaderEnabled();
public void Announcement(string message);
public void NavigationAnnouncement(string message);
}
}
DeviceAccessibility.cs Located in the shared .NET project
using System;
namespace Bitspace.Services
{
public class DeviceAccessibility
{
private static Lazy<IAccessibilityService> Implementation = new Lazy<IAccessibilityService>(() => CreateAccessibilityService(), System.Threading.LazyThreadSafetyMode.PublicationOnly);
public static IAccessibilityService Current
{
get
{
var curr = Implementation.Value;
if (curr == null)
{
throw new Exception();
}
return curr;
}
}
private static IAccessibilityService CreateAccessibilityService()
{
return new DeviceAccessibilityImplementation();
}
}
}
DeviceAccessibilityImplementation.cs Located in the Android project
using Android.Runtime;
namespace Bitspace.Services
{
[Preserve (AllMembers = true)]
public class DeviceAccessibilityImplementation : IAccessibilityService
{
public bool IsScreenReaderEnabled()
{
return true;
}
public void Announcement(string message)
{
}
public void NavigationAnnouncement(string message)
{
}
}
}
If I try to build the project, I get an error on the return new DeviceAccessibilityImplementation(); line in DeviceAccessibility.cs that says DeviceAccessibility.cs(25, 24): [CS0246] The type or namespace name 'DeviceAccessibilityImplementation' could not be found (are you missing a using directive or an assembly reference?)
However, CTRL Clicking on that line takes me to the DeviceAccessibilityImplementation.cs
I need to get the Context of my app but in my main Class extends from Game so I can not extends from Activity. Does anybody know how to do it?
Thank you!
LibGDX is a cross-platform game engine, so your application can be executed on multiple platforms. Only Android, which is just one supported platform, can provide a Context object.
To get around this issue, you'll need to create an Interface in the core module of your LibGDX project. That Interface can, for example, contain a getContext() method. Add the interface as an argument in the constructor of your main LibGDX class. In every platform-specific module, you should then implement this Interface , override the getContext() method (by returning a Context object in the android module and null in every other module) and pass it with the constructor for the main LibGDX class in the Launcher class for that module.
For more information about the topic, read the LibGDX Wiki: https://github.com/libgdx/libgdx/wiki/Interfacing-with-platform-specific-code
EDIT:
LibGDX isn't able to handle the Context object, you'll need to manipulate the Context object in the Android module, instead of passing it to the core module! Thanks to #Nicolas and #Luis Fernando Frontanilla for mentioning this.
Interfacing is the way to go since you can't access Android specific code from Core module.
Step 1: Create the interface (CORE MODULE)
public interface MyInterface {
void manipulateContext();
void manipulateContextWithExtraParams(String example, int example2);
}
Step 2: Implement the interface (ANDROID MODULE)
import android.content.Context;
public class InterfaceImplementation implements MyInterface {
private Context context;
public InterfaceImplementation(Context context) {
// Store the context for later use
this.context = context;
}
#Override
public void manipulateContext() {
// Do something with the context, this is called on the core module
System.out.println(context);
}
#Override
public void manipulateContextWithExtraParams(String example, int example2) {
if (example2 == 1) {
System.out.println(example + context);
} else {
System.out.println(example);
}
}
}
Step 3: Send the implemented interface your game (ANDROID MODULE)
import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.frontanilla.helping.getcontext.InterfaceImplementation;
import com.frontanilla.helping.getcontext.MyGame;
public class AndroidLauncher extends AndroidApplication {
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
InterfaceImplementation interfaceImplementation = new InterfaceImplementation(this);
// Here we send the implementation to our Game in Core module
initialize(new MyGame(interfaceImplementation), config);
}
}
Step 4: Store and use the methods you defined on your interface (CORE MODULE)
import com.badlogic.gdx.Game;
public class MyGame extends Game {
private MyInterface myInterface;
public MyGame(MyInterface myInterface) {
// Store for later use
this.myInterface = myInterface;
}
#Override
public void create() {
// Example of manipulating the Android Context indirectly from Core module
myInterface.manipulateContext();
myInterface.manipulateContextWithExtraParams("Hello", 2);
}
}
As you can see, you will not be manipulating the Context from the core module directly, instead, place that logic on the InterfaceImplementation class
What I have tried is:
scoreHelper = new ScoreSQLiteHelper(context,"dbtest",null,1);
db = scoreHelper.getWritableDatabase();
but I don't have any context to feed that method.
It would be usefull any other way to get a path to create the db with:
db = SQLiteDatabase.openOrCreateDatabase(path,null);
I can use android methods from GDX (Platform specific code), but is it possible to get libgdx method from android back-end?
I have firebase database. On android side of my game I catch any changes in database. And I need to transfer that changes to my core back-end (For example update some actors, labels, and so on). What's the best way to do that?
Accessing Platform Specific API inside core module can be possible using Interfacing.
core-module is common part of all platform so you can access anywhere in your project.
Keep reference of ApplicationListener, If you want to call any method/access data member of your core module.
Inside android module :
public class AndroidLauncher extends AndroidApplication {
MyGdxGame gdxGame;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
gdxGame=new MyGdxGame();
initialize(gdxGame, config);
}
public void andoridMethod(){
System.out.println(gdxGame.x); //access data member
gdxGame.doSomething(); //access method
}
}
Inside core module :
public class MyGdxGame implements ApplicationListener {
public int x=4;
public void doSomething(){}
// Life cycle methods of ApplicationListener
}
Good news this is possible and simple, just import whatever you need, for example the Color class from LibGDX
import com.badlogic.gdx.graphics.Color;
public class AndroidLauncher extends AndroidApplication {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
Color color = new Color();
initialize(new Game(), config);
}
Hope this is what you needed
If you simply call core functions from your Android code, as suggested by Aryan, the code will be executed on a different thread, which may cause issues unless you have designed your code to be thread safe.
If you want to make sure it is executed on the Gdx render thread, you should keep a reference to your game in the Android code then use
Gdx.app.postRunnable(new Runnable(){
#Override
public void run(){
gdxGame.doSomething();
}
})
The runnable should then be executed at the start of the render loop (before input processing).
I added admob to my libgdx project without any problem but How can I disable admob in game. I have 2 screen(MainMenu and PlayScreen) and I want to ads to be shown only at MainMenu.
I have found an article about conntrolling ads in libgdx but the problem is this article is for Desktop not Android.
https://code.google.com/p/libgdx/wiki/AdMobInLibgdx (Note: question arises in part from using deprecated document, newer version available at https://github.com/libgdx/libgdx/wiki/Admob-in-libgdx)
Take a look at the #control at the new wiki. There are 2 Final static values inside of your Android Project:
public class HelloWorldAndroid extends AndroidApplication {
private final int SHOW_ADS = 1;
private final int HIDE_ADS = 0;
protected Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg) {
switch(msg.what) {
case SHOW_ADS:
{
adView.setVisibility(View.VISIBLE); //change to visible
break;
}
case HIDE_ADS:
{
adView.setVisibility(View.GONE);//change to not visible
// you should also disable the ad fetching here!
break;
}
}
}
};
So if you call the method: (which is parsed as interface to the core project)
public interface IActivityRequestHandler {
public void showAds(boolean show);
}
public class HelloWorldAndroid extends AndroidApplication implements IActivityRequestHandler {
...
// This is the callback that posts a message for the handler
#Override
public void showAds(boolean show) {
handler.sendEmptyMessage(show ? SHOW_ADS : HIDE_ADS);
}
it sends an message to the handler which activates or disable the admob. The interface for showAds is passed to the core project so you can hold an reference to it and use it. To see how this works take a look at the article of interfacing plattformspec code.
Just to show this here:
View gameView = initializeForView(new HelloWorld(this), false); // and "this" is the mainclass of the android project which implements the IActivityRequestHandler interface shown above
//the HelloWorld(this) is the core project where you now can save the `IActivityRequestHandler` as referance and call the showAds(bool)
But in the end if you would have read the aticle you should have know this all.
I need to determine in runtime from code if the application is run under TestInstrumentation.
I could initialize the test environment with some env/system variable, but Eclipse ADK launch configuration would not allow me to do that.
Default Android system properties and environment do not to have any data about it. Moreover, they are identically same, whether the application is started regularly or under test.
This one could be a solution: Is it possible to find out if an Android application runs as part of an instrumentation test but since I do not test activities, all proposed methods there won't work. The ActivityManager.isRunningInTestHarness() method uses this under the hood:
SystemProperties.getBoolean("ro.test_harness")
which always returns false in my case. (To work with the hidden android.os.SystemProperties class I use reflection).
What else can I do to try to determine from inside the application if it's under test?
I have found one hacky solution: out of the application one can try to load a class from the testing package. The appication classloader surprisingly can load classes by name from the testing project if it was run under test. In other case the class is not found.
private static boolean isTestMode() {
boolean result;
try {
application.getClassLoader().loadClass("foo.bar.test.SomeTest");
// alternatively (see the comment below):
// Class.forName("foo.bar.test.SomeTest");
result = true;
} catch (final Exception e) {
result = false;
}
return result;
}
I admit this is not elegant but it works. Will be grateful for the proper solution.
The isTestMode() solution did not work for me on Android Studio 1.2.1.1. Almighty Krzysztof from our company tweaked your method by using:
Class.forName("foo.bar.test.SomeTest");
instead of getClassLoader(). Thanks for Krzysztof!
We created a solution to pass parameters to the MainActivity and use it inside the onCreate method, enabling you to define how the Activity will be created.
In MainActivity class, we created some constants, which could also be an enum. We created a static attribute too.
public class MainActivity {
public static final int APPLICATION_MODE = 5;
public static final int UNIT_TEST_MODE = 10;
public static final int OTHER_MODE = 15;
public static int activityMode = APPLICATION_MODE;
(...)
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
switch (activityMode) {
case OTHER_MODE:
(...)
break;
case UNIT_TEST_MODE:
Log.d(TAG, "Is in Test Mode!");
break;
case APPLICATION_MODE:
(...)
break;
}
(...)
}
(...)
}
We made MainActivityTest class abstract, created a setApplicationMode and called this method inside the setUp() method, before calling the super.setUp() method.
public abstract class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
protected void setUp() throws Exception {
setApplicationMode(); // <=====
super.setUp();
getActivity();
(...)
}
(...)
public void setApplicationMode() {
MainActivity.activityMode = MainActivity.UNIT_TEST_MODE;
}
}
All other test classes inherit from MainActivityTest, if we want it to have another behaviour, we can simply override the setApplicationMode method.
public class OtherMainActivityTest extends MainActivityTest {
(...)
#Override
public void setApplicationMode() {
MainActivity.activityMode = MainActivity.OTHER_MODE;
}
}
The user nathan-almeida is the friend that is co-author of this solution.