Related
I have designed a code which leads to application not responding.
I have used okhttp3.WebSocket for continuous input stream of data on which i am deciding to start an IntentService which will be fetching data from server.
I have an IntentService; in onHandleIntent i am giving an service call for fetching data from the server(roughly 3 calls).
For Service call i am using AsyncTask of android inside which my WebConnectionManger class runs on different thread.
Inside websocket i am getting details of a particular record for which i am going to fetch the details from the service call.
For 5-6 such records my application runs fine, but if records get 80-100 my application do not respond at all and i get ANR.
I am using simple plain TCP request for this.
can any on tells me what is the actual issue and how i can get rid of it?
any help is appreciated.
i am pasting the code of WebSocket, AsyncTask(rest two have same implementation), WebConnectionManger class and IntentService class.
WebSocket.class
public class WebSocket {
public static boolean isConnected;
public static String TO_UPDATE = "toOrderUpdate";
#SuppressLint("StaticFieldLeak")
private static WebSocket _instance;
private static OkHttpClient client;
private static WebSocket webSocket = null;
private Context mContext;
private AppPreferences preferences;
private WebSocket() {
client = new OkHttpClient();
}
public WebSocket(Context context) {
client = new OkHttpClient();
mContext = context;
preferences = new AppPreferences(mContext);
init(mContext);
}
public static WebSocket getInstance(Context mContext) {
if (_instance == null) {
_instance = new WebSocket(mContext);
}
return _instance;
}
public static void closeWebSocket() {
if (isConnected) {
webSocket.close(1001, LOGOUT);
_instance = null;
webSocket = null;
isConnected = false;
}
}
public void init(Context context) {
if (webSocket == null) {
preferences = new AppPreferences(context);
Request request = new Request.Builder()
.url(preferences.getWSUrl() + ":" + preferences.getWSPort() + "/" + preferences.getUserID())
.build();
WebSocketMessageListener messageListener = new WebSocketMessageListener();
webSocket = client.newWebSocket(request, messageListener);
isConnected = true;
}
}
private class WebSocketMessageListener extends WebSocketListener {
// private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
Log.i("******", "Socket Open");
}
#Override
public void onMessage(WebSocket webSocket, String response) {
try {
super.onMessage(webSocket, response);
Log.i("******", "Message Received " + response);
// Logger.log("OnMessage : " + response);
ModelAdvertisements modelAdvertisements = DecoderJSONWebSocket.decode(response);
Intent intentForService = new Intent(mContext, WebSocketService.class);
int transCode = Integer.parseInt(modelAdvertisements.getTC());
Intent mwBroadcastIntent = new Intent();
switch (transCode) {
case 1005:
mwBroadcastIntent.setAction(Constants.IntentKeys.KEY_LOGICAL_SESSION_START_END);
mContext.sendBroadcast(mwBroadcastIntent);
break;
case 1004:
case 1006:
case 1007:
intentForService.putExtra(TO_UPDATE, true);
mContext.startService(intentForService);
break;
case 1008:
try {
mwBroadcastIntent.putExtra(KEY_AUCTION_FLOOR_SNAPSHOT, modelAdvertisements);
mwBroadcastIntent.setAction(Constants.IntentKeys.KEY_MARKET_DATASNAPSHOT);
mContext.sendBroadcast(mwBroadcastIntent);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
} catch (Exception e) {
// e.printStackTrace();
}
}
#Override
public void onClosing(WebSocket webSockett, int code, String reason) {
super.onClosing(webSockett, code, reason);
Log.i("******", "Socket Closing Reason: " + reason);
}
#Override
public void onClosed(WebSocket webSockett, int code, String reason) {
super.onClosed(webSockett, code, reason);
Log.i("******", "Socket closed reason: " + reason);
webSocket = null;
isConnected = false;
}
#Override
public void onFailure(WebSocket webSockett, Throwable t, Response response) {
super.onFailure(webSockett, t, response);
isConnected = false;
webSocket = null;
Logger.log(e);
}
}
}
WebSocketService.class
public class WebSocketService extends IntentService {
String securityId;
private Context mContext;
private String tokenId;
private String contractCode;
private int transCode;
private boolean toUpdate;
private String mktCode;
public WebSocketService() {
super("WebSocketService");
}
public WebSocketService(String name) {
super(name);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
if (intent != null) {
tokenId = intent.getStringExtra(KEY_TOKEN_ID);
transCode = intent.getIntExtra(KEY_TRANSCODE, 0);
toUpdate = intent.getBooleanExtra(NeMLWebSocket.TO_UPDATE, false);
contractCode = intent.getStringExtra(KEY_SYMBOL);
mktCode = intent.getStringExtra(KEY_ADV_REF_ID);
}
securityId = DatabaseUtils.getSecurityIdFromFOOrders(mContext, tokenId);
performTokenMasterTask();
}
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
protected void performTokenMasterTask() {
synchronized (this) {
TokenMasterTask tokenMasterTask = new TokenMasterTask(mContext, new RequestCallback() {
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
if (transCode == TC_1004_WEB_SOCKET) {
Intent mwBroadcastIntent = new Intent();
mwBroadcastIntent.setAction(Constants.IntentKeys.KEY_TOKEN_SESSION_START_END);
mContext.sendBroadcast(mwBroadcastIntent);
// stopSelf();
} else if (transCode == TC_TIME_WEB_SOCKET || transCode == TC_AUCTION_WEB_SOCKET) {
performTimeSessionTask();
}
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
try {
Logger.log(transCode + "--->" + msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}, mktCode);
tokenMasterTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, tokenId);
if (transCode == TC_TIME_WEB_SOCKET || transCode == TC_AUCTION_WEB_SOCKET) {
performTimeSessionTask();
}
}
}
public void performTimeSessionTask() {
synchronized (this) {
TimeSessionMapTask timeSessionMapTask = new TimeSessionMapTask(mContext, new RequestCallback() {
ProgressDialog progressDialog;
private boolean m_ConnectionErr = false;
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
if (!m_ConnectionErr) {
if (transCode == TC_AUCTION_WEB_SOCKET) {
performFoOrderTask();
}
}
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
try {
Logger.log("Received ErrorMessage :" + msg + " \n ErrorCode :" + transCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}, modelMarket);
timeSessionMapTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, TIME_SESSION);
if (transCode == TC_AUCTION_WEB_SOCKET) {
performFoOrderTask();
}
}
}
private synchronized void performFoOrderTask() {
synchronized (mContext) {
FOOrdersTask foOrdersTask = new FOOrdersTask(mContext, new RequestCallback() {
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
}
});
foOrdersTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, tokenId);
}
}
}
TokenMasterTask.class
public class TokenMasterTask extends AsyncTask<Object, Void, ModelToken> {
private final String mktCode;
private RequestCallback _callback;
#SuppressLint("StaticFieldLeak")
private Context context;
private boolean isConnectionError;
private ModelToken modelToken;
private boolean isServerDown;
public TokenMasterTask(Context context, RequestCallback requestCallback, String mktCode) {
this.context = context;
this.mktCode = mktCode;
if (requestCallback == null) {
requestCallback = new RequestCallback() {
#Override
public void onStart() {
}
#Override
public void onComplete(Object object) {
}
#Override
public void onProgress(int current, int total) {
}
#Override
public void onError(int transCode, String msg) {
}
};
}
this._callback = requestCallback;
}
#Override
protected ModelToken doInBackground(Object... voids) {
if (voids != null && voids.length > 0) {
String tokenId = String.valueOf(voids[0]);
isConnectionError = false;
transactionCall(tokenId);
}
return modelToken;
}
private void transactionCall(String tokenId) {
try {
WebConnectionManager connectionManager = new WebConnectionManager(context, new ConnectionListener() {
#Override
public void notifyReadCompleted(String f_Response) {
modelToken = DecoderTokenRequest.decode(f_Response);
synchronized (TokenMasterTask.this) {
TokenMasterTask.this.notify();
}
}
#Override
public void notifySocketError(boolean isServerDown) {
if (!isServerDown) {
isConnectionError = true;
}
TokenMasterTask.this.isServerDown = isServerDown;
synchronized (TokenMasterTask.this) {
TokenMasterTask.this.notify();
}
}
#Override
public void onReceivePacket(int total, int current) {
_callback.onProgress(current, total);
}
});
connectionManager.modifiedHandleRequest(EncoderTokenRequest.encode(context, tokenId,mktCode).getBytes());
} catch (Exception e) {
e.printStackTrace();
Logger.log(e);
}
synchronized( TokenMasterTask.this) {
try {
TokenMasterTask.this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
protected void onPostExecute(ModelToken modelToken) {
if (isServerDown) {
_callback.onError(Constants.ErrorCode.TC_ERROR_SERVER_DOWN, "");
} else if (isConnectionError) {
_callback.onError(0, "Connection Error.");
} else if (modelToken!=null && modelToken.getErrorCode() != null && !TextUtils.isEmpty(modelToken.getErrorCode()) && !modelToken.getErrorCode().equalsIgnoreCase("200")) {
_callback.onError(Integer.parseInt(modelToken.getErrorCode()), modelToken.getError());
} else {
_callback.onComplete(modelToken);
}
super.onPostExecute(modelToken);
}
}
WebConnectionManager.class
public class WebConnectionManager {
private String m_Response = "";
byte[] m_RequestData;
boolean m_Read_Response_Completed = false;
Thread l_WorkerThread;
ConnectionListener m_ConnectionListener;
boolean m_IsFetchCompleted;
Context context;
AppPreferences preferences;
Socket mWebSocket;
public WebConnectionManager(Context mcontext, ConnectionListener f_LoginListener) {
m_ConnectionListener = f_LoginListener;
m_IsFetchCompleted = false;
context = mcontext;
preferences = new AppPreferences(context);
}
public String modifiedHandleRequest(byte[] f_RequestData) {
m_RequestData = f_RequestData;
Logger.log("" + Constants.TIME_OUT);
l_WorkerThread = new Thread(new Runnable() {
#Override
public void run() {
String encodedIP = null;
try {
if (mWebSocket == null || !mWebSocket.isBound()
|| mWebSocket.isClosed() ) {
mWebSocket = new Socket(ip, port);
mWebSocket.setKeepAlive(true);
mWebSocket.setSoTimeout(Constants.TIME_OUT);
}
if (m_RequestData == null) {
m_Read_Response_Completed = true;
if (!mWebSocket.isClosed()) {
m_ConnectionListener.notifyReadCompleted("Connected");
return;
} else {
m_ConnectionListener.notifyReadCompleted("Disconnected");
return;
}
} else {
String request = new String(m_RequestData);
Logger.log(Utils.encodePackets(request));
}
InputStream inputStream = mWebSocket.getInputStream();
try {
mWebSocket.getOutputStream().write(m_RequestData);
} catch (Exception e) {
Logger.log(e);
}
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(1048576);
byte[] buffer = new byte[1048576];
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
m_Response = byteArrayOutputStream.toString();
}
inputStream.close();
byteArrayOutputStream.close();
mWebSocket.close();
if (TextUtils.isEmpty(m_Response.toString().trim())) {
throw new IOException("Empty Response");
} else {
m_ConnectionListener.notifyReadCompleted(m_Response.toString());
}
} catch (UnknownHostException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
} catch (SocketTimeoutException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(false);
mWebSocket = null;
e.printStackTrace();
} catch (SocketException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
e.printStackTrace();
} catch (IOException e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
e.printStackTrace();
} catch (Exception e) {
Logger.log(e);
m_ConnectionListener.notifySocketError(true);
mWebSocket = null;
e.printStackTrace();
}
}
});
l_WorkerThread.start();
return m_Response;
}
}
And the interfaces.
public interface ConnectionListener {
void notifyReadCompleted(String f_Response);
void notifySocketError(boolean isServerDown);
void onReceivePacket(int total, int current);
}
public interface RequestCallback {
void onStart();
void onComplete(Object object);
void onProgress(int current, int total);
void onError(int transCode, String msg);
}
You may want to check what is blocking the main thread for more than 6 seconds.
Usually ANR happens when main thread is blocked for some time. 6-10 seconds.
Good day everyone, I would like to ask, hat is the cause of that ANR?. In my project I have service which is binded in a activity. Now when I exit in that activity the app is hang for a moment. My thought is that the service is still running though I unbind it in onStop() of the activity.
Here is my service class
public class SpeechService extends Service {
public interface Listener {
/**
* Called when a new piece of text was recognized by the Speech API.
*
* #param text The text.
* #param isFinal {#code true} when the API finished processing audio.
*/
void onSpeechRecognized(String text, boolean isFinal);
}
private static final String TAG = "SpeechService";
private static final String PREFS = "SpeechService";
private static final String PREF_ACCESS_TOKEN_VALUE = "access_token_value";
private static final String PREF_ACCESS_TOKEN_EXPIRATION_TIME = "access_token_expiration_time";
/** We reuse an access token if its expiration time is longer than this. */
private static final int ACCESS_TOKEN_EXPIRATION_TOLERANCE = 30 * 60 * 1000; // thirty minutes
/** We refresh the current access token before it expires. */
private static final int ACCESS_TOKEN_FETCH_MARGIN = 60 * 1000; // one minute
public static final List<String> SCOPE =
Collections.singletonList("https://www.googleapis.com/auth/cloud-platform");
private static final String HOSTNAME = "speech.googleapis.com";
private static final int PORT = 443;
private final SpeechBinder mBinder = new SpeechBinder();
private final ArrayList<Listener> mListeners = new ArrayList<>();
private volatile AccessTokenTask mAccessTokenTask;
private SpeechGrpc.SpeechStub mApi;
private static Handler mHandler;
private final StreamObserver<StreamingRecognizeResponse> mResponseObserver
= new StreamObserver<StreamingRecognizeResponse>() {
#Override
public void onNext(StreamingRecognizeResponse response) {
String text = null;
boolean isFinal = false;
if (response.getResultsCount() > 0) {
final StreamingRecognitionResult result = response.getResults(0);
isFinal = result.getIsFinal();
if (result.getAlternativesCount() > 0) {
final SpeechRecognitionAlternative alternative = result.getAlternatives(0);
text = alternative.getTranscript();
}
}
if (text != null) {
for (Listener listener : mListeners) {
listener.onSpeechRecognized(text, isFinal);
}
}
}
#Override
public void onError(Throwable t) {
Log.e(TAG, "Error calling the API.", t);
}
#Override
public void onCompleted() {
Log.i(TAG, "API completed.");
}
};
private final StreamObserver<RecognizeResponse> mFileResponseObserver
= new StreamObserver<RecognizeResponse>() {
#Override
public void onNext(RecognizeResponse response) {
String text = null;
if (response.getResultsCount() > 0) {
final SpeechRecognitionResult result = response.getResults(0);
if (result.getAlternativesCount() > 0) {
final SpeechRecognitionAlternative alternative = result.getAlternatives(0);
text = alternative.getTranscript();
}
}
if (text != null) {
for (Listener listener : mListeners) {
listener.onSpeechRecognized(text, true);
}
}
}
#Override
public void onError(Throwable t) {
Log.e(TAG, "Error calling the API.", t);
}
#Override
public void onCompleted() {
Log.i(TAG, "API completed.");
}
};
private StreamObserver<StreamingRecognizeRequest> mRequestObserver;
public static SpeechService from(IBinder binder) {
return ((SpeechBinder) binder).getService();
}
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
fetchAccessToken();
}
#Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mFetchAccessTokenRunnable);
mHandler = null;
// Release the gRPC channel.
if (mApi != null) {
final ManagedChannel channel = (ManagedChannel) mApi.getChannel();
if (channel != null && !channel.isShutdown()) {
try {
channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Log.e(TAG, "Error shutting down the gRPC channel.", e);
}
}
mApi = null;
}
}
private void fetchAccessToken() {
if (mAccessTokenTask != null) {
return;
}
mAccessTokenTask = new AccessTokenTask();
mAccessTokenTask.execute();
}
private String getDefaultLanguageCode() {
final Locale locale = Locale.getDefault();
final StringBuilder language = new StringBuilder(locale.getLanguage());
final String country = locale.getCountry();
if (!TextUtils.isEmpty(country)) {
language.append("-");
language.append(country);
}
return language.toString();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void addListener(#NonNull Listener listener) {
mListeners.add(listener);
}
public void removeListener(#NonNull Listener listener) {
mListeners.remove(listener);
}
/**
* Starts recognizing speech audio.
*
* #param sampleRate The sample rate of the audio.
*/
public void startRecognizing(int sampleRate) {
if (mApi == null) {
Log.w(TAG, "API not ready. Ignoring the request.");
return;
}
// Configure the API
mRequestObserver = mApi.streamingRecognize(mResponseObserver);
mRequestObserver.onNext(StreamingRecognizeRequest.newBuilder()
.setStreamingConfig(StreamingRecognitionConfig.newBuilder()
.setConfig(RecognitionConfig.newBuilder()
.setLanguageCode(getDefaultLanguageCode())
.setEncoding(RecognitionConfig.AudioEncoding.LINEAR16)
.setSampleRateHertz(sampleRate)
.build())
.setInterimResults(true)
.setSingleUtterance(true)
.build())
.build());
}
/**
* Recognizes the speech audio. This method should be called every time a chunk of byte buffer
* is ready.
*
* #param data The audio data.
* #param size The number of elements that are actually relevant in the {#code data}.
*/
public void recognize(byte[] data, int size) {
if (mRequestObserver == null) {
return;
}
// Call the streaming recognition API
mRequestObserver.onNext(StreamingRecognizeRequest.newBuilder()
.setAudioContent(ByteString.copyFrom(data, 0, size))
.build());
}
/**
* Finishes recognizing speech audio.
*/
public void finishRecognizing() {
if (mRequestObserver == null) {
return;
}
mRequestObserver.onCompleted();
mRequestObserver = null;
}
/**
* Recognize all data from the specified {#link InputStream}.
*
* #param stream The audio data.
*/
public void recognizeInputStream(InputStream stream) {
try {
mApi.recognize(
RecognizeRequest.newBuilder()
.setConfig(RecognitionConfig.newBuilder()
.setEncoding(RecognitionConfig.AudioEncoding.LINEAR16)
.setLanguageCode("en-US")
.setSampleRateHertz(16000)
.build())
.setAudio(RecognitionAudio.newBuilder()
.setContent(ByteString.readFrom(stream))
.build())
.build(),
mFileResponseObserver);
} catch (IOException e) {
Log.e(TAG, "Error loading the input", e);
}
}
private class SpeechBinder extends Binder {
SpeechService getService() {
return SpeechService.this;
}
}
private final Runnable mFetchAccessTokenRunnable = new Runnable() {
#Override
public void run() {
fetchAccessToken();
}
};
private class AccessTokenTask extends AsyncTask<Void, Void, AccessToken> {
#Override
protected AccessToken doInBackground(Void... voids) {
final SharedPreferences prefs =
getSharedPreferences(PREFS, Context.MODE_PRIVATE);
String tokenValue = prefs.getString(PREF_ACCESS_TOKEN_VALUE, null);
long expirationTime = prefs.getLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, -1);
// Check if the current token is still valid for a while
if (tokenValue != null && expirationTime > 0) {
if (expirationTime
> System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION_TOLERANCE) {
return new AccessToken(tokenValue, new Date(expirationTime));
}
}
// ***** WARNING *****
// In this sample, we load the credential from a JSON file stored in a raw resource
// folder of this client app. You should never do this in your app. Instead, store
// the file in your server and obtain an access token from there.
// *******************
final InputStream stream = getResources().openRawResource(R.raw.credential);
try {
final GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
.createScoped(SCOPE);
final AccessToken token = credentials.refreshAccessToken();
prefs.edit()
.putString(PREF_ACCESS_TOKEN_VALUE, token.getTokenValue())
.putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME,
token.getExpirationTime().getTime())
.apply();
return token;
} catch (IOException e) {
Log.e(TAG, "Failed to obtain access token.", e);
}
return null;
}
#Override
protected void onPostExecute(AccessToken accessToken) {
mAccessTokenTask = null;
final ManagedChannel channel = new OkHttpChannelProvider()
.builderForAddress(HOSTNAME, PORT)
.nameResolverFactory(new DnsNameResolverProvider())
.intercept(new GoogleCredentialsInterceptor(new GoogleCredentials(accessToken)
.createScoped(SCOPE)))
.build();
mApi = SpeechGrpc.newStub(channel);
// Schedule access token refresh before it expires
if (mHandler != null) {
mHandler.postDelayed(mFetchAccessTokenRunnable,
Math.max(accessToken.getExpirationTime().getTime()
- System.currentTimeMillis()
- ACCESS_TOKEN_FETCH_MARGIN, ACCESS_TOKEN_EXPIRATION_TOLERANCE));
}
}
}
/**
* Authenticates the gRPC channel using the specified {#link GoogleCredentials}.
*/
private static class GoogleCredentialsInterceptor implements ClientInterceptor {
private final Credentials mCredentials;
private Metadata mCached;
private Map<String, List<String>> mLastMetadata;
GoogleCredentialsInterceptor(Credentials credentials) {
mCredentials = credentials;
}
#Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
final MethodDescriptor<ReqT, RespT> method, CallOptions callOptions,
final Channel next) {
return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(
next.newCall(method, callOptions)) {
#Override
protected void checkedStart(Listener<RespT> responseListener, Metadata headers)
throws StatusException {
Metadata cachedSaved;
URI uri = serviceUri(next, method);
synchronized (this) {
Map<String, List<String>> latestMetadata = getRequestMetadata(uri);
if (mLastMetadata == null || mLastMetadata != latestMetadata) {
mLastMetadata = latestMetadata;
mCached = toHeaders(mLastMetadata);
}
cachedSaved = mCached;
}
headers.merge(cachedSaved);
delegate().start(responseListener, headers);
}
};
}
/**
* Generate a JWT-specific service URI. The URI is simply an identifier with enough
* information for a service to know that the JWT was intended for it. The URI will
* commonly be verified with a simple string equality check.
*/
private URI serviceUri(Channel channel, MethodDescriptor<?, ?> method)
throws StatusException {
String authority = channel.authority();
if (authority == null) {
throw Status.UNAUTHENTICATED
.withDescription("Channel has no authority")
.asException();
}
// Always use HTTPS, by definition.
final String scheme = "https";
final int defaultPort = 443;
String path = "/" + MethodDescriptor.extractFullServiceName(method.getFullMethodName());
URI uri;
try {
uri = new URI(scheme, authority, path, null, null);
} catch (URISyntaxException e) {
throw Status.UNAUTHENTICATED
.withDescription("Unable to construct service URI for auth")
.withCause(e).asException();
}
// The default port must not be present. Alternative ports should be present.
if (uri.getPort() == defaultPort) {
uri = removePort(uri);
}
return uri;
}
private URI removePort(URI uri) throws StatusException {
try {
return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), -1 /* port */,
uri.getPath(), uri.getQuery(), uri.getFragment());
} catch (URISyntaxException e) {
throw Status.UNAUTHENTICATED
.withDescription("Unable to construct service URI after removing port")
.withCause(e).asException();
}
}
private Map<String, List<String>> getRequestMetadata(URI uri) throws StatusException {
try {
return mCredentials.getRequestMetadata(uri);
} catch (IOException e) {
throw Status.UNAUTHENTICATED.withCause(e).asException();
}
}
private static Metadata toHeaders(Map<String, List<String>> metadata) {
Metadata headers = new Metadata();
if (metadata != null) {
for (String key : metadata.keySet()) {
Metadata.Key<String> headerKey = Metadata.Key.of(
key, Metadata.ASCII_STRING_MARSHALLER);
for (String value : metadata.get(key)) {
headers.put(headerKey, value);
}
}
}
return headers;
}
}
}
and here is my activity class
public class MainActivity extends AppCompatActivity implements MessageDialogFragment.Listener {
private static final String FRAGMENT_MESSAGE_DIALOG = "message_dialog";
private static final String STATE_RESULTS = "results";
private static final int REQUEST_RECORD_AUDIO_PERMISSION = 1;
private SpeechService mSpeechService;
private VoiceRecorder mVoiceRecorder;
private final VoiceRecorder.Callback mVoiceCallback = new VoiceRecorder.Callback() {
#Override
public void onVoiceStart() {
showStatus(true);
if (mSpeechService != null) {
mSpeechService.startRecognizing(mVoiceRecorder.getSampleRate());
}
}
#Override
public void onVoice(byte[] data, int size) {
if (mSpeechService != null) {
mSpeechService.recognize(data, size);
}
}
#Override
public void onVoiceEnd() {
showStatus(false);
if (mSpeechService != null) {
mSpeechService.finishRecognizing();
}
}
};
// Resource caches
private int mColorHearing;
private int mColorNotHearing;
// View references
private TextView mStatus;
private TextView mText, mResult;
private Button editButton, clearButton;
private SharedPreferences settings;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder binder) {
mSpeechService = SpeechService.from(binder);
mSpeechService.addListener(mSpeechServiceListener);
mStatus.setVisibility(View.VISIBLE);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mSpeechService = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
final Resources resources = getResources();
final Resources.Theme theme = getTheme();
mColorHearing = ResourcesCompat.getColor(resources, R.color.status_hearing, theme);
mColorNotHearing = ResourcesCompat.getColor(resources, R.color.status_not_hearing, theme);
mStatus = (TextView) findViewById(R.id.status);
mText = (TextView) findViewById(R.id.text);
mResult = (TextView) findViewById(R.id.resultText);
editButton = (Button)findViewById(R.id.button1);
clearButton = (Button)findViewById(R.id.button2);
settings = getSharedPreferences("MyPreference", Context.MODE_PRIVATE);
clearButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Sounds sounds = new Sounds(getApplicationContext());
if(settings.getBoolean("muteAble", false ) == true){
sounds.playSound();
}
mResult.setText("");
}
});
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Sounds sounds = new Sounds(getApplicationContext());
if(settings.getBoolean("muteAble", false ) == true){
sounds.playSound();
}
Intent editIntent = new Intent(MainActivity.this, EditorActivity.class);
String forEditText = mResult.getText().toString();
editIntent.putExtra("forEdit", forEditText);
startActivity(editIntent);
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
this.finish();
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onStart() {
super.onStart();
// Prepare Cloud Speech API
bindService(new Intent(this, SpeechService.class), mServiceConnection, BIND_AUTO_CREATE);
// Start listening to voices
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
startVoiceRecorder();
} else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.RECORD_AUDIO)) {
showPermissionMessageDialog();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO},
REQUEST_RECORD_AUDIO_PERMISSION);
}
}
#Override
protected void onStop() {
// Stop listening to voice
stopVoiceRecorder();
// Stop Cloud Speech API
mSpeechService.removeListener(mSpeechServiceListener);
unbindService(mServiceConnection);
mSpeechService = null;
super.onStop();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
if (permissions.length == 1 && grantResults.length == 1
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startVoiceRecorder();
} else {
showPermissionMessageDialog();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void startVoiceRecorder() {
if (mVoiceRecorder != null) {
mVoiceRecorder.stop();
}
mVoiceRecorder = new VoiceRecorder(mVoiceCallback);
mVoiceRecorder.start();
}
private void stopVoiceRecorder() {
if (mVoiceRecorder != null) {
mVoiceRecorder.stop();
mVoiceRecorder = null;
}
}
private void showPermissionMessageDialog() {
MessageDialogFragment
.newInstance(getString(R.string.permission_message))
.show(getSupportFragmentManager(), FRAGMENT_MESSAGE_DIALOG);
}
private void showStatus(final boolean hearingVoice) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mStatus.setTextColor(hearingVoice ? mColorHearing : mColorNotHearing);
}
});
}
#Override
public void onMessageDialogDismissed() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO},
REQUEST_RECORD_AUDIO_PERMISSION);
}
private final SpeechService.Listener mSpeechServiceListener =
new SpeechService.Listener() {
#Override
public void onSpeechRecognized(final String text, final boolean isFinal) {
if (isFinal) {
mVoiceRecorder.dismiss();
}
if (mText != null && !TextUtils.isEmpty(text)) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (isFinal) {
mText.setText(null);
mResult.append(" "+text.toString());
} else {
mText.setText(text);
}
}
});
}
}
};
}
Thank in advance for your help
I am trying to integrate the Sinch API in android .
My VOIPClient. Java is like this
public class VOIPClient {
private static final String TAG = "VOIPClient";
private SinchClient mSinch;
private TTSHelper mTTS;
private Call mCurrentCall;
private BootService mContext;
private SinchClientBuilder mBuilder;
private NsdController mNsdController;
private final CallListener mCallListener = new CallListener() {
#Override
public void onCallProgressing(Call call) {
Log.d(TAG, "Call established at " + " Thusee");
}
#Override
public void onCallEstablished(Call call) {
Log.d(TAG, "Call established at " + call.getDetails().getEstablishedTime());
mTTS.speak("Call started", TTSHelper.UTTERANCE_VOIP_START);
JsonObject payload = new JsonObject();
payload.addProperty("Status", 0);
payload.addProperty("Call_status", 1);
if (mNsdController != null) {
mNsdController.sendCommand(20, payload);
}
}
#Override
public void onCallEnded(Call call) {
Log.d(TAG, "Call ended at " + call.getDetails().getEndedTime() + "caused by " + call.getDetails().getEndCause().toString());
mTTS.speak("Call ended", TTSHelper.UTTERANCE_VOIP_END);
mCurrentCall.hangup();
JsonObject payload = new JsonObject();
payload.addProperty("Status", 0);
payload.addProperty("Call_status", 1);
if (mNsdController != null) {
mNsdController.sendCommand(21, payload);
}
}
#Override
public void onShouldSendPushNotification(Call call, List<PushPair> list) {
}
};
public VOIPClient(BootService context) {
mContext = context;
mTTS = TTSHelper.getInstance(context);
mBuilder = Sinch.getSinchClientBuilder().context(mContext.getApplicationContext())
.applicationKey(CloudConfig.SINCH_APP_KEY)
.applicationSecret(CloudConfig.SINCH_APP_SECRET)
.environmentHost(CloudConfig.SINCH_ENVIRONMENT);
if (mNsdController != null)
mNsdController.initialize();
}
public void start() {
SharedPreferences prefs = mContext.getPreferences();
int userId = prefs.getInt(MerryClient.PREF_USER_ID, 0);
String mUserId;
if (userId > 0) {
mUserId = String.valueOf(userId);
mSinch = Sinch.getSinchClientBuilder().context(mContext.getApplicationContext()).userId(mUserId)
.applicationKey(CloudConfig.SINCH_APP_KEY)
.applicationSecret(CloudConfig.SINCH_APP_SECRET)
.environmentHost(CloudConfig.SINCH_ENVIRONMENT).build();
mSinch.setSupportCalling(true);
mSinch.setSupportManagedPush(false);
SinchClientListener sinchClientListener = new SinchClientListener() {
#Override
public void onClientStarted(SinchClient sinchClient) {
Log.d(TAG, "Sinch Client starts: " + sinchClient.getLocalUserId());
mTTS.speak("Call ready", TTSHelper.UTTERANCE_VOIP_READY);
}
#Override
public void onClientStopped(SinchClient sinchClient) {
Log.d(TAG, "Sinch Client stops");
}
#Override
public void onClientFailed(SinchClient sinchClient, SinchError sinchError) {
Log.e(TAG, String.format("Sinch Client error %d: %s", sinchError.getCode(), sinchError.getMessage()));
mSinch.terminate();
mTTS.speak("Voice Over IP failed", TTSHelper.UTTERANCE_VOIP_FAIL);
}
#Override
public void onRegistrationCredentialsRequired(SinchClient sinchClient, ClientRegistration clientRegistration) {
Log.d(TAG, "Sinch Client requires registration");
}
#Override
public void onLogMessage(int i, String s, String s1) {
Log.d(TAG, s1);
}
};
mSinch.addSinchClientListener(sinchClientListener);
mSinch.getCallClient().setRespectNativeCalls(false);
mSinch.getCallClient().addCallClientListener(new SinchCallClientListener());
mCurrentCall = null;
mSinch.startListeningOnActiveConnection();
mSinch.start();
}
}
public void tearDown() {
if (mSinch != null) {
mSinch.stopListeningOnActiveConnection();
mSinch.terminate();
mSinch = null;
}
}
public void restart() {
tearDown();
start();
}
public void initiateCall(final String targetUserName) {
new Thread(new Runnable() {
public void run() {
Looper.prepare();
if (targetUserName != null) {
try {
Call call = callUser(targetUserName);
call.addCallListener(mCallListener);
mCurrentCall = call;
} catch (Exception e) {
Log.e(TAG, "Initiate VOIP call failed", e);
}
}
Looper.loop();
}
}).start();
}
public void answerCall() {
if (mCurrentCall != null) {
mCurrentCall.answer();
}
}
public void hangUpCall() {
if (mCurrentCall != null) {
mCurrentCall.hangup();
}
}
private class SinchCallClientListener implements CallClientListener {
#Override
public void onIncomingCall(CallClient callClient, Call call) {
Log.d(TAG, "Incoming call");
mTTS.speak("Incoming call from " + call.getRemoteUserId(), TTSHelper.UTTERANCE_VOIP_INCOMING);
call.addCallListener(mCallListener);
mCurrentCall = call;
// For testing only
answerCall();
}
}
public Call callUser(String userId) {
if (mSinch != null && mSinch.isStarted()) {
start();
}
if (mSinch == null) {
return null;
}
return mSinch.getCallClient().callUser(userId);
}
class CallerThread implements Runnable {
public String mtargetUserName;
CallerThread(String targetUserName) {
this.mtargetUserName = targetUserName;
}
#Override
public void run() {
Looper.prepare();
if (mtargetUserName != null) {
try {
Call call = callUser(mtargetUserName);
call.addCallListener(mCallListener);
mCurrentCall = call;
} catch (Exception e) {
Log.e(TAG, "Initiate VOIP call failed", e);
mContext.getAlexa().start();
}
}
Looper.loop();
}
}
}
When I try to call to other device then I am getting these kind of exceptions
Initiate VOIP call failed
java.lang.IllegalStateException: SinchClient not started
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.throwUnlessStarted(Unknown Source)
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.call(Unknown Source)
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.callUser(Unknown Source)
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.callUser(Unknown Source)
at tw.com.test.cloud.VOIPClient.callUser(VOIPClient.java:272)
at tw.com.test.cloud.VOIPClient$CallerThread.run(VOIPClient.java:293)
at java.lang.Thread.run(Thread.java:818)
Also some times I am getting this exception
FATAL EXCEPTION: Thread-75
Process: tw.com.test.wear, PID: 1123
java.lang.IllegalThreadStateException: A Looper must be associated with this thread.
at com.sinch.android.rtc.internal.AndroidLooperCallbackHandler.<init>(Unknown Source)
at com.sinch.android.rtc.internal.client.InternalSinchClientFactory.createSinchClient(Unknown Source)
at com.sinch.android.rtc.DefaultSinchClientBuilder.build(Unknown Source)
at tw.com.test.cloud.VOIPClient.start(VOIPClient.java:109)
at tw.com.test.cloud.VOIPClient$2.onClientStopped(VOIPClient.java:124)
at com.sinch.android.rtc.internal.client.DefaultSinchClient.shutdown(Unknown Source)
at com.sinch.android.rtc.internal.client.DefaultSinchClient.terminate(Unknown Source)
at tw.com.test.cloud.VOIPClient.tearDown(VOIPClient.java:160)
at tw.com.test.nsd.NsdController.messageReceived(NsdController.java:570)
at tw.com.test.nsd.NsdConnection.run(NsdConnection.java:115)
at java.lang.Thread.run(Thread.java:818)
2 Days I tried my self, I can't able to solve this yet,
I am always getting these exception. Sometimes it will work for one time then I need to restart the app.
You have to start SinchClient sinchClient.start(); and take NOTE during production mode do not place in a plain text form your SINCH_APP_SECRET, because its a secret key, hackers will easily read or decompile your code.
public VOIPClient(BootService context) {
mContext = context;
mTTS = TTSHelper.getInstance(context);
mBuilder = Sinch.getSinchClientBuilder().context(mContext.getApplicationContext())
.applicationKey(CloudConfig.SINCH_APP_KEY)
.applicationSecret(CloudConfig.SINCH_APP_SECRET)
.environmentHost(CloudConfig.SINCH_ENVIRONMENT);
sinchClient.setSupportCalling(true);
sinchClient.start();
if (mNsdController != null)
mNsdController.initialize();
}
I am currently using okhttp for network calls. I also need websocket so I made it like this:
public class WebSocketService extends Service implements WebSocketListener {
private static final String TAG = "WebSocketService";
private static final String BASE_URL = "ws://192.168.1.39:8080/websocket";
public static final int MSG_RESPONSE = 1;
public static final int MSG_HELLO = 2;
Messenger msger = new Messenger(new MessageHandler());
private WebSocket webSocket;
private boolean mWebSocketOpened = false;
private Messenger replyToMsngr;
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "service oncreate");
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.NANOSECONDS)
.connectTimeout(15000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true)
.build();
Request request = new Request.Builder().url(BASE_URL).build();
WebSocketCall webSocketCall = WebSocketCall.create(okHttpClient, request);
webSocketCall.enqueue(this);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return msger.getBinder(); //using Messenger
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
stopSelf();
return super.onUnbind(intent);
}
#Override
public void onOpen(WebSocket webSocket, Response response) {
Log.i(TAG, "On Open"+response.toString());
this.webSocket = webSocket;
mWebSocketOpened = true;
sendMessage(data);
}
#Override
public void onFailure(IOException e, Response response) {
Log.i(TAG, "onFailure " + e.getMessage());
e.printStackTrace();
mWebSocketOpened = false;
}
#Override
public void onMessage(ResponseBody message) throws IOException {
byte[] bytes = message.bytes();
if(message.contentType()==WebSocket.TEXT){
String newString = new String(bytes);
Message msg = Message.obtain(null, MSG_RESPONSE, 0,0);
msg.replyTo = replyToMsngr;
Bundle bundle = new Bundle();
bundle.putString("rec", newString);
msg.setData(bundle);
try {
replyToMsngr.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
message.close();
}
#Override
public void onPong(Buffer payload) {
Log.i(TAG, "onPong");
}
#Override
public void onClose(int code, String reason) {
mWebSocketOpened = false;
}
public class WebSocketBinder extends Binder{
public WebSocketService getService() {
// Return this instance of LocalService so clients can call public methods
return WebSocketService.this;
}
}
public void sendMessage(String msg){
Log.i(TAG, "sendMessage : "+msg);
if(mWebSocketOpened & webSocket!=null){
try {
RequestBody requestBody = RequestBody.create(WebSocket.TEXT, msg);
webSocket.sendMessage(requestBody);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}else{
Log.e(TAG, "socket not connected");
}
}
//test func
public int getRandomNumber(){
return new Random().nextInt(100);
}
public class MessageHandler extends android.os.Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESPONSE:
Bundle data = msg.getData();
replyToMsngr = msg.replyTo;
WebSocketService.this.sendMessage(data.getString("rec", "No data"));
break;
case MSG_HELLO:
Toast.makeText(getApplicationContext(), "heelo", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
}
But what I need to do is to be able to use STOMP in the web socket like in the example/library https://github.com/NaikSoftware/StompProtocolAndroid
if there is any way/ example to use okhttp along with stomp, it would help me if you mentioned.
Also if the successful implementation of websocket with above mentioned library is needed here is how I implemented it.
public class TestActivity extends AppCompatActivity {
private static final String TAG = "testactivity";
#BindView(R.id.toolbar)
Toolbar toolbar;
#BindView(R.id.ettext)
EditText ettext;
#BindView(R.id.content_test)
RelativeLayout contentTest;
#BindView(R.id.fab)
FloatingActionButton fab;
private StompClient mStompCLient;
private static final String BASE_URL = "ws://192.168.1.39:8080/websocket";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
ButterKnife.bind(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mStompCLient = Stomp.over(WebSocket.class, BASE_URL);
mStompCLient.topic("/topic/greetings").subscribe(topicMessage -> {
Log.d(TAG, topicMessage.getPayload());
});
mStompCLient.send("/app/hello", "{\"userName\":\"abcd\"}").subscribe();
mStompCLient.lifecycle().subscribe(lifecycleEvent -> {
switch (lifecycleEvent.getType()) {
case OPENED:
Log.d(TAG, "Stomp connection opened");
break;
case ERROR:
Log.e(TAG, "Error", lifecycleEvent.getException());
break;
case CLOSED:
Log.d(TAG, "Stomp connection closed");
break;
}
});
mStompCLient.connect();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
JSONObject object = new JSONObject();
try {
object.put("name", ettext.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
Log.i(TAG, "send data : "+ object.toString());
mStompCLient.send("/app/hello", object.toString()).subscribe();
}
});
}
#Override
protected void onStop() {
super.onStop();
disconnectStomp();
}
private void disconnectStomp() {
mStompCLient.disconnect();
}
}
It would also help if anyone can mention the stomp examples using okhttp websocket.
You can now call Stomp.over(okhttp3.WebSocket.class).
We are using qucikblox sdk 2.0 in online consultation mobile application in both platform ios & android. But recently facing issue that if A user device is locked or A user is not using app and if B user calls A user over audio/video A user will not get call.
Case 1-- Device locked app is in foreground User A will be getting a call from user B but user A will not get to know about a call when user A unlock device then only user A can see call notification.
Case 2-- App is in background & device is unlocked User A will not get a audio.video call, evn push message of chats also not receiving
Create a sticky service which will run in background even activity destroy, this service is responsible for QBsession and all other operations so it will detect call in background so you will create Session in service , not in CallActivity. Iam successfully implements this and iam successfully receiving calls in background by this.
public class BloxService extends Service implements QBRTCClientSessionCallbacks {
private QBChatService chatService;
private volatile boolean resultReceived = true;
static final String APP_ID = "";
static final String AUTH_KEY = "";
static final String AUTH_SECRET = "";
static final String ACCOUNT_KEY = "";
private QBRTCClient rtcClient;
public static BloxService bloxService;
private static final String TAG = "BloxService";
public boolean isSessionRunning;
public boolean isCallRunning;
private Date tokenExpirationDate;
private QBAuth qbAuth;
private AppPrefs prefs;
private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
/*boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
String reason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
boolean isFailover = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);*/
NetworkInfo currentNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
//NetworkInfo otherNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
if(currentNetworkInfo!=null && currentNetworkInfo.isConnected()){
if(!QBChatService.getInstance().isLoggedIn()){
if(!isSessionRunning) {
initializeQb();
}
}
}
}
};
#Override
public void onCreate() {
super.onCreate();
// prefs = AppPrefs.getInstance(getApplicationContext()); // for testing we put this line on start
registerReceiver(this.mConnReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("bloxservice","onDestroy");
try{
unregisterReceiver(mConnReceiver);
}catch (Exception e){
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
prefs = AppPrefs.getInstance(getApplicationContext());
if (prefs.getData(IS_USER_LOGIN, false)) {
Log.d("bloxservice","start");
try {
if (!QBChatService.getInstance().isLoggedIn()) {
initializeQb();
}
}catch (Exception e)
{
initializeQb();
}
bloxService=this;
}
else {
stopSelf();
}
return START_STICKY;
}
public static BloxService getBloxService() {
return bloxService;
}
public void initializeQb(){
QBSettings.getInstance().init(getApplicationContext(), APP_ID, AUTH_KEY, AUTH_SECRET);
QBSettings.getInstance().setAccountKey(ACCOUNT_KEY);
QBChatService.setDebugEnabled(true);
// added on 20 july
QBChatService.setDefaultAutoSendPresenceInterval(60);
QBChatService.ConfigurationBuilder chatServiceConfigurationBuilder = new QBChatService.ConfigurationBuilder();
chatServiceConfigurationBuilder.setSocketTimeout(60); //Sets chat socket's read timeout in seconds
chatServiceConfigurationBuilder.setKeepAlive(true); //Sets connection socket's keepAlive option.
QBChatService.setConfigurationBuilder(chatServiceConfigurationBuilder);
// QBChatService.getInstance().startAutoSendPresence(10);// added on 20 july
chatService = QBChatService.getInstance();
/* tokenExpirationDate = qbAuth.getTokenExpirationDate();
try {
String Token= QBAuth.getSession().toString();
QBAuth.createFromExistentToken()
} catch (QBResponseException e) {
e.printStackTrace();
}
*/
if(AppPrefs.getInstance(this).getData(Constants.PrefsConstatnt.IS_USER_LOGIN,false)){
Log.e("Login Process", "Started");
isSessionRunning=true;
String userId=AppPrefs.getInstance(this).getData(Constants.PrefsConstatnt.USER_ID,"");
String name=AppPrefs.getInstance(this).getData(Constants.PrefsConstatnt.USER_NAME,"");
String picUrl=AppPrefs.getInstance(this).getData(Constants.PrefsConstatnt.USER_IMAGE,"");
String phone=prefs.getData(Constants.PrefsConstatnt.USER_PHONE, "");
if(name.isEmpty()){
name=userId;
}
createAppSession(Integer.parseInt(userId)<10?"0"+userId:userId,name,userId,picUrl,phone);
}
}
private void createAppSession(final String userId, final String name,final String exId,final String picUrl,final String phone) {
QBAuth.createSession(new QBEntityCallback<QBSession>() {
#Override
public void onSuccess(QBSession qbSession, Bundle bundle) {
loadUsers(userId, name, exId,picUrl,phone);
final SharedPreferences prefs = getGCMPreferences(getApplicationContext());
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
}
// Subscribe to Push Notifications
//subscribeToPushNotifications(registrationId);
}
#Override
public void onError(QBResponseException exc) {
exc.printStackTrace();
isSessionRunning=false;
}
});
}
//QBUser users;
public void loadUsers(String userId,String name,String exId,String picUrl,String phone) {
final QBUser userr = new QBUser(userId, DataHolder.PASSWORD);
userr.setFullName(name);
userr.setExternalId(exId);
userr.setCustomData(picUrl);
userr.setPhone(phone);
QBUsers.signUp(userr, new QBEntityCallback<QBUser>() {
#Override
public void onSuccess(QBUser user, Bundle args) {
createSession(userr.getLogin(), userr.getPassword());
}
#Override
public void onError(QBResponseException error) {
error.printStackTrace();
QBUsers.signIn(userr, new QBEntityCallback<QBUser>() {
#Override
public void onSuccess(QBUser user, Bundle args) {
createSession(userr.getLogin(), userr.getPassword());
}
#Override
public void onError(QBResponseException error) {
error.printStackTrace();
isSessionRunning = false;
}
});
}
});
}
private void createSession(final String login, final String password) {
final QBUser user = new QBUser(login, password);
QBAuth.createSession(login, password, new QBEntityCallback<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle bundle) {
user.setId(session.getUserId());
Log.e("User" + session.getUserId(), "Login");
QBSettings.getInstance().fastConfigInit(APP_ID, AUTH_KEY, AUTH_SECRET);
sendRegistrationToServer(AppPrefs.getInstance(BloxService.this).getData(Constants.PrefsConstatnt.DEVICE_TOKEN, ""));
DataHolder.setLoggedUser(user);
if (chatService.isLoggedIn()) {
resultReceived = true;
initQBRTCClient();
isSessionRunning = false;
} else {
chatService.login(user, new QBEntityCallback<Void>() {
#Override
public void onSuccess(Void result, Bundle bundle) {
initQBRTCClient();
resultReceived = true;
isSessionRunning = false;
}
#Override
public void onError(QBResponseException exc) {
resultReceived = true;
isSessionRunning = false;
}
});
}
/* QBRosterListener rosterListener = new QBRosterListener() {
#Override
public void entriesDeleted(Collection<Integer> userIds) {
Log.d("mayanks","changed");
}
#Override
public void entriesAdded(Collection<Integer> userIds) {
Log.d("mayanks","changed");
}
#Override
public void entriesUpdated(Collection<Integer> userIds) {
Log.d("mayanks","changed");
}
#Override
public void presenceChanged(QBPresence presence) {
Log.d("mayanks","changed");
}
};
QBSubscriptionListener subscriptionListener = new QBSubscriptionListener() {
#Override
public void subscriptionRequested(int userId) {
}
};
QBRoster chatRoster = QBChatService.getInstance().getRoster(QBRoster.SubscriptionMode.mutual, subscriptionListener);
chatRoster.addRosterListener(rosterListener);
Collection<QBRosterEntry> entries = chatRoster.getEntries();
QBPresence presence = chatRoster.getPresence(9);
if (presence!=null) {
if (presence.getType() == QBPresence.Type.online) {
Log.d("mayanks","online");
// User is online
}else{
Log.d("mayanks","offline");
// User is offline
}
}*/
}
#Override
public void onError(QBResponseException exc) {
resultReceived = true;
isSessionRunning = false;
}
});
}
private void sendRegistrationToServer(final String token) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
final SharedPreferences prefs = getGCMPreferences(getApplicationContext());
String deviceID = prefs.getString(PROPERTY_DEVICE_ID, null);
if(deviceID==null)
{
deviceID=DeviceUtils.getDeviceUid();
storeDeviceId(getApplicationContext(),deviceID);
}
QBSubscription qbSubscription = new QBSubscription();
qbSubscription.setNotificationChannel(QBNotificationChannel.GCM);
qbSubscription.setDeviceUdid(deviceID);
qbSubscription.setRegistrationID(token);
qbSubscription.setEnvironment(QBEnvironment.DEVELOPMENT); // Don't forget to change QBEnvironment to PRODUCTION when releasing application
QBPushNotifications.createSubscription(qbSubscription,
new QBEntityCallback<ArrayList<QBSubscription>>() {
#Override
public void onSuccess(ArrayList<QBSubscription> qbSubscriptions, Bundle bundle) {
Log.e(TAG, "Successfully subscribed for QB push messages");
//saveGcmRegIdToPreferences(gcmRegId);
isSessionRunning=false;
}
#Override
public void onError(QBResponseException error) {
Log.e(TAG, "Unable to subscribe for QB push messages; " + error.toString());
isSessionRunning=false;
}
});
}
});
}
#Override
public void onReceiveNewSession(final QBRTCSession qbrtcSession) {
Log.d("bloxservice","CallRecive");
new Handler().post(new Runnable() {
#Override
public void run() {
if(!isCallRunning) {
DataHolder.incomingSession = qbrtcSession;
/* Map<String,String> userInfo = qbrtcSession.getUserInfo();
String s=userInfo.get("mayank");*/
Intent intent = new Intent(BloxService.this, CallActivity.class);
intent.putExtra("incoming", true);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
else{
Log.e("User","Busy");
}
}
});
}
#Override
public void onUserNotAnswer(QBRTCSession qbrtcSession, Integer integer) {
// ToastUtil.showShortToast(this, "no answer");
}
#Override
public void onCallRejectByUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {
// ToastUtil.showShortToast(this,"rejected");
}
#Override
public void onCallAcceptByUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {
//ToastUtil.showShortToast(this,"accepted");
}
#Override
public void onReceiveHangUpFromUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {
}
#Override
public void onUserNoActions(QBRTCSession qbrtcSession, Integer integer) {
// ToastUtil.showShortToast(this,"no Action");
}
#Override
public void onSessionClosed(QBRTCSession qbrtcSession) {
// ToastUtil.showShortToast(this,"onSessionClosed");
}
#Override
public void onSessionStartClose(QBRTCSession qbrtcSession) {
// ToastUtil.showShortToast(this,"onSessionStartClose");
}
private void initQBRTCClient() {
rtcClient = QBRTCClient.getInstance(this);
QBVideoChatWebRTCSignalingManager qbChatService = QBChatService.getInstance().getVideoChatWebRTCSignalingManager();
if (qbChatService != null) {
qbChatService.addSignalingManagerListener(new QBVideoChatSignalingManagerListener() {
#Override
public void signalingCreated(QBSignaling qbSignaling, boolean createdLocally) {
if (!createdLocally) {
rtcClient.addSignaling((QBWebRTCSignaling) qbSignaling);
}
}
});
QBRTCConfig.setMaxOpponentsCount(2);
QBRTCConfig.setDisconnectTime(40);
QBRTCConfig.setAnswerTimeInterval(30l);
QBRTCConfig.setDebugEnabled(true);
rtcClient.addSessionCallbacksListener(this);
rtcClient.prepareToProcessCalls();
QBChatService.getInstance().addConnectionListener(new AbstractConnectionListener() {
#Override
public void connectionClosedOnError(Exception e) {
}
#Override
public void reconnectionSuccessful() {
}
#Override
public void reconnectingIn(int seconds) {
}
});
}
}
public void logout(){
chatService.logout(new QBEntityCallback<Void>() {
#Override
public void onSuccess(Void result, Bundle bundle) {
}
#Override
public void onError(QBResponseException list) {
}
});
}
/* public void subscribeToPushNotifications(String registrationID) {
QBSubscription subscription = new QBSubscription(QBNotificationChannel.GCM);
subscription.setEnvironment(QBEnvironment.DEVELOPMENT);
//
String deviceId;
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(
Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null) {
deviceId = mTelephony.getDeviceId(); /*//*** use for mobiles
} else {
deviceId = Settings.Secure.getString(getContentResolver(),
Settings.Secure.ANDROID_ID); /*//*** use for tablets
}
subscription.setDeviceUdid(deviceId);
//
subscription.setRegistrationID(registrationID);
//
QBPushNotifications.createSubscription(subscription, new QBEntityCallback<ArrayList<QBSubscription>>() {
#Override
public void onSuccess(ArrayList<QBSubscription> subscriptions, Bundle args) {
Log.d("push_send","sucess");
}
#Override
public void onError(QBResponseException error) {
Log.d("push_send","sucess");
}
});
}*/
private SharedPreferences getGCMPreferences(Context context) {
// This sample app persists the registration ID in shared preferences,
// but
// how you store the regID in your app is up to you.
Log.e("getGCMPreferences", "package= " + context.getPackageName());
return getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
}
private void storeDeviceId(Context context, String deviceId) {
final SharedPreferences prefs = getGCMPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_DEVICE_ID, deviceId);
editor.commit();
}
}