I am struggling to connect to server's websocket on android java.
My main class for websocket on server-side is as below.
#ServerEndpoint("/websocket")
public class WebsocketListener {
#OnOpen
public void handleConnect(Session session) {
System.out.println("Client connect : " + session);
}
#OnMessage
public void handleMessage(Session session, String message) {
System.out.println(session + " : " + message);
String[] tokens = message.split(":::");
if(tokens[0].equals("connect")) {
WebSocketSessionManager.addSession(tokens[1], session);
} else if(tokens[0].equals("alert")) {
WebSocketSessionManager.sendMessage(tokens[1]);
}
}
#OnClose
public void handleDisconnect(Session session) {
System.out.println(session + "과의 연결 종료.");
WebSocketSessionManager.removeSession(session);
}
#OnError
public void handleError(Session session, Throwable throwable) {
throwable.printStackTrace();
WebSocketSessionManager.removeSession(session);
}
}
And below is my android-java code for trying to connect to server's websocket.
package com.example.socketexample;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URI;
public class MainActivity extends AppCompatActivity {
private Button button;
private WebSocketClient webSocketClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
connectToWebSocket();
}
});
}
private void connectToWebSocket() {
Log.i("websocket", "connectToWebSocket() called.");
URI uri;
try {
uri = new URI("ws://10.21.20.24:8080/websocket");
} catch(Exception e){
e.printStackTrace();
return;
}
webSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen(ServerHandshake handshakedata) {
Log.i("websocket", "connected to server.");
webSocketClient.send("connect:::TESTKEY");
webSocketClient.send("alert:::HI");
}
#Override
public void onMessage(String message) {
Log.i("websocket", message);
}
#Override
public void onClose(int code, String reason, boolean remote) {
Log.i("websocket", "closed.");
}
#Override
public void onError(Exception ex) {
Log.i("websocket" , "error : " + ex.getMessage());
}
};
webSocketClient.connect();
}
}
I saw that websocket uses ws:// protocol, so I set the URI to ws://10.21.20.24, which is the IP address in my wifi.
For server's websocket, I am using the pom.xml dependency below.
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
For android's websocket, I am using the gradle dependency below.
implementation 'org.java-websocket:Java-WebSocket:1.3.0'
Thank you so much in advance. :(
For everyone who is suffering from the same problem that I encountered...
I solved the problem by adding new Draft_17() as the second parameter of new WebSocketClient(). The code is summarized as below.
private void connectToWebSocket() {
Log.i("websocket", "connectToWebSocket() called.");
URI uri;
try {
uri = new URI("ws://10.21.20.24:8080/websocket");
} catch(Exception e){
e.printStackTrace();
return;
}
webSocketClient = new WebSocketClient(uri, new Draft_17()) {
// ...
}
}
However, this issues is from year 2017, and I think I have to find an alternative for Draft_17.
https://github.com/TooTallNate/Java-WebSocket/issues/478
Good luck!
Related
I used Bluetooth API and following code is for on/off, show paired devices list, and connect paired devices.
other functions work well, but connecting devices doesn't work .
I try to use thread bidirectional, when bluetooth turns on, serverthread(acceptthread) generated and started. And when I choose device on the list, clientthread(connectthread) generated and started. This is my intent, but when I try to connect on the phone, app is turned off(almost at the client, occasionally at the server).
I thought maybe it's UUID problem so I checked UUID 00enter code here001101-0000-1000-8000-00805F9B34FB, but it didn't help.enter code here
sorry for the import code chunks, I would really appreciate your help.
'''
package com.practice.bluetoothmodule;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
public class MainActivity extends AppCompatActivity {
TextView bthStatus;
Button bthOn;
Button bthOff;
Button bthCon;
BluetoothAdapter bthAdapter;
Set<BluetoothDevice> pairedDevices;
List<String> listofPairedDevices;
private String btAddress=null;
BluetoothDevice bthDevice;
AcceptThread acceptThread;
ConnectThread connectThread;
private Handler mHandler = null;
final static int BT_REQUEST_ENABLE=1;
final static UUID BT_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bthStatus = (TextView)findViewById(R.id.text_check);
bthOn = (Button)findViewById(R.id.bth_on);
bthOff=(Button)findViewById(R.id.bth_off);
bthCon=(Button)findViewById(R.id.dev_con);
bthAdapter=BluetoothAdapter.getDefaultAdapter();
bthOn.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view){
bluetoothOn();
}
});
bthOff.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view){
bluetoothOff();
}
});
bthCon.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View view){
listPairedDevices();
}
});
}
#Override
public void onStart(){
super.onStart();
}
#Override
public void onDestroy(){
super.onDestroy();
if(acceptThread != null){
acceptThread.cancel();
acceptThread=null;
}
if(connectThread != null){
connectThread.cancel();
connectThread=null;
}
}
void bluetoothOn(){
if(bthAdapter == null){
Toast.makeText(getApplicationContext(),"블루투스를 지원하지 않는 기기입니다",Toast.LENGTH_SHORT).show();
}
else{
if(bthAdapter.isEnabled()){
Toast.makeText(getApplicationContext(),"블루투스가 이미 활성화된 상태입니다",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),"블루투스가 활성화 되어 있지 않습니다",Toast.LENGTH_SHORT).show();
Intent intentBthEnable = new Intent(bthAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intentBthEnable,BT_REQUEST_ENABLE);
}
}
}
void bluetoothOff(){
if(bthAdapter.isEnabled()){
bthAdapter.disable();
Toast.makeText(getApplicationContext(),"블루투스가 비활성화 되었습니다.",Toast.LENGTH_SHORT).show();
bthStatus.setText("비활성화");
}
else{
Toast.makeText(getApplicationContext(),"블루투스가 이미 비활성화 상태입니다",Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
switch(requestCode){
case BT_REQUEST_ENABLE:
if(resultCode == RESULT_OK){
Toast.makeText(getApplicationContext(),"블루투스 활성화",Toast.LENGTH_LONG).show();
bthStatus.setText("활성화");
start();
} else if(resultCode == RESULT_CANCELED){
Toast.makeText(getApplicationContext(),"취소",Toast.LENGTH_LONG).show();
bthStatus.setText("비활성화");
}
break;
}
super.onActivityResult(requestCode,resultCode,data);
}
void listPairedDevices(){
if(bthAdapter.isEnabled()){
pairedDevices = bthAdapter.getBondedDevices();
if(pairedDevices.size()>0){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("장치 선택");
listofPairedDevices = new ArrayList();
for(BluetoothDevice device: pairedDevices){
listofPairedDevices.add(device.getName());
}
final CharSequence[] items= listofPairedDevices.toArray(new CharSequence[listofPairedDevices.size()]);
listofPairedDevices.toArray(new CharSequence[listofPairedDevices.size()]);
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
connectSelectedDevice(items[item].toString());
}
});
AlertDialog alert=builder.create();
alert.show();
}
else{
Toast.makeText(getApplicationContext(),"페어링된 장치가 없습니다",Toast.LENGTH_LONG).show();
}
}
else{
Toast.makeText(getApplicationContext(),"블루투스가 비활성화 되어 있습니다.",Toast.LENGTH_LONG).show();
}
}
void connectSelectedDevice(String selectedDeviceName){
for(BluetoothDevice tempDevice: pairedDevices){
if(selectedDeviceName.equals(tempDevice.getName())){
bthDevice=tempDevice;
btAddress=bthDevice.getAddress();
break;
}
}
connect(bthDevice);
//Toast.makeText(getApplicationContext(),"연결 시도"+bthDevice.getName(),Toast.LENGTH_LONG).show();
}
public synchronized void start(){
acceptThread = new AcceptThread();
acceptThread.start();
}
public synchronized void connect(BluetoothDevice device){
connectThread=new ConnectThread(device);
connectThread.start();
}
private class AcceptThread extends Thread{
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp=null;
try{
tmp=bthAdapter.listenUsingRfcommWithServiceRecord("Listen",BT_UUID);
Toast.makeText(getApplicationContext(),"서버 열림",Toast.LENGTH_LONG).show();
}catch(IOException e){
Toast.makeText(getApplicationContext(),"서버 안열림",Toast.LENGTH_LONG).show();
}
mmServerSocket=tmp;
}
public void run(){
BluetoothSocket socket=null;
while(true){
try{
socket=mmServerSocket.accept();
} catch(IOException e){
break;
}
if(socket != null){
Toast.makeText(getApplicationContext(),"연결됨",Toast.LENGTH_SHORT).show();
try{
sleep(3000);
} catch (Exception e){}
}
}
}
public void cancel(){
try{
mmServerSocket.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
private class ConnectThread extends Thread{
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device){
BluetoothSocket tmp=null;
mmDevice=device;
try{
tmp=device.createRfcommSocketToServiceRecord(BT_UUID);
//Toast.makeText(getApplicationContext(),"클라 초기화 됨.",Toast.LENGTH_LONG).show();
}catch (IOException e){
//Toast.makeText(getApplicationContext(),"클라 초기화 실패.",Toast.LENGTH_LONG).show();
}
mmSocket=tmp;
//Toast.makeText(getApplicationContext(),"클라 초기화",Toast.LENGTH_LONG).show();
}
public void run() {
try {
bthAdapter.cancelDiscovery();
mmSocket.connect();
Toast.makeText(getApplicationContext(), "클라이언트 연결", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "연결실패", Toast.LENGTH_LONG).show();
}
}
public void cancel(){
try{
mmSocket.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
'''
With Android device, Enable BluetoothHCISnoop log to know , what is happening . It will give the sequential flow on what is happening with Bluetooth communication.
https://www.androidcentral.com/all-about-your-phones-developer-options
The following reasons may be the cause:
1. In your code the device address may be wrong
2. The service UUID which you are trying to connect should be present in the service discovery database of remote bluetooth device
3. The app should wait for connect to happen How to programmatically tell if a Bluetooth device is connected?
So I'm a beginner in developing android application i wanna know how do you implement websocket to my android application so that i can get the data's from our server
I have tried deserialization the data from json to java so that they'll be able to communicate once the connection is established
package com.example.app;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.net.URISyntaxException;
public class MainActivity extends Activity {
private WebSocketClient mWebSocketClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connectWebSocket();
}
private void connectWebSocket() {
URI uri;
try {
uri = new URI("ws://10.24.204.215:9090");
} catch (URISyntaxException e) {
e.printStackTrace();
return;
}
mWebSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen(ServerHandshake handshakedata) {
Log.i("Websocket", "Opened");
mWebSocketClient.send("Hello from" + Build.MANUFACTURER + " " + Build.MODEL );
}
#Override
public void onMessage(String s) {
final String uiview = s;
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView textView = (TextView)findViewById(R.id.uiview);
textView.setText(textView.getText() + "\n" + uiview);
}
});
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed" + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error" + e.getMessage());
}
};
mWebSocketClient.connect();
}
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
public void sendMessage(View view) {
EditText editText = (EditText) findViewById(R.id.edittxt);
String mWebSocketClient = editText.getText().toString();
editText.setText("");
}
}
It wont let me display gather the data's from the WS to display it to my mobile screen.
Hello me and my group from university decide to create an app, that a client of a gym can see his/her exercise list and we are using retrofit to get a json. Early this code was working very well, but suddenly stopped to work, and now I'm getting null response and status 200 from callback.
image with the log.d 200 and null response
Sorry for my english.
My JSON
{
"0":{
"id":"1",
"nome":"Fernanda Kondrat",
"peso":"67.4",
"altura":"172",
"imc":"22.8",
"login":"fefe",
"senha":"1234"},
"lista_exercicios":[
{
"id":"1",
"id_aluno":"1",
"nome":"supino reto",
"num_serie":"3",
"num_repeticao":"10"
},
{
"id":"2",
"id_aluno":"1",
"nome":"agachamento hack",
"num_serie":"3",
"num_repeticao":"10"
},
{
"id":"3",
"id_aluno":"1",
"nome":"barra fixa",
"num_serie":"3",
"num_repeticao":"10"
},
{
"id":"4",
"id_aluno":"1",
"nome":"leg press",
"num_serie":"4",
"num_repeticao":"10"
}
]
}
And now my MainActivity.java
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.u9.fabapp.virtualgym.APIClient;
import com.u9.fabapp.virtualgym.RespostaLogin;
import com.u9.fabapp.virtualgym.Resposta;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class MainActivity extends AppCompatActivity {
Button btn_login;
EditText edt_login;
EditText edt_senha;
private Callback<RespostaLogin> respostaCallback;
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_login = findViewById(R.id.btn_login);
edt_login = findViewById(R.id.edt_Login);
edt_senha= findViewById(R.id.edt_Senha);
btn_login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Log.d(TAG, "onClick: ");
//Intent i = new Intent(MainActivity.this, ProfileActivity.class);
//startActivity(i);
String login = edt_login.getText().toString();
String senha = edt_senha.getText().toString();
if(TextUtils.isEmpty(login)|| TextUtils.isEmpty(senha)) {
Toast.makeText(MainActivity.this, "Campos vazios", Toast.LENGTH_SHORT).show();
} else {
configurarCallback();
//new APIClient().getRestService().setUsuarioLoginDTO(login, senha, respostaCallback);
new APIClient().getRestService().setUsuarioLoginDTO(login, senha, respostaCallback);
}
}
});
}
private void configurarCallback() {
respostaCallback = new Callback<RespostaLogin>() {
#Override
public void success(RespostaLogin resposta, Response response) {
Log.d(TAG, "Funcionou: "+ response.getStatus());
Log.d(TAG, "Funcionou: " + resposta.getRETORNO());
/*if (resposta.getRETORNO().equals("SUCESSO")){
Intent intent1 = new Intent(MainActivity.this, ProfileActivity.class);
startActivity(intent1);
}else{
Toast.makeText(MainActivity.this, resposta.getRETORNO() +" ,Verifique usuário e senha" , Toast.LENGTH_SHORT).show();
}*/
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(MainActivity.this, "Deu Ruim: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
};
}
}
APIClient.java
import com.u9.fabapp.virtualgym.Resposta;
import com.u9.fabapp.virtualgym.RespostaLogin;
import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.client.OkClient;
import retrofit.http.GET;
import retrofit.http.Query;
import retrofit.http.Path;
public class APIClient {
private static RestAdapter REST_ADAPTER;
public APIClient(){
createAdapterIfNeeded();
}
private static void createAdapterIfNeeded() {
if(REST_ADAPTER == null){
REST_ADAPTER = new RestAdapter
.Builder()
.setEndpoint("http://golfetto.16mb.com/virtual-fit/home/")
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient())
.build();
}
}
public RestServices getRestService(){
return REST_ADAPTER.create(RestServices.class);
}
public interface RestServices{
#GET("/getExercicios.php")
void setUsuarioLoginDTO(
#Query("LOGIN") String login,
#Query("SENHA") String senha,
Callback<RespostaLogin> callbackResposta
);
}
}
In interface "RestService", change at:
#GET("/getExercicios.php")
Modify it as:
#GET("getExercicios.php")
Remove "/" because it is being already being appended.
Thanks and happy coding
The full URL of your service will be
BASE_URL (defined at the time of createing retrofit object) + END_POINT_URL (defined in the interface)
You have added "http://golfetto.16mb.com/virtual-fit/home/" as base URL and in the interface you have define the endpoint as "/getExercicios.php" so the full URL will be
"http://golfetto.16mb.com/virtual-fit/home//getExercicios.php"
which is not a valid URL. So you have to remove '/' from the interface
The interface will be
public interface RestServices{
#GET("getExercicios.php")
void setUsuarioLoginDTO(
#Query("LOGIN") String login,
#Query("SENHA") String senha,
Callback<RespostaLogin> callbackResposta
);
}
I am trying to write a plugin that will check if Android Pay is setup on the users phone. I have followed the Android tutorial with their sample code but can't get it to work with Cordova. When the function canMakePayments is called from the sample below, nothing happens. I do not see a failure or success come back from the call to Wallet.Payments.isReadyToPay. Any advise would be much appreciated.
package com.myapp.test;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import android.util.Log;
import android.support.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.app.ProgressDialog;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.BooleanResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wallet.MaskedWallet;
import com.google.android.gms.wallet.MaskedWalletRequest;
import com.google.android.gms.wallet.Wallet;
import com.google.android.gms.wallet.WalletConstants;
import com.google.android.gms.wallet.fragment.SupportWalletFragment;
import com.google.android.gms.wallet.fragment.WalletFragmentInitParams;
import com.google.android.gms.wallet.fragment.WalletFragmentMode;
import com.google.android.gms.wallet.fragment.WalletFragmentOptions;
import com.google.android.gms.wallet.fragment.WalletFragmentStyle;
public class AndroidPay extends CordovaPlugin implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
// actions
private static final String CAN_MAKE_PAYMENTS = "canMakePayments";
// Plugin tag name
private static final String TAG = "AndroidPay";
// Cordova callbacks
CallbackContext canMakePaymentCallback = null;
// Android Pay
private SupportWalletFragment mWalletFragment;
private GoogleApiClient mGoogleApiClient;
public static final int WALLET_ENVIRONMENT = WalletConstants.ENVIRONMENT_TEST;
/*
* Public function calls
*/
#Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
Log.d(TAG, "Plugin initialized");
}
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
boolean validAction = true;
if (action.equals(CAN_MAKE_PAYMENTS)) {
canMakePayments(callbackContext);
}
else {
validAction = false;
}
return validAction;
}
/*
* Private function calls
*/
private void canMakePayments(CallbackContext callbackContext) {
Log.d(TAG, "canMakePayments");
canMakePaymentCallback = callbackContext;
try {
// Setup Google client
mGoogleApiClient = new GoogleApiClient.Builder(this.cordova.getActivity())
.addApi(Wallet.API, new Wallet.WalletOptions.Builder()
.setEnvironment(WALLET_ENVIRONMENT)
.build())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
// Check if user is ready to use Android Pay
Wallet.Payments.isReadyToPay(mGoogleApiClient).setResultCallback(
new ResultCallback<BooleanResult>() {
#Override
public void onResult(#NonNull BooleanResult booleanResult) {
if (booleanResult.getStatus().isSuccess()) {
if (booleanResult.getValue()) {
// Show Android Pay buttons and user can make payments
Log.d(TAG, "isReadyToPay:true");
// TODO: Add logic
canMakePaymentCallback.success();
} else {
// Hide Android Pay buttons, user can't make payments
Log.d(TAG, "isReadyToPay:false:" + booleanResult.getStatus());
// TODO: Add logic
canMakePaymentCallback.failure();
}
} else {
// Error making isReadyToPay call
Log.e(TAG, "isReadyToPay:" + booleanResult.getStatus());
canMakePaymentCallback.failure();
}
}
});
} catch (Exception e) {
e.printStackTrace();
System.err.println("Exception: " + e.getMessage());
}
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d(TAG, "***** onConnectionFailed:" + connectionResult.getErrorMessage());
}
#Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "***** Connection suspended *****");
}
#Override
public void onConnected(Bundle connectionHint) {
Log.d(TAG, "***** Connected to GoogleApiClient *****");
}
}
It wasn't in the developer documentation but what fixed this for me was to make a connect call to the google client before calling Wallet.Payments.isReadyToPay
mGoogleApiClient = new GoogleApiClient.Builder(this.cordova.getActivity())
.addApi(Wallet.API, new Wallet.WalletOptions.Builder()
.setEnvironment(WALLET_ENVIRONMENT)
.build())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
// Connect to google api client
mGoogleApiClient.connect();
Remote Service
I'm doing a test for Android remote Service.
In the first app module, I make a service, complete as below:
AppService
package com.hqyj.dev.aidltest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AppService extends Service {
public AppService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return new IAppServiceRemoteBinder.Stub() {
#Override
public void basicTypes(
int anInt, long aLong,
boolean aBoolean, float aFloat,
double aDouble, String aString)
throws RemoteException {
}
#Override
public void setData(String data)
throws RemoteException {
setRealData(data);
}
#Override
public void registerCallback(IRemoteServiceCallback cb)
throws RemoteException {
AppService.this.callback = cb;
}
#Override
public void unregisterCallback(IRemoteServiceCallback cb)
throws RemoteException {
AppService.this.callback = null;
}
};
}
private IRemoteServiceCallback callback;
#Override
public void onCreate() {
super.onCreate();
System.out.println("Service started");
}
#Override
public void onDestroy() {
super.onDestroy();
System.out.println("Service stop");
}
public void setRealData(String data) {
this.data = data;
System.out.println("data = " + data);
try {
Thread.sleep(1000);
if (callback != null) {
callback.vlueChanged(data);
}
} catch (InterruptedException | RemoteException e) {
e.printStackTrace();
}
}
private String data = "default date";
}
And their are two AIDL files:
IAppServiceRemoteBinder.aild
// IAppServiceRemoteBinder.aidl
package com.hqyj.dev.aidltest;
// Declare any non-default types here with import statements
import com.hqyj.dev.aidltest.IRemoteServiceCallback;
interface IAppServiceRemoteBinder {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt,
long aLong,
boolean aBoolean, float aFloat,
double aDouble, String aString);
void setData(String data);
void registerCallback(IRemoteServiceCallback cb);
void unregisterCallback(IRemoteServiceCallback cb);
}
IRemoteServiceCallback.aild
// IRemoteServiceCallback.aidl
package com.hqyj.dev.aidltest;
// Declare any non-default types here with import statements
interface IRemoteServiceCallback {
/**
* return from server
*/
void vlueChanged(String value);
}
And in AndroidManifest.xml, this Server decleared as below:
AndroidManifest.xml
<service
android:name="com.hqyj.dev.aidltest.AppService"
android:enabled="true"
android:exported="true"
android:process=":remote">
</service>
And then, the in second module, copies all these aidl files with package name, as below:
And in MainActivity in anotherapp, complete as below:
package com.hqyj.dev.anotherapp;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.hqyj.dev.aidltest.IAppServiceRemoteBinder;
import com.hqyj.dev.aidltest.IRemoteServiceCallback;
public class MainActivity extends AppCompatActivity
implements View.OnClickListener, ServiceConnection {
private final String TAG = MainActivity.class.getSimpleName();
private Intent intent;
private IAppServiceRemoteBinder binder;
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_start).setOnClickListener(this);
findViewById(R.id.btn_stop).setOnClickListener(this);
findViewById(R.id.btn_set).setOnClickListener(this);
intent = new Intent();
intent.setComponent(new
ComponentName("com.hqyj.dev.aidltest",
"com.hqyj.dev.aidltest.AppService"));
}
#SuppressLint("DefaultLocale")
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
bindService(intent, this,
Context.BIND_AUTO_CREATE);
break;
case R.id.btn_set:
if (binder != null) {
try {
binder.setData(
String.format("the %d times",
++count));
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
case R.id.btn_stop:
try {
binder.unregisterCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
unbindService(this);
break;
}
}
#Override
public void onServiceConnected(
ComponentName name, IBinder service) {
binder =
IAppServiceRemoteBinder.Stub.asInterface(service);
Log.d(TAG, "onServiceConnected: " + 1);
try {
binder.registerCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
private IRemoteServiceCallback.Stub callback =
new IRemoteServiceCallback.Stub() {
#Override
public void
vlueChanged(String value) throws RemoteException {
Log.e(TAG, "vlueChanged: " + value);
}
};
}
As you see, I called the remote service by using bindService();
It works well, when I push these two apps into an emulator which using Android 7.0 as platform.
But
When I push these app into an real device(using Android 6.0), the flowing mistake happened:
AIDL failed!!
Why??