Android message between classes - java

This is my first post and I did not find anything similar, so I've decided to ask.
Im developing a Poker Game for Android to practice the SDK and refresh/improve my Java. Its a simple app that control a texas hold'em poker hand.
Initally, I wrote my classes using only Java SE and it looks fine. Each class has its own purpose and testing it with console input/output, I can see it really works :)
Last week, I decided to port it to Android to see things happening through a graphic interface, so I got the resource images, make an Activity and included my poker package.
Before port to Android I can just put a println (or readLine) to see whats going on and send my inputs. Now Im stuck in how each class can communicate to the game activity to provide what must be drawn. If possible, I don't want insert Android draw code inside game classes. Im trying find a way to exchange messages between my Activity and the game classes and Id like some suggetions. Im new in developing Android apps, so I dont know all mechanics to do this.
Below are the snippet from my activity:
package my.poker.game;
//import stuff
public class ActivityHand extends Activity
{
private static Vector<Player> Players = new Vector<Player>();
public static final int MAX_PLAYERS = 8;
public static void startEmptyTable()
{
Players.removeAllElements();
Players.setSize(MAX_PLAYERS);
}
public static void LeaveTable(int pos)
{
Players.set(pos, null);
}
public static void SitTable(int pos, Player player)
{
Players.set(pos, player);
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
int cash = 1000;
startEmptyTable();
SitTable(0, new Jogador("William", cash));
SitTable(2, new Jogador("Richard", cash));
SitTable(4, new Jogador("John", cash));
SitTable(6, new Jogador("Paul", cash));
SitTable(8, new Jogador("Albert", cash));
//Start a Hand.... in future this will be a loop for each Hand
Hand hand = new Hand(Players);
}
}
The object hand, will select a Dealer, deal the cards, control the small and big blinds and start the game loop.
The question is: how the hand class can tell the Activity to Draw and pass an object containing what to draw?
Thanks a lot for your help
Editing: I've decided to try implementing it using a Handler and passing simple messages. As I read from Handler at Developers a Handler object is assigned to thread's MessageQueue, so I tried to put this into my Activity Class (before Hand hand = new Hand (...) ):
Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
Bundle bundle = msg.getData();
// Do something with message contents
}
};
And inside the Hand class I put this when I want to draw something:
Handler handler = new Handler();
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("Key", "The Key's Value");
msg.setData(bundle);
handler.sendMessage(msg);
As I understood, both handlers are from same thread, so they are assigned to same MessageQueue right? I tought when I send a message inside Hand class, the Activity class can receive it in handleMessage method and processes any message I send, but handleMessage doesn't execute.
What am I missing?
Thanks again

To call methods in the activity, you want to pass the activity to this class.
for example:
public class PokerActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
Hand hand = new Hand(this);
}
public void setVisibleHand(Player player)
{
<do something in the activity>
}
}
public class Hand
{
PokerActivity pokerActivity;
public Hand(PokerActivity activity)
{
this.pokerActivity = activity;
}
public void setVisibleHand()
{
pokerActivity.setVisibleHand(player1);
}
}
Now, this might not be the best way to do it. In Android you have to be carefull to not leak the context, or you might be getting trouble with the memory. (simply passing the activity/context might be the easy way, but is also the easiest way to leak the context.)
I'd advise you to look at some simple tutorials first, to get a feeling of how android activities work.

You could use a Handler and Message system to communicate between your classes.
This tutorial by Lars Vogel should help you Android Threads, Handlers and AsyncTask - Tutorial

You will have to create another class to make the interactions with your own classes and the activity itself.
From that class you can use the activity context to control the android activity.
The approach about using Handlers and Messages is good but would require you to modify your game classes.

Maybe you should extend View Class to draw the Hand.
http://developer.android.com/reference/android/view/View.html

Related

Is there an alternative in Android Java for Message sendToTarget to access View in inner class of an activity?

