I am thinking of using Skiller to manage my multiplayer game and had some questions. I was hoping to find some tutorials on how to use it, but I'll have to look through the code and the examples to figure it out. From what I understand, the data sent back and forth in a turn based game (payload) is going to be a string. This means all my information will need to be condensed into a string and then extracted out on the other end?
For example, Pikachu wants to use Thundershock on Pidgey.
Info to send: MoveName("Thundershock"), movePower("40"), specialAttack("55")
(I could put a key at the beginning to help me figure out what is being sent.)
String payload = "Move;Thundershock; 40; 55";
Then the other player's game would take that info and figure out the damage done and send that info back
payload = "Damage; Super Effective; 23"
How does this sound?
SKApplication.getInstance().getGameManager().getTurnBasedTools().makeMove(gameId, event, payload, chatline,
new SKListenerInterface<SKGameMoveResponse>(){
#Override
public void onResponse(SKGameMoveResponse response){
String gameId = response.getGameId();
eTBGameState state = response.getGameState();
String payload = response.getPayload();
String chatline = response.getChatline();
// handle opponent's move – explained in the next section
}
#Override
public void onError(SKStatusResponse response) {
// failed to send the move
}
});
Here is the documentation site
Related
I'm using the Brother Print SDK for Android. My code is based on the example code as shown in the manual:
void printTemplate(int templateKey, String newText) {
// Specify Printer
final Printer printer = new Printer();
PrinterInfo settings = printer.getPrinterInfo();
settings.printerModel = Model.QL_1110NWB;
settings.ipAddress = "your-printer-ip";
// Connect, then print
new Thread(new Runnable() {
#Override
public void run() {
if (printer.startCommunication()) {
// Specify the template key and the printer encode
if (startPTTPrint(templateKey, null)) {
// Replace text object with new text
replaceText(newText);
// Start print
PrinterStatus result = printer.flushPTTPrint();
if (result.errorCode != ErrorCode.ERROR_NONE) {
Log.d("TAG", "ERROR - " + result.errorCode);
}
}
printer.endCommunication();
}
}
}).start();
}
When the printer has its cover open, the flushPTTPrint() function does immediately return with a status of ERROR_COVER_OPEN. That is great.
When the printer is out of paper, the flushPTTPrint() function only returns after about three minutes with a status of ERROR_COMMUNICATION_ERROR. Not so great.
QUESTION: how can I detect when the printer is out of paper? Any method would be fine, either be getting flushPTTPrint() to return immediately with a out of paper staus or by querying the printer actively beforehand.
EDIT (in response to Matt Clark's suggestion)
One can set a handler to process status messages from the printer. On a regular printout (and also on the last printout before the paper is empty) the following messages arrive in this order:
MESSAGE_START_COMMUNICATION
MESSAGE_START_CONNECT
MESSAGE_END_CONNECTED
MESSAGE_START_SEND_STATUS_REQUEST
MESSAGE_END_READ_PRINTER_STATUS
MESSAGE_START_SEND_DATA
MESSAGE_END_SEND_DATA
When the last paper was used, the printer immediately turns a red led on and shows on its display the out of paper notice. When trying to print in this situation, the following messages arrive:
MESSAGE_START_COMMUNICATION
MESSAGE_START_CONNECT
MESSAGE_END_CONNECTED
MESSAGE_START_SEND_STATUS_REQUEST
...about three minutes later...
MESSAGE_START_SOCKET_CLOSE
MESSAGE_END_SOCKET_CLOSE
The out of paper message (MESSAGE_PAPER_EMPTY) is never seen.
EDIT 2
I just figured out that this problem only happens when connecting via Bluetooth. When using WiFi the above mentioned function immediately returns with an error code ERROR_PAPER_EMPTY.
Perhaps try calling printer.getPrinterStatus() before attempting to print?
Reading the documentation, it appears as if the printer is capable of sending asynchronous messages back to your application. This might be useful to catch a variety of things, including determining when the printing is actually complete.
From the documentation:
Section 4.1.2.3 shows a method which you can use to register a callback for these messages received:
void setMessageHandle(Handler handler, int MsgType)
Section 4.2.2.13 has a list of all the message types available, one of them being:
MESSAGE_PAPER_EMPTY
I imagine you would get this message as soon as the printer detects the out of paper state.
I've set up a bidirectional stream construct in an Android app, where I am currently using the mechanism to send chunks of large files. The problem I am having is that my app will receive a request message for a file, then I'll respond with potentially hundreds of MBs worth of response GRPC messages, frequently causing an OOM. Pseudo code:
public class Myclass implements StreamObserver<CameraRequest>, Closeable {
...
public void onNext(Request req) {
for (Chunk chunk : getChunks(req))
this.requestObserver.onNext(builder.setChunk(chunk).build());
}
...
}
Is there some good way to rate limit the number of outstanding calls to onNext based on what has actually been put on the wire (and corresponding memory made freeable)? IE only allowing 10 calls to onNext to be made, then subsequent ones block until the data for the preceding calls has successfully been sent by the underlying protocol stack? I could implement a full e2e acknowledgement window in my wire protocol TCP style, but was hoping there was an easier/built in technique others were using.
Thanks!
Cast requestObserver to ClientCallStreamObserver. You can then call clientCallStreamObserver.isReady() to check if you should stop sending.
You will then need notifications for when the RPC is ready for more messages, to resume sending. For that, implement ClientResponseObserver and call clientCallStreamObserver.setOnReadyHandler(Runnable) within beforeStart().
Putting that all together, gets you something like:
public class MyClass implements
ClientResponseObserver<CameraRequest,CameraResponse> {
private ClientCallStreamObserver<CameraRequest> requestObserver;
private Iterable<Chunk> chunks;
public void beforeStart(ClientCallStreamObserver<CameraRequest> requestObserver) {
this.requestObserver = requestObserver;
requestObserver.setOnReadyHandler(MyClass::drain);
}
public void onNext(CameraRequest req) {
// I don't know if this assert valid for your protocol
assert chunks == null || !chunks.hasNext();
chunks = getChunks(req);
drain();
}
public void drain() {
while (requestObserver.isReady() && chunks.hasNext()) {
Chunk chunk = chunks.next();
requestObserver.onNext(builder.setChunk(chunk).build());
}
}
...
}
You can check out the flow control example here.
I have to implement live tracking using Glympse. In Glympse application you can share a link that link will show your current location. Now I have to get that link and send that link to server. I am searching for it but I am unable to get desired solution to get that link.
I have got examples form https://developer.glympse.com/docs/core/client-sdk/downloads link.
The GlympseCreateDemo shows the steps needed to get the link, but here are the key parts.
// Create the ticket for the given duration.
GTicket ticket = GlympseFactory.createTicket(duration, null, null);
// For the recipient list, we create a single "LINK" recipient. This
// means we want a recipient URL for the new Glympse without having
// the Glympse API actually send the invite out to anyone.
GInvite recipient = GlympseFactory.createInvite(GC.INVITE_TYPE_LINK, null, null);
ticket.addInvite(recipient);
// Call sendTicket to create the ticket and the recipient URL.
_glympse.sendTicket(ticket);
To listen for when the link is available
// The object you pass to this method must implement GEventListener
// In the demo this is done in GlympseCreateDemoActivity.java
ticket.addListener(this);
// Once the invite is ready you will get this event
#Override public void eventsOccurred(GGlympse glympse, int listener, int events, Object obj)
{
if (GE.LISTENER_TICKET == listener)
{
if (0 != (events & GE.TICKET_INVITE_CREATED))
{
GTicket ticket = (GTicket) obj;
// This string will contain the link that you can send to your server
String theUrlLink = ticket.getInvites().at(0).getUrl();
}
}
}
My app is using a NotificationListener to read out messages from various 3rd party apps, for example WhatsApp.
So far I was able to send a reply if only one chat is unread, the code is below.
However, in the case with WhatsApp, getNotification().actions returns a null object when more than two chats are unread, as the messages are bundled together. As you can see in the pictures below, if the notifications are extended there is an option to send a direct reply as well, therefore I am certain that it is possible to utilize this, also I think apps like PushBullet are using this method.
How could I access the RemoteInput of that notification?
public static ReplyIntentSender sendReply(StatusBarNotification statusBarNotification, String name) {
Notification.Action actions[] = statusBarNotification.getNotification().actions;
for (Notification.Action act : actions) {
if (act != null && act.getRemoteInputs() != null) {
if (act.title.toString().contains(name)) {
if (act.getRemoteInputs() != null)
return new ReplyIntentSender(act);
}
}
}
return null;
}
public static class ReplyIntentSender {
[...]
public final Notification.Action action;
public ReplyIntentSender(Notification.Action extractedAction) {
action = extractedAction;
[...]
}
private boolean sendNativeIntent(Context context, String message) {
for (android.app.RemoteInput rem : action.getRemoteInputs()) {
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putCharSequence(rem.getResultKey(), message);
android.app.RemoteInput.addResultsToIntent(action.getRemoteInputs(), intent, bundle);
try {
action.actionIntent.send(context, 0, intent);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
return false;
}
}
Some explanation how the above code works: Once a notification is received the app tries to get the actions and checks if the name is in the title of a remoteInput (normally it is in the format of "Reply to $NAME"), if that is found the Action is saved into a ReplyIntentSender class, which, when triggered by sendNativeIntent, cycles through all RemoteInputs of that Action and adds the message to the intent. If more than one chat is unread, getNotification().actions returns null.
Below are two screenshots, the first one where it is working without any problems and the second one where it doesn't.
You can consider this as my suggestion. I have done bit research on this and come up with following conclusions.(Also it looks like you have done plenty of research on this so it might be possible that you aware about what I wrote below)
Numerous apps send Wear specific notifications, and many of those contain actions accessible from an Android Wear device. We can grab those Wear notifications on the device, extracting the actions, finding the reply action (if one exists), populating it with our own response and then executing the PendingIntent which sends our response back the original app for it to send on to the recipient.
To do so you can refer this link (A nice workaround by Rob J). You can also refer this link in this context (Great research work done by Michał Tajchert).(You might need to work around with NotificationCompat.isGroupSummary)
This is what I feel(Might be I am totally wrong)
.actions method returns Array of all Notification.Action
structures attached to current notification by addAction(int,
CharSequence, PendingIntent), Here addAction method is deprecated
one so it might not working as intended.
I am not able to test this at my end otherwise I will love to provide a working solution with code.
Hope this will help you. Happy Coding!!!
I'm currently attempting to use AppSync to sync a piece of data between an android app and a pebble app. However, I seem to not be able to get the pebble to realize that any data is being transferred - that is, no logs are being produced where they should be. What is really bothering me is that this is essentially the code found in the pebble weather example. I've pasted the relevant bits of code below - could someone possibly look it over and suggest where any issues may be? I've made sure that the UUIDs in both programs (pebble app and android app) are the same, and that they are on the same network, and that the pebble is actually connected to the phone, and that the android function is actually being called and all.
Snippet of pebble app code:
static void sync_error_callback(DictionaryResult dict_error, AppMessageResult app_message_error, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "App Message Sync Error: %d", app_message_error);
}
static void sync_tuple_changed_callback(const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, new_tuple->value->cstring);
}
void home_screen_load() {
// set up each one of the SimpleMenuItems
Tuplet initial_values[] = {
TupletCString(0x0, "Initial 1")
};
app_sync_init(&sync, sync_buffer, sizeof(sync_buffer), initial_values, ARRAY_LENGTH(initial_values), sync_tuple_changed_callback, sync_error_callback, NULL);
}
Snippet of android app:
final UUID PEBBLE_APP_UUID = UUID.fromString("10549fd4-1fe4-4d30-8a18-6f2f8149f8fd");
public void sendDataToWatch(String toSend) {
// Build up a Pebble dictionary containing the weather icon and the current temperature in degrees celsius
PebbleDictionary data = new PebbleDictionary();
data.addString(0x0, toSend);
PebbleKit.sendDataToPebble(getApplicationContext(), PEBBLE_APP_UUID, data);
}
To debug this type of problem, you should set a inbox_dropped handler and see if you get anything there.
After initializing AppMessage and AppSync, call:
app_message_register_inbox_dropped(appmsg_in_dropped);
And add this function:
static void appmsg_in_dropped(AppMessageResult reason, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "In dropped: %s", translate_error(reason));
}
Take a look at this question for the source of the translate_error function.