GCM sometimes works, sometimes doesn't - java

My aplication is a multiplayer game in android, with a server running on google app engine and using GCM to conect the server with the player devices. i have registered the device in GCM and then i sent the registerId to the server to connect with the device. When i run the game sometimes it works fine but sometimes the device doesn¡t receive anything from GCM, the server still receive from the device. I have no idea what is happening :s
Here is where i register my device in the onCreate of the main class :
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
if (GCMRegistrar.isRegistered(this)) {
Log.d("info", GCMRegistrar.getRegistrationId(this));
}
regId = GCMRegistrar.getRegistrationId(this);
deviceId = getDeviceId();
if (regId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
Log.d("info", GCMRegistrar.getRegistrationId(this));
}
Then the first time i run the application on a phone i use this code to send the registationId to the server:
sendMessage("code=" + REGISTRATION_CODE +
"&deviceId=" + deviceId +
"&regId=" + regId +
"&phoneNumber=" + phoneNumber);
And here is the code in the server to send messages back to the device:
public void sendMessage(String regId, String text) {
Sender sender = new Sender(APIKey);
Message message = new Message.Builder().collapseKey("1").timeToLive(3).delayWhileIdle(true).addData("message", text).build();
try {
sender.send(message,regId,1);
} catch (IOException e) {
e.printStackTrace();//Manejar la excepcion
}
}
I can't understand why stop working, i'm in the middle of a game and stops working and then works again ...

I just solved it, the problem was the collapseKey here
Message message = new Message.Builder().collapseKey("1").timeToLive(3).delayWhileIdle(true).addData("message", text).build();
If you use the same collapseKey always sometimes you don't receive messages randomly so i try this and works finally works!!
Message message = new Message.Builder().collapseKey(""+((int) (Math.random () * (10000)))).timeToLive(3).delayWhileIdle(true).addData("message", text).build();

Related

Bluetooth connected but not sending data

I'm working on a project connecting my Android phone to an Arduino bluetooth transceiver. It works fine until the phone goes into suspend (sleep?) mode; when that happens, the bluetooth connection I establish seems to still exist, but no data is transferred. I'm using Android Sdk 30.
Here's what I do: I have a UI list with BT devices for the user to choose; after one is selected, this is called to connect:
// in my BluetoothService class
private BluetoothDevice bluetoothDevice;
private BluetoothSocket bluetoothSocket;
public void connect(BluetoothDevice device) {
try {
bluetoothDevice = device;
String uuid = getString(R.string.bluetooth_uuid);
bluetoothSocket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(uuid));
bluetoothSocket.connect();
if (bluetoothSocket.isConnected()) {
Log.i(TAG, "connected to " + device + " with socket " + bluetoothSocket);
} else {
Log.w(TAG, "still not connected to " + device + " with socket " + bluetoothSocket);
}
} catch (IOException e) {
Log.e(TAG, "failed to connect to device", e);
}
}
So again, this works fine; the connection is established and data is sent/received.
Now, I send data every 30 seconds, and on the receiver side light an led until 60 seconds have passed with no data received.
private ScheduledFuture<?> sendScheduler; // canceled in onDestroy()
public void onCreate() {
sendScheduler = Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
sendData(lastLevelSent); // i can post sendData, but it works in normal state
}, 30, 30, TimeUnit.SECONDS);
}
Now when the phone goes into sleep (ie I press the power button once), the led turns off after 60 seconds, ie no data is being received. However, the connection itself seems to still be established (I can tell by how the receiver led blinks).
When I wake the device back up, it does not resume sending data. The disconnect button in my app doesn't work (bluetoothSocket.close()), and trying to connect to the device again doesn't either. I have to kill the app, then I can disconnect.
The check I'm using whether the connection is still valid is bluetoothSocket != null && bluetoothSocket.isConnected().
I did add my app to the "don't put into standby" in the Android settings.
So how can I either convince the app to continue sending data while in sleep mode, or at least reliably check the connection status?

Is it possible to make insecure connection between android bluetooth and laptop bluetooth device?