i have an activity where i have a text view. I am also using an sdk which has some events.
Within on of these events i need to display some data at the TextView.
The events are in an external class and i got them via some interfaces.
The interfaces iam implementing within the Activity.
I am using Handler and Message to set the text into the TextView within the implementation of the interface.
I would like to know if there is another way to set the text within the the interfaces except Handler and Message.
Here is that code:
public class MyActivity extends AppCompatActivity {
private TextView nameTextView;
// some code
// implementing interfaces of external class
Service.ServiceEvents events = new Service.ServiceEvents() {
#Override
public void onSomeEvent(String name) {
nameTextView.setText(name); // not working
Message m = myHandler.obtainMessage(0, nameTextView);
m.sendToTarget();
}
Handler myHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message message) {
String s = message.obj.toString();
nameTextView.setText(s);
}
};
}
} // end of activity
Is there another way to set the text in the TextView?
Please Help.
What to use
You can do it by using an interface.
How to implement
Create a new interface and give it a name whatever u like.(Here it is SampleInterface).
Add some void methods to like this
void onSomeEvent(String name);
Create a object of it in the class where you get the data from the sdk and add this listener in its constructor. Something like this
public YourJavaClassName(SampleInterface sampleInterface) {
this.sampleInterface= sampleInterface;
}
When you receive an update in the sdk, you can call it like this
void onDataReceived(String name){// I don't know how you get the value from the sdk so I wrote this
sampleInterface.onSomeEvent(name);
}
You are done with implementing it in the sdk receiver class. Now you need to add to the main activity to receive and update data.
Create the object of the class where you receive the data from the sdk.Like this
MySDKReceiverClass mysdkreceiverclass;
mysdkreceiverclass = new MySDKReceiverClass(this);
Implement the interface in the activity and there you ge the values and you can set it in the textview.
Note: You need not add any runnable or handler or anything.Whenever there is a value change, the listener is called and the value is set.

Android: Updating textviews in multiple activities

I need some pointers on doing the following:
lets say i have 10/20 (number doesn't matter) of activities.
each of these activities has a textview that should work like a counter.
each of these activities has a button to go to the next activity.
this counter starts when the app is launched, and increment itself every second.
So what i did so far is:
have in my main activity a method that instantiate a class that extends Thread.
In that class in the run() method, i increment a variable when a second passes.
Now i'm stuck on what i should do next. Any pointers would be appreciated thanks.
Edit: i need a way to communicate from inside the run method, to whichever activity is now currently on screen, to update its textview.
Just a bit of theory here for standard Object Oriented Programming : stick to the recommended principles like Loose Coupling which makes your project code less tied to each other. You can read more on that later.
Now, using Events, you can setup a system that is synonymous with the natural Publisher/Subscriber design pattern. Like this:
The activity that needs to notify the other activities is called Publisher and the other activities that need to be notified are called Subscribers.
From here:
There are already built and tested libraries to do Events in android. Like my favorite EventBus.
Step 1 Add this line to your app-level build.gradle file:
compile 'org.greenrobot:eventbus:3.0.0'
Then create a simple Plain Old Java Object aka POJO class like this:
public class UpdateTextViewEvent{
private String textToShow;
public UpdateTextViewEvent(String text){
this.textToShow = text;
}
//add your public getters and setters here
}
Step 2 Notify others:
When you want to notify anyone of the changes, you simply called this method:
EventBus.getDefault().post(new UpdateTextViewEvent("Some new Text"));
Step 3 Receive notifications
For those who want to be notified of this event, simply do this:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
NOTE: to actually handle the event:
#Subscribe
public void onEvent(UpdateTextViewEvent event){
String text = event.getTextToShow();
//now you can show by setting accordingly on the TextView;
}
This is so much easier to do, do decouple your code by eliminating static references in your different activities
I hope this helps! Good luck!
make that Textview in second class as
public static Textview text;
and call it in main activity as
SecondActivity obj=new SecondActivity();
obj.text.settext("");
You can create one another activity e.g. BaseActivity extend with Activity class and your all 10/20 activity extends with created BaseActivity Class.
You can use your textview with protected access specifiers.
What you need to do is inside the counter class, create an a method and passed in a TextView as the parameter. Then create an int variable and set the counter as the instance:
Like this
public static class Counter extends Thread{
private static int x;
#Override
public void run(){
x = counter;
}
public void setCounter(TextView tv){
tv.setText(String.valueOf(x));
}
}
Now call this method setCounter(TextView) in all the activity's onCreate() method you'll like to display the counter, and passed in your the layout TextView as the argument. Like this
...
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState):
....
TextView cTextView = (TextView)findViewById(R.id.texT1);
Counter c = new Counter();
c.setCounter(cTextView);
}

Google Api Client interface methods explanation?

#Override
public void getLeaderboardGPGS() {
if (gameHelper.isSignedIn()) {
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(gameHelper.getApiClient(), getString(R.string.event_score)), 100);
}
else if (!gameHelper.isConnecting()) {
loginGPGS();
}
}
#Override
public void getAchievementsGPGS() {
if (gameHelper.isSignedIn()) {
startActivityForResult(Games.Achievements.getAchievementsIntent(gameHelper.getApiClient()), 101);
}
else if (!gameHelper.isConnecting()) {
loginGPGS();
}
}
Can anyone explain to me what these methods do? I have them as part of implementing a GoogleApi interface I made in the context of a tutorial. I especially don't understand the 100 / 101 parts, but the whole thing, in general, is quite confusing for me.
PS. I am making a game in LibGDX and this is my first time touching the Google Play API (or I think any API for that matter)
First Method getLeaderboardGPGS show you Leaderboard above your Activity
if you are already Signed in otherwise it start signing process.
Above method definition is from Libgdx wiki but it should be
private final static int REQUEST_CODE_UNUSED = 9002;
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(gameHelper.getApiClient(), getString(R.string.leaderboardId)), REQUEST_CODE_UNUSED);
REQUEST_CODE_UNUSED is an arbitrary integer for the request code
getString(R.string.leaderboardId) is LEADERBOARD_ID
taken from Google wiki
Second Method getAchievementsGPGS is used to show a player's achievements, call getAchievementsIntent() to get an Intent to create the default achievements UI.
startActivityForResult(Games.Achievements.getAchievementsIntent(gameHelper.getApiClient()), REQUEST_ACHIEVEMENTS);
where REQUEST_ACHIEVEMENTS is an arbitrary integer used as the request code.

I am trying to run the code inside the onMenuItemClick() without pressing the menu button