I am trying to connect android device with laptop or desktop which contains Bluetooth via Bluetooth socket connection.
I have created one android application (Client) which tries to connect laptop Bluetooth device where java application (Server) is running.
My concern is that, Is it possible to connect both the device insecurely (without pin authentication) using Bluetooth socket connection?
If possible, Please suggest me solution.
If not, Is there any way to programmatically auto pair both the devices?
Thanks in advance !!!
By referring java api for bluetooth, I got the solution for Insecure connection between two Android and laptop Bluetooth devices.
I have used SPP client server mechanism.
My server is in java.
In java add certain parameters to URL.
Make authentication= false; authorize=false;encrypt=false;
open this URL for connection acceptance.
//Create a UUID for SPP
UUID uuid=new UUID("0f2b61c18be240e6ab90e735818da0a7", false);
System.out.println("\n"+uuid.toString());
//Create the servicve url
String url="btspp://localhost:"+uuid.toString()+";"+"name=remoteNotifier;authenticate=false;authorize=false;encrypt=false";
//open server url
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)Connector.open(url);
//Create a UUID for SPP
UUID uuid=new UUID("0f2b61c18be240e6ab90e735818da0a7", false);
System.out.println("\n"+uuid.toString());
//Create the servicve url
String url="btspp://localhost:"+uuid.toString()+";"+"name=remoteNotifier;authenticate=false;authorize=false;encrypt=false";
//open server url
StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)Connector.open(url);
Now on client side:
Android API 10 above contains insecure connection method. "createInsecureRfcommSocketToServiceRecord(UUID)"
So use this method for connection. It will not pop up for pairing request adn try to connect with remote Bluetooth device where Java server is already running.
Code:
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
// btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
AlertBox("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
mBluetoothAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
try {
btSocket.connect();
out.append("\n...Connection established and data link opened...");
} catch (IOException e) {
try {
btSocket.close();
e.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
AlertBox("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
}
}
// Create a data stream so we can talk to server.
out.append("\n...Sending message to server...");
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
AlertBox("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
}
// Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android_logo);
// byte[] msgBuffer = getBytesFromBitmap(bitmap);
String message = "Hello from Android.\n";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
if (address.equals("00:00:00:00:00:00")) {
msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 37 in the java code";
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
}
// AlertBox("Fatal Error", msg);
}
I have provided only required code.
For connection UUID should be same for both the devices.
Provide server Bluetooth MAC address at "address" field at client side.
We are able to communicate with remote Bluetooth device insecurely (Without pairing).
But this code is device dependent...
certain device are able to communicate very efficiently.
Like Lenovo laptop, external bluetooth device for PC for Java server
AND
Android devices DELL venue 7, Sony, LG mobiles for client.
Tested and working properly.
But in Dell laptop, Micromaxx, xolo mobile it doesn't work.
I don't know why it is not working, If anyone knows please give the solution.
For Bluetooth 2.1 and above devices, security is mandatory.
If you are just trying to avoid the passkey entry/display, you can set the security requirements on the laptop and android device to "MITM protection not required".
This way the devices will pair automatically, but the link would be susceptible to man in the middle attacks.

GCM sendRegistrationIdToBackend is undefined

I am trying to set up GCM but my project doesn't recognize certain methods. I followed the advice of many other links which was to import GCM and google play services but I am still getting no such luck. Thanks for looking.
Edit: I've cleaned a million times and rebuilt.
I'm not sure where you got the code of the demo app from, but there are several things wrong with it.
First of all, the method you are missing is not implemented in the Demo. It has an empty body :
/**
* Sends the registration ID to your server over HTTP, so it can use GCM/HTTP or CCS to send
* messages to your app. Not needed for this demo since the device sends upstream messages
* to a server that echoes back the message using the 'from' address in the message.
*/
private void sendRegistrationIdToBackend() {
// Your implementation here.
}
It's your responsibility to implement it, since its implementation depends on your server implementation.
Another error (you'd get an exception after you fix the compilation error) is calling gcm.register() from the main thread. You must call it in the background :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDisplay = (TextView) findViewById(R.id.display);
context = getApplicationContext();
// Check device for Play Services APK. If check succeeds, proceed with GCM registration.
if (checkPlayServices()) {
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty()) {
registerInBackground();
}
} else {
Log.i(TAG, "No valid Google Play Services APK found.");
}
}
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration ID and the app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP, so it
// can use GCM/HTTP or CCS to send messages to your app.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device will send
// upstream messages to a server that echo back the message using the
// 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
All code samples are taken from the official GCM Demo app.

Not able to receive ACLMessage in android via JADE