This is the code for android activity I want to run, if at all possible without creating a new activity. Need to get rid of the Listener function. I tried to make a new java class but it gave me error on putExtra functions. Also how can I deal with the instance of newConnection inside the Listener constructor.
public class NewConnection extends Activity {
private Bundle result = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
private class Listener implements OnMenuItemClickListener {
//used for starting activities
private NewConnection newConnection = null;
public Listener(NewConnection newConnection)
{
this.newConnection = newConnection;
}
Trying to run the code below without clicking:
#Override
public boolean **onMenuItemClick**(MenuItem item) {
{
// this will only connect need to package up and sent back
Intent dataBundle = new Intent();
String server = ("tsp//:server address");
String port = ("1823");
//put data into a bundle to be passed back to ClientConnections
dataBundle.putExtra(ActivityConstants.server, server);
dataBundle.putExtra(ActivityConstants.port, port);
...
...
//add result bundle to the data being returned to ClientConnections
dataBundle.putExtras(result);
setResult(RESULT_OK, dataBundle);
newConnection.finish();
}
return false;
}
This is the code used to call the activity:
createConnection = new Intent();
createConnection.setClassName(
clientConnections.getApplicationContext(),
"org.eclipse.paho.android.service.sample.NewConnection");
clientConnections.startActivityForResult(createConnection,
ActivityConstants.connect);
This is a basic constructor within a listener paradigm. It's a core idea within computer science that code should be reusable, and to facilitate this code needs to generally be self contained. This is often done within Java with a listener. It's usually an abstract class or an interface that has a few set functions. The main class that uses the listener is assigned this object or objects, and when it reaches a relevant point will trigger the listener to notify your code of an event.
This allows people to write code that is fully contained and still provide event hooks whereby other user who employ that code can get feedback such as when a menu item is clicked or a new connection is made, and have this dealt with by the person using this code, but without the author of the original class knowing anything about your code. It allows things like menus and connection managers and buttons that have no connection to the code that they trigger, by design. So that any number of these can be made and used.

Is there a way for push notifications in libGDX (Android and iOS projects)?

Does someone knows if it is possible to add push notifications(like Amazon Simple Notification Service) in an Android and iOS with RoboVM libGDX projects? And if it is possible, are there any good tutorials or good hints how to implement such things?
I would be happy about every hint how I can implement it.
Hi I know this is an old question but I was struggling to find a solution for this specially for iOS, but I finally found a way. If the explanation below is confusing and you prefer to see an example here is a github repo with a sample project:
Repo GitHub
I only show the code for iOS see the repo for Android.
The idea is simple you need to create a class that handles sending a notification for each platform on each of your projects (Android and iOS) and have it implement an interface called NotificationsHandler.
NotificationsHandler:
public interface NotificationsHandler {
public void showNotification(String title, String text);
}
iOS Adapter:
public class AdapteriOS implements NotificationsHandler {
public AdapteriOS () {
//Registers notifications, it will ask user if ok to receive notifications from this app, if user selects no then no notifications will be received
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Alert, null));
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Sound, null));
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Badge, null));
//Removes notifications indicator in app icon, you can do this in a different way
UIApplication.getSharedApplication().setApplicationIconBadgeNumber(0);
UIApplication.getSharedApplication().cancelAllLocalNotifications();
}
#Override
public void showNotification(final String title, final String text) {
NSOperationQueue.getMainQueue().addOperation(new Runnable() {
#Override
public void run() {
NSDate date = new NSDate();
//5 seconds from now
NSDate secondsMore = date.newDateByAddingTimeInterval(5);
UILocalNotification localNotification = new UILocalNotification();
localNotification.setFireDate(secondsMore);
localNotification.setAlertBody(title);
localNotification.setAlertAction(text);
localNotification.setTimeZone(NSTimeZone.getDefaultTimeZone());
localNotification.setApplicationIconBadgeNumber(UIApplication.getSharedApplication().getApplicationIconBadgeNumber() + 1);
UIApplication.getSharedApplication().scheduleLocalNotification(localNotification);
}
});
}
}
Now by default Libgdx passes your ApplicationListener or Game object to AndroidLauncher and IOSLauncher along with a configuration object. The trick is to pass the class we created earlier to the ApplicationListener so that you can use it inside your Core project. Simple enough:
public class IOSLauncher extends IOSApplication.Delegate {
#Override
protected IOSApplication createApplication() {
IOSApplicationConfiguration config = new IOSApplicationConfiguration();
// This is your ApplicationListener or Game class
// it will be called differently depending on what you
// set up when you created the libgdx project
MainGame game = new MainGame();
// We instantiate the iOS Adapter
AdapteriOS adapter = new AdapteriOS();
// We set the handler, you must create this method in your class
game.setNotificationHandler(adapter);
return new IOSApplication(game, config);
}
public static void main(String[] argv) {
NSAutoreleasePool pool = new NSAutoreleasePool();
UIApplication.main(argv, null, IOSLauncher.class);
pool.close();
}
}
Now that you have a reference to the implementation of NotificationHandler you can simply call it through your Core project.
public class MainGame extends Game {
// This is the notificatino handler
public NotificationHandler notificationHandler;
#Override
public void create () {
// Do whatever you do when your game is created
// ...
}
#Override
public void render () {
super.render();
// This is just an example but you
// can now send notifications in your project
if(condition)
notificationHandler.showNotification("Title", "Content");
}
#Override
public void dispose() {
super.dispose();
}
// This is the method we created to set the notifications handler
public void setNotificationHandler(NotificationHandler handler) {
this.notificationHandler = handler;
}
}
One last thing
If you need to run the Desktop version then you will need to do the same thing for Desktop otherwise you might get errors, it will not do anything on the Desktop, or you can check the platform before calling the method showNotfication. You can clone the repo where I do this:
Repo GitHub
I've never done it myself. But you can use this tutorial to find out how to write Android specific code in your libGDX project. Your Android code could then receive the notifications and trigger a callback in libGDX. I hope this is at least a step in the right direction.
However I' not sure about doing the same for iOS.

Categories