I'm currently using Topic based communication using JADE. I'm able to register a JADE agent using jade.core.messaging.TopicManagementFEService thereby connecting to the main-container in the same platform.
The details are below:
Main-Container: a simple LAMP/WAMP Server that hosts the Main-Container.
Client: An Android Emulator(testing purpose) to connect to the main-container.
Currently,
Server starts the main-container
Android emulator connects to the Main-container successfully (Agent created along with Topic Mgmt Service enabled)
Server is sending messages based on a specific topic.
But my Android Client is not able to receive this message although the topic registered is the same on both ends!
You can see the code below:
Server Side:
TopicManagementHelper topicHelper = (TopicManagementHelper) getHelper(TopicManagementHelper.SERVICE_NAME);
final AID sensorTopic = topicHelper.createTopic("JADE");
topicHelper.register(sensorTopic);
addBehaviour(new TickerBehaviour(this, TIMER_VALUE_IN_MILLISECONDS) {
private static final long serialVersionUID = -2567778187494378326L;
public void onTick() {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(eventTopic);
msg.setContent(eventValue);
myAgent.send(msg);
}
});
Android Side:
// Registering on Android Side as well
TopicManagementHelper topicHelper = (TopicManagementHelper) getHelper(TopicManagementHelper.SERVICE_NAME);
topic = topicHelper.createTopic("JADE"); // See, same topic!
topicHelper.register(topic);
behaviour = new myBehaviour(this, TIMER_VALUE_IN_MILLISECONDS, topic);
addBehaviour(behaviour);
private class myBehaviour extends TickerBehaviour {
private static final long serialVersionUID = 4782913834042415090L;
AID topic;
Agent agent;
MessageTemplate tpl;
public myBehaviour(Agent a, long period, AID topic) {
super(a, period);
this.agent = a;
this.topic = topic;
}
public void onTick() {
tpl = MessageTemplate.MatchTopic(topic);
ACLMessage msg = receive(tpl);
if (msg != null) {
logger.log(Level.INFO, "Agent "+ agent.getLocalName() +
": Message about topic "+ topic.getLocalName() +" received. \n" +
"Content is " + msg.getContent());
data = msg.getContent();
} else {
logger.log(Level.INFO, "In here..."); // Always executes only this code!
block();
}
}
}
Where am I going wrong here? It always executes the else part in the Android side which is obvious to say that message received is NULL!
Never mind. The logic was wrong. The Android-Agent was not identifying itself to the Central-Agent.
I set the Ontology so that the Central Agent is able to identify such message and sends the message accordingly. Now, it is receiving messages!
Self-help works sometimes! ;-)
Receiving topic messages doesn't work correctly with Android up to version 4.3.0 in JADE. Android can send out topic messages but can't receive them. I found this out through my own issues. I've posted more info about it in my own question on stack overflow.
Take a look. JADE Leap Android App unable to receive topic messages

Receiving SMS Messages using WMA in Java ME

I am trying to develop a sms sending and receiving test application in J2ME using the WMA API. I have separate threads for sending and receiving.
The Sending thread's run method -
public void run() {
try {
MessageConnection connection = (MessageConnection) Connector.open("sms://+" + number + ":1234");
BinaryMessage messageBody = (BinaryMessage) connection.newMessage(connection.BINARY_MESSAGE);
messageBody.setPayloadData(message.getBytes());
connection.send(messageBody);
connection.close();
} catch (IOException ex) {
}
}
The receiving thread's run method
public void run() {
try {
while (true) {
MessageConnection connection = (MessageConnection) Connector.open("sms://:1234");
BinaryMessage messageBody = (BinaryMessage) connection.receive();
message = new String(messageBody.getPayloadData());
number = messageBody.getAddress();
number = number.substring(6, 15);
App.setDisplay(number, message);
connection.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
I am initializing the receiving thread in the startApp() and initializing the sending thread when the send command is pressed. The problem I have is that if I use two Emulators, both sides can't send messages. One emulator can continuously send messages to the other but when the other emulator tries to send a message the message isn't received.
When a message is received by the emulator console shows -
[INFO] [sms ] ## javacall: SMS
sending...
when that line appears the emulator doesn't receive any messages. Where is the problem in my code?
PS: I saw that their is a way to use a listener to work around this problem with using a separate thread for receiving but I want to know where is the problem is in the above code?
Any help is really appreciated ^^
If you are running in emulator, use wma console available to send or receive messages. You can't do it from emulator to emulator. wma console is available at
utilities -> wma console
I found the problem... It's because SMS doesn't work in Netbeans above versions. It only works in Netbeans 6.1 ... Something is wrong with the emulator

Categories