isGestureDetectionAvailable() always returns false. I looked this issue up here on SO, and all those who faced the same problem in the past few years haven't received an answer or got it solved. Here and Here And everywhere else. There will be a 50 points reward for the correct answer as a token of appreciation.
AndroidManifest.xml
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<service
android:enabled="true"
android:name="helpers.FingerprintSVC"
android:label="#string/app_name"
android:accessibilityFlags="flagDefault|flagRequestFingerprintGestures"
android:canRequestFingerprintGestures="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/accessibility_service_config" />
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
FingerprintSVC
public class FingerprintSVC extends AccessibilityService {
private static final String TAG = "++++";
#Override
public int onStartCommand(Intent aIntent, int aFlags, int aStartId){
super.onStartCommand(aIntent, aFlags, aStartId);
Log.d(TAG, "onStartCommand");
if(!isAccessibilityServiceEnabled(this, this.getClass())){
Toast toast= Toast.makeText(this, "Enable A.SVC", Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP|Gravity.FILL_HORIZONTAL, 0, 0);
toast.show();
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
return START_STICKY;
}
#Override
public void onCreate(){
super.onCreate();
Log.d(TAG, "onCreate");
}
#Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
Log.d(TAG, "onAccessibilityEvent");
}
#Override
public void onInterrupt() {
Log.d(TAG, "onInterrupt");
}
#Override
protected boolean onGesture(int gestureId) {
Log.d(TAG, "onGesture " + gestureId);
return super.onGesture(gestureId);
}
#Override
protected boolean onKeyEvent(KeyEvent event) {
Log.d(TAG, "onKeyEvent " + event.getKeyCode());
return super.onKeyEvent(event);
}
#Override
public void onDestroy() {
Toast.makeText(getApplicationContext(), "onDestroy" , Toast.LENGTH_SHORT).show();
super.onDestroy();
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.d(TAG, "onServiceConnected");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
FingerprintGestureController gestureController = getFingerprintGestureController();
Toast.makeText(getApplicationContext(), "Is available: " + gestureController.isGestureDetectionAvailable(), Toast.LENGTH_LONG).show();
Log.e(TAG, "Is available: " + gestureController.isGestureDetectionAvailable() );
FingerprintGestureController.FingerprintGestureCallback callback = new
FingerprintGestureController.FingerprintGestureCallback() {
#Override
public void onGestureDetectionAvailabilityChanged(boolean available) {
super.onGestureDetectionAvailabilityChanged(available);
Toast.makeText(getApplicationContext(), "Gesture available change to: " + available, Toast.LENGTH_SHORT).show();
Log.d(TAG, "onGestureDetectionAvailabilityChanged " + available);
}
#Override
public void onGestureDetected(int gesture) {
super.onGestureDetected(gesture);
Toast.makeText(getApplicationContext(), "Gesture: " + gesture, Toast.LENGTH_SHORT).show();
Log.d(TAG, "onGestureDetected " + gesture);
}
};
gestureController.registerFingerprintGestureCallback(callback, new Handler());
}
}
#Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind " );
return super.onUnbind(intent);
}
public boolean isAccessibilityServiceEnabled(Context context, Class<?> accessibilityService) {
ComponentName expectedComponentName = new ComponentName(context, accessibilityService);
String enabledServicesSetting = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (enabledServicesSetting == null)
return false;
TextUtils.SimpleStringSplitter colonSplitter = new TextUtils.SimpleStringSplitter(':');
colonSplitter.setString(enabledServicesSetting);
while (colonSplitter.hasNext()) {
String componentNameString = colonSplitter.next();
ComponentName enabledService = ComponentName.unflattenFromString(componentNameString);
if (enabledService != null && enabledService.equals(expectedComponentName))
return true;
}
return false;
}
}
build.gradle
android {
compileSdkVersion 30
buildToolsVersion '29.0.3'
defaultConfig {
applicationId "com.xxxx.xxxx"
minSdkVersion 26
targetSdkVersion 30
}
I'm testing on Samsung M11 powered by Android 10. I don't have other devices to test on.
Related
I have a simple application that collects locations. it works without for some minutes or hours but if I disconnect or loose Internet connection, or for disable/enable GPS 4-5 or more times, it not sends connection updates anymore. and I have to restart phone most times or kill that app and start it again (some times not works again after restart) to get locations again.
My application have a simple activity and a service for running in foreground and collection and sending them to server.
Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shetapp.ranandeg">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="mydefaultnotificationchannel" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyLocationTrackerService"
android:enabled="true"
android:exported="true" />
<service android:name=".MyFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
This is my activity :
public class MainActivity extends AppCompatActivity {
private final String TAG = "myapp-ma";
public static final String _TAG = "myapp-ma";
public static Context context;
private WebView webViewBrowser;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: main activity created.");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
loadPrefs(getApplicationContext());
getControles();
setBrowser();
startService(new Intent(this , MyLocationTrackerService.class));
}
#Override
protected void onDestroy() {
Log.d(TAG, "onDestroy: main activity destroyed.");
super.onDestroy();
}
#Override
protected void onResume() {
Log.d(TAG, "onResume: main activity resumed.");
super.onResume();
loadPrefs(getApplicationContext());
startService(new Intent(this , MyLocationTrackerService.class));
}
public void loadPrefs(Context context) {
Log.d(TAG, "loadPrefs: fired!");
SharedPreferences pref = getApplicationContext().getSharedPreferences(AppConfig.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
MyLocationTrackerService.USER_TOKEN = pref.getString(AppConfig.SHARED_PREFERENCES_USER_TOKEN , "xxx");
}
protected void getControles() {
Log.d(TAG, "getControles: fired!");
webViewBrowser = (WebView) findViewById(R.id.activity_main_webViewBrowser);
WebAppInterface.wv = webViewBrowser;
}
protected void setBrowser() {
webViewBrowser.addJavascriptInterface(new WebAppInterface(this), "NativeInterface");
WebSettings webSettings = webViewBrowser.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webViewBrowser.setWebViewClient(new MyWebViewClient());
webViewBrowser.setWebChromeClient(new MyWebChromeClient());
webViewBrowser.loadUrl("file:///android_asset/www/index.html");
}
#Override
public void onBackPressed() {
if(webViewBrowser.canGoBack() == true) {
webViewBrowser.goBack();
} else {
MainActivity.super.onBackPressed();
}
}
}
Location tracker service :
public class MyLocationTrackerService extends Service
{
private static final String TAG = "myapp-mlts";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1 * 60 * 1000; // MINUTES*60*1000
private static final float LOCATION_DISTANCE = 0f; // 100f;
public static String USER_TOKEN = "";
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";
private BroadcastReceiver mRegistrationBroadcastReceiver;
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;
public LocationListener(String provider)
{
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location)
{
Log.d(TAG, "onLocationChanged: location change detected , "+location.getProvider());
mLastLocation.set(location);
updateServerLocation(getApplication() , location , AppConfig.SERVER_IP , MyLocationTrackerService.USER_TOKEN);
}
#Override
public void onProviderDisabled(String provider)
{
Log.d(TAG, "LocationListener onProviderDisabled , "+provider);
}
#Override
public void onProviderEnabled(String provider)
{
Log.d(TAG, "LocationListener onProviderEnabled , "+provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.d(TAG, "LocationListener onStatusChanged , " + provider);
}
protected void updateServerLocation(Context context, final Location location , final String ip , final String userToken)
{
Log.d(TAG, "LocationListener updateServerLocation, token/server : "+userToken+"/"+ip);
if(ip.equals("")){
Log.d(TAG , "ip of server is empty string. returned.");
} else if(!isConnected()){
Log.d(TAG, "updateServerLocation: not connected!");
} else if(userToken.length() < 1){
Log.d(TAG, "updateServerLocation: userToken.length() < 1 , userToken is : "+userToken);
} else {
String url = ip + "/app/ranande/location";
StringRequest request = new StringRequest(
Request.Method.POST,
url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try{
Log.d(TAG, "onResponse: " + response);
} catch (Exception e){
Log.d(TAG, "onResponse: " + e.getMessage().toString());
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse: " + error.toString());
}
}
){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
String token = userToken;
if( token.equals(null) || token.equals("") ){
Log.d(TAG , "token is empty string, returned.");
}
params.put("token", token);
params.put("latitude", String.valueOf(location.getLatitude()));
params.put("longitude", String.valueOf(location.getLongitude()));
return params;
}
};
VolleyController.getInstance(context).addToRequestQueue(request);
}
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "MyLocationTrackerService onStartCommand fired.");
startForeground();
try{
Log.d(TAG, "MyLocationTrackerService onStartCommand: token/ip are "+MyLocationTrackerService.USER_TOKEN+"/"+AppConfig.SERVER_IP);
} catch (Exception ex){
Log.d(TAG, "onStartCommand: Exception! : "+ex.toString());
}
try{
super.onStartCommand(intent, flags, startId);
} catch (Exception ex){
Log.e(TAG, "onStartCommand: Exception on calling super.onStartCommand," +ex.toString());
}
return START_STICKY;
}
#Override
public void onCreate()
{
Log.d(TAG, "MyLocationTrackerService created.");
initializeLocationManager();
try {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//use checkSelfPermission()
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} else {
//simply use the required feature
//as the user has already granted permission to them during installation
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
}
} catch (java.lang.SecurityException ex) {
Log.d(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.d(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
#Override
public void onDestroy()
{
Log.d(TAG, "MyLocationTrackerService destroyed.");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.d(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
try{
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
} catch (Exception ex) {
Log.d(TAG, "initializeLocationManager: error : "+ex.toString());
}
}
public Boolean isConnected(){
ConnectivityManager connectivityManager = (ConnectivityManager)getApplicationContext().getSystemService(MainActivity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isConnected()){
return true;
}
return false;
}
private void startForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // don't forget create a notification channel first
.setOngoing(true)
.setContentTitle(getString(R.string.app_name))
.setContentText("running ...")
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.globe)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round))
.build());
}
}
After restart phone, my application works without any issue, some times I have to kill the Application from application manager and run it again but some times I have to restart the phone.
I think maybe there is an bug with phones GPS or android OS not mine App.
IS THERE ANY ERROR IN MY CODE? or how I could change and solve this problem? Is it good idea to use fuse/google service instead?
I use quickblox for create video call
Start call work, but incoming service not work for opponent user
VideoActivity
public class VideoActivity extends E implements QBRTCClientSessionCallbacks,QBRTCClientVideoTracksCallbacks {
private int userid;
private Boolean isOutgoing,micE=true,vidE=true;
private QBRTCSurfaceView surfaceView,remoteview;
private MediaPlayer mp;
private QBRTCSession currentsession;
private QBMediaStreamManager mediaStreamManager;
private ImageView mic,video;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video);
userid=getIntent().getIntExtra("user", 1);
userid = 39753771;
isOutgoing=getIntent().getBooleanExtra("isoutgoing",false);
isOutgoing = true;
ProcessCalls();
InitSignalling();
if (isOutgoing) {
//CallUser();
SetCallerName(userid);
}
Log.i("errorCheck", "Nz: " + userid);
Log.i("errorCheck", "Na: " + isOutgoing);
if(getIntent().getBooleanExtra("service",false)){
Log.i("errorCheck", "x");
}
mic=(ImageView)findViewById(R.id.mic);
mic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (micE) {
micE = false;
AudioManage();
} else {
micE = true;
AudioManage();
}
}
});
video=(ImageView)findViewById(R.id.video);
video.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (vidE) {
vidE = false;
VideoManage();
} else {
vidE = true;
VideoManage();
}
}
});
surfaceView =(QBRTCSurfaceView)findViewById(R.id.localView);
surfaceView.setMirror(true);
surfaceView.requestLayout();
remoteview=(QBRTCSurfaceView)findViewById(R.id.opponentView);
remoteview.requestLayout();
}
private void SetCallerName(Integer callerID) {
TextView callerName=(TextView)findViewById(R.id.callername);
TextView callertime=(TextView)findViewById(R.id.callTime);
callerName.setText(callerID + " , You:");
if(isOutgoing){
callertime.setText("Calling...");
}
}
private void InitSignalling() {
final QBChatService chatService = QBChatService.getInstance();
Log.i("errorCheck", "ERR1: " + G.userQB);
chatService.login(G.userQB, new QBEntityCallback() {
#Override
public void onSuccess(Object result, Bundle params) {
Log.i("errorCheck", "R0: " + result);
Log.i("errorCheck", "R1: " + params);
chatService.getVideoChatWebRTCSignalingManager().addSignalingManagerListener(new QBVideoChatSignalingManagerListener() {
#Override
public void signalingCreated(QBSignaling qbSignaling, boolean createdLocally) {
Log.i("errorCheck", "Q1: " + qbSignaling);
Log.i("errorCheck", "Q2: " + createdLocally);
if (!createdLocally) {
QBRTCClient.getInstance(VideoActivity.this).addSignaling((QBWebRTCSignaling) qbSignaling);
}
}
});
QBRTCClient.getInstance(G.currentActivity).addSessionCallbacksListener((QBRTCSessionEventsCallback) G.currentActivity);
QBRTCConfig.setDebugEnabled(true);
QBRTCClient.getInstance(getApplicationContext()).prepareToProcessCalls();
Log.i("errorCheck", "chatService1: " + chatService);
if(G.userMobile.equals("09139479548")) {
CallUser();
}
}
#Override
public void onError(QBResponseException errors) {
Log.i("errorCheck", "E1: " + errors);
}
});
}
private void ProcessCalls() {
QBRTCClient.getInstance(this).prepareToProcessCalls();
}
private void CallUser() {
List<Integer> opponents = new ArrayList<Integer>();
opponents.add(userid);
Map<String, String> userInfo = new HashMap<>();
userInfo.put("key", "value");
QBRTCTypes.QBConferenceType qbConferenceType = QBRTCTypes.QBConferenceType.QB_CONFERENCE_TYPE_VIDEO;
QBRTCSession session = QBRTCClient.getInstance(G.currentActivity).createNewSessionWithOpponents(opponents, qbConferenceType);
session.addVideoTrackCallbacksListener(this);
session.startCall(userInfo);
Log.i("errorCheck", "QR1: " + session);
SetCallButtonsDialing(session,userInfo);
StartDialRinging();
}
#Override
public void onReceiveNewSession(QBRTCSession qbrtcSession) {
Log.i("errorCheck","x");
qbrtcSession.addVideoTrackCallbacksListener(this);
Map<String,String> userInfo = qbrtcSession.getUserInfo();
SetLayoutForReceiveCall(qbrtcSession,userInfo);
}
private void SetLayoutForReceiveCall(final QBRTCSession qbrtcSession,final Map<String, String> userInfo) {
final FrameLayout receive=(FrameLayout)findViewById(R.id.answerlayout);
receive.setVisibility(View.VISIBLE);
qbrtcSession.addVideoTrackCallbacksListener(this);
final ImageView calll=(ImageView)findViewById(R.id.answerCall);
calll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Accept incoming call
qbrtcSession.acceptCall(userInfo);
receive.setVisibility(View.GONE);
SetCallButtonsDialing(qbrtcSession, userInfo);
StartTimer();
if (mp != null && mp.isPlaying()) {
mp.stop();
}
}
});
findViewById(R.id.rejectcall).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
qbrtcSession.rejectCall(userInfo);
VideoActivity.this.finish();
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
}
});
}
#Override
public void onUserNoActions(QBRTCSession qbrtcSession, Integer integer) {
Toast.makeText(this, "no action by user", Toast.LENGTH_SHORT).show();
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
}
#Override
public void onSessionStartClose(QBRTCSession qbrtcSession) {
qbrtcSession.addVideoTrackCallbacksListener(this);
try {
qbrtcSession.getMediaStreamManager().setVideoCapturer(new QBRTCCameraVideoCapturer(this, null));
mediaStreamManager = qbrtcSession.getMediaStreamManager();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onUserNotAnswer(QBRTCSession qbrtcSession, Integer integer) {
Toast.makeText(this, "No answer", Toast.LENGTH_SHORT).show();
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
finish();
}
#Override
public void onCallRejectByUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {
Toast.makeText(this, "Call rejected", Toast.LENGTH_SHORT).show();
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
finish();
}
#Override
public void onCallAcceptByUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {
qbrtcSession.addVideoTrackCallbacksListener(this);
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
StartTimer();
}
#Override
public void onReceiveHangUpFromUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
Toast.makeText(this, "Call ended by user", Toast.LENGTH_SHORT).show();
finish();
}
#Override
public void onSessionClosed(QBRTCSession qbrtcSession) {
if(mp!=null&&mp.isPlaying())
{
mp.stop();
}
}
#Override
public void onLocalVideoTrackReceive(QBRTCSession qbrtcSession, QBRTCVideoTrack qbrtcVideoTrack) {
Log.i("errorCheck", "WW1: " + qbrtcSession);
qbrtcVideoTrack.addRenderer(new VideoRenderer(surfaceView));
surfaceView.setMirror(true);
surfaceView.requestLayout();
}
#Override
public void onRemoteVideoTrackReceive(QBRTCSession qbrtcSession, QBRTCVideoTrack qbrtcVideoTrack, Integer integer) {
Log.i("errorCheck", "WW2: " + qbrtcSession);
qbrtcVideoTrack.addRenderer(new VideoRenderer(remoteview));
mediaStreamManager = qbrtcSession.getMediaStreamManager();
remoteview.requestLayout();
}
public void StartDialRinging(){
try {
mp = MediaPlayer.create(getApplicationContext(), R.raw.beep);
mp.setLooping(true);
mp.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
VideoCallService
public class VideoCallService extends Service implements QBRTCClientSessionCallbacks {
private Timer mTimer = null;
private Handler mHandler = new Handler();
public static final int notify = 300000;
public VideoCallService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Log.wtf("service", "start");
if (mTimer != null) {
Log.wtf("service", "All ready started");
} else {
mTimer = new Timer(); //recreate new
mTimer.scheduleAtFixedRate(new TimeDisplay(), 0, notify);
LoginChatService();
ProcessCalls();
InitSignalling();
QBRTCClient.getInstance(this).addSessionCallbacksListener(this);
}
}catch (Exception e){
Log.wtf("ex",""+e);
}
return START_NOT_STICKY;
}
private void InitSignalling() {
QBChatService.getInstance().getVideoChatWebRTCSignalingManager()
.addSignalingManagerListener(new QBVideoChatSignalingManagerListener() {
#Override
public void signalingCreated(QBSignaling qbSignaling, boolean createdLocally) {
if (!createdLocally) {
QBRTCClient.getInstance(VideoCallService.this).addSignaling((QBWebRTCSignaling) qbSignaling);
}
}
});
}
private void ProcessCalls() {
QBRTCClient.getInstance(this).prepareToProcessCalls();
}
#Override
public void onReceiveNewSession(QBRTCSession qbrtcSession) {
//DataHolder.getInstance().setServiceData(qbrtcSession,qbrtcSession.getUserInfo());
startActivity(new Intent(this,VideoActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("service",true));
}
}
Manifest
<service
android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name=".VideoCallService" />
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.quickblox.sample.groupchatwebrtc" />
</intent-filter>
</receiver>
<service
android:name=".GcmPushListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name="com.quickblox.messages.services.gcm.QBGcmPushInstanceIDService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<meta-data android:name="com.quickblox.messages.TYPE" android:value="GCM" />
<meta-data android:name="com.quickblox.messages.SENDER_ID" android:value="1" />
<meta-data android:name="com.quickblox.messages.QB_ENVIRONMENT" android:value="DEVELOPMENT" />
After start Call, session created for opponent
This my log for user caller
I/org.webrtc.Logging: SurfaceViewRenderer: localView: onMeasure(). New size: 200x200
I/org.webrtc.Logging: EglRenderer: localView: setLayoutAspectRatio: 1.0
I/org.webrtc.Logging: EglRenderer: opponentView: setLayoutAspectRatio: 0.58536583
D/QBASDK: register network listener
D/QBASDK: Connected. Login to chat, currentUser JID: 39753009-65649, resource: android_ffffffff-ac04-0c2d-ffff-ffffd173e4c0
I/errorCheck: R0: null
I/errorCheck: R1: Bundle[{}]
D/RTCClient.: Added session CALLBACK listenerapp.x.y.VideoActivity#4288e7f8
I/errorCheck: chatService1: com.quickblox.chat.QBChatService#42f6b478
D/RTCClient.: Call createNewSessionWithOpponents[39753771]conference type=QBConferenceType{value='1'}
D/RTCClient.QBRTCSession: Create new session
I/errorCheck: Q1: com.quickblox.chat.QBWebRTCSignaling#43156ce0
I/errorCheck: Q2: true
D/RTCClient.: New signalling was added for participant39753771
D/RTCClient.QBRTCSession: Make new channel for oppoennt:39753771com.quickblox.videochat.webrtc.QBPeerChannel#42f23c00
D/RTCClient.QBRTCSession: isInitiator=true
D/RTCClient.QBRTCSession: ADD VideoTrackCallbacksListener app.x.y.VideoActivity#4288e7f8
D/RTCClient.QBRTCSession: startCall
D/RTCClient.PeerFactoryManager: Creating Peer connection factory
D/RTCClient.QBRTCSession.SessionWaitingTimers: Stop WaitTimer
But for opponent not set log ( not incoming notification or ... )
How can I solve this problem?
You may refer with this thread. Check the video-sample. There is implementation of opening IncomingCallFragment by receiving push in this sample. Also, if you have successful subscription, but do not receive pushes, you always can check the following:
Check certificates for pushes: Admin panel ->Push Notification ->Settings -> APNS, GCM etc.
Send push from Admin Panel - > Push notifications - > Send (link)
Also you can check Push Notifications Queue tab in Admin panel, there should be a log of your push. It will help you to understand what's going on with your devices.
Hope this helps!
I am testing on Pixel device with Fingerprint Gestures ON from accessibility. I am trying to get the gesture callbacks using FingerprintGestureController but never getting any gestures in return even after I turn the accessibility ON for this app from Settings->Accessibility. isGestureDetectionAvailable() is always returning false to me. Can someone please help.
Here is the code:
my_gesture_service.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRequestFingerprintGestures="true" />
AndroidManifest.xml
<uses-feature android:name="android.hardware.fingerprint"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
<service
android:name="android.gestures.MyService"
android:label="#string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/my_gesture_service" />
</service>
MyService.java
public class MyService extends AccessibilityService {
private static final String TAG = MyService.class.getSimpleName();
#Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
Log.d(TAG, "onAccessibilityEvent");
}
#Override
public void onInterrupt() {
Log.d(TAG, "onInterrupt");
}
#Override
protected boolean onGesture(int gestureId) {
Log.d(TAG, "onGesture " + gestureId);
return super.onGesture(gestureId);
}
#Override
protected boolean onKeyEvent(KeyEvent event) {
Log.d(TAG, "onKeyEvent " + event.getKeyCode());
return super.onKeyEvent(event);
}
#Override
public void onDestroy() {
Toast.makeText(getApplicationContext(), "onDestroy" , Toast.LENGTH_SHORT).show();
super.onDestroy();
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.d(TAG, "onServiceConnected");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
FingerprintGestureController gestureController = getFingerprintGestureController();
Toast.makeText(getApplicationContext(), "Is available: " + gestureController.isGestureDetectionAvailable(), Toast.LENGTH_LONG).show();
Log.e(TAG, "Is available: " + gestureController.isGestureDetectionAvailable() );
FingerprintGestureController.FingerprintGestureCallback callback = new
FingerprintGestureController.FingerprintGestureCallback() {
#Override
public void onGestureDetectionAvailabilityChanged(boolean available) {
super.onGestureDetectionAvailabilityChanged(available);
Toast.makeText(getApplicationContext(), "Gesture available change to: " + available, Toast.LENGTH_SHORT).show();
Log.d(TAG, "onGestureDetectionAvailabilityChanged " + available);
}
#Override
public void onGestureDetected(int gesture) {
super.onGestureDetected(gesture);
Toast.makeText(getApplicationContext(), "Gesture: " + gesture, Toast.LENGTH_SHORT).show();
Log.d(TAG, "onGestureDetected " + gesture);
}
};
gestureController.registerFingerprintGestureCallback(callback, new Handler());
}
}
#Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind " );
return super.onUnbind(intent);
}
}
Found the answer. I needed this one flag too in xml:
android:accessibilityFlags="flagDefault|flagRequestFingerprintGestures"
I have a connection with SIP server(Asterisk), but micro and dynamics doesn't work. Asterisk kicks client in 31 seconds(Empty RTP thread). Documentation by Google says:
Android provides an API that supports the Session Initiation Protocol (SIP). This lets you add SIP-based internet telephony features to your applications. Android includes a full SIP protocol stack and integrated call management services that let applications easily set up outgoing and incoming voice calls, without having to manage sessions, transport-level communication, or audio record or playback directly.
Activity + Receiver:
public class MainActivity extends AppCompatActivity {
public String domain = "192.168.10.37";
public String name = "111";
public String password = "123456";
public String sipAddress = "100#192.168.10.37";
public IncomingCallReceiver receiver;
public SipManager sipManager;
public SipProfile sipProfile;
public SipAudioCall call;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.USE_SIP)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.USE_SIP)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.USE_SIP},
0);
}
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("zlotnikov.SIPexample.INCOMING_CALL");
receiver = new IncomingCallReceiver();
this.registerReceiver(receiver, intentFilter);
initManager();
}
private void initManager() {
if (sipManager == null) {
sipManager = SipManager.newInstance(this);
}
}
private void initializeLocalProfile() {
if (sipProfile != null) {
closeLocalProfile();
}
try {
SipProfile.Builder builder = new SipProfile.Builder(name, domain);
builder.setPassword(password);
builder.setSendKeepAlive(true);
builder.setAutoRegistration(true);
sipProfile = builder.build();
Intent intent = new Intent();
intent.setAction("zlotnikov.SIPexample.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
SipRegistrationListener listener = new SipRegistrationListener() {
#Override
public void onRegistering(String s) {
System.out.println("voip onRegistering " + s);
}
#Override
public void onRegistrationDone(String s, long l) {
System.out.println("voip onRegistrationDone " + s + " " + l);
//initCall();
}
#Override
public void onRegistrationFailed(String s, int i, String s1) {
System.out.println("voip onRegistrationFailed " + s);
}
};
sipManager.open(sipProfile, pendingIntent, null);
//sipManager.register(sipProfile, 40, listener);
sipManager.setRegistrationListener(sipProfile.getUriString(), listener);
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
}
}
#Override
protected void onStart() {
super.onStart();
initializeLocalProfile();
}
#Override
protected void onStop() {
super.onStop();
closeLocalProfile();
}
private void closeLocalProfile() {
try {
if (sipProfile != null) {
sipManager.close(sipProfile.getUriString());
}
} catch (Exception ee) {
ee.printStackTrace();
}
}
private void initCall() {
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCallEstablished(SipAudioCall call) {
super.onCallEstablished(call);
System.out.println("voip onCallEstablished");
call.startAudio();
call.setSpeakerMode(true);
}
#Override
public void onCallEnded(SipAudioCall call) {
super.onCallEnded(call);
System.out.println("voip onCallEnded");
}
};
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
} catch (SipException e) {
closeLocalProfile();
call.close();
e.printStackTrace();
System.out.println("voip MainActivity Конец соединения");
}
}
public class IncomingCallReceiver extends BroadcastReceiver {
private MediaPlayer mediaPlayer;
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
System.out.println("voip Пришел звонок " + intent.toString());
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
System.out.println("voip onRinging()");
try {
startRinging();
} catch (Exception e) {
stopRinging();
System.out.println("voip onRinging exception");
e.printStackTrace();
}
}
#Override
public void onCallEstablished(SipAudioCall call) {
super.onCallEstablished(call);
System.out.println("voip onCallEstablished()");
stopRinging();
}
#Override
public void onCallEnded(SipAudioCall call) {
super.onCallEnded(call);
System.out.println("voip onCallEnded()");
}
};
incomingCall = sipManager.takeAudioCall(intent, listener);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
/*if (incomingCall.isMuted()) {
incomingCall.toggleMute();
}*/
//call = incomingCall;
incomingCall.answerCall(30);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
System.out.println("voip IncomingCallReceiver конец соединения");
}
}
}
private synchronized void startRinging() {
long[] pattern = {0, 1000, 1000};
((Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE)).vibrate(pattern, 0);
Uri defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(getApplicationContext(), RingtoneManager.TYPE_RINGTONE);
mediaPlayer = MediaPlayer.create(getApplicationContext(), defaultRingtoneUri);
mediaPlayer.setLooping(true);
mediaPlayer.start();
}
private synchronized void stopRinging() {
((Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE))
.cancel();
if (mediaPlayer != null || mediaPlayer.isPlaying()) mediaPlayer.stop();
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="zlotnikov.sipexample">
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.sip.voip" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MainActivity$IncomingCallReceiver" android:label="Call Receiver" />
</application>
I use estimote android sdk for becan detaction or scan but i did not get beacons and there list call. i setup my code according to Readme file shows on lib and complie code but not get becons.
https://github.com/Estimote/Android-SDK
private static final String ESTIMOTE_PROXIMITY_UUID = "B9407F30-F5F8-466E-AFF9-25556B57FE6D";
private static final Region ALL_ESTIMOTE_BEACONS = new Region("regionId", ESTIMOTE_PROXIMITY_UUID, null, null);
private BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_signup);
beaconManager = new BeaconManager(SignupActivity.this);
// Should be invoked in #onCreate.
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region arg0, List<Beacon> beacons) {
Log.d("TAG", "Ranged beacons: " + beacons);
}
});
}
#Override
protected void onStart() {
super.onStart();
// Should be invoked in #onStart.
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS);
} catch (RemoteException e) {
Log.e("TAG", "Cannot start ranging", e);
}
}
});
}
#Override
protected void onStop() {
super.onStop();
try {
beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS);
} catch (RemoteException e) {
Log.e("TAG", "Cannot stop but it does not matter now", e);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.disconnect();
}
Change
private static final Region ALL_ESTIMOTE_BEACONS = new Region("regionId", ESTIMOTE_PROXIMITY_UUID, null, null);
to
private static final Region ALL_ESTIMOTE_BEACONS = new Region("regionId", null, null, null);
And also Change
beaconManager = new BeaconManager(SignupActivity.this);
// Should be invoked in #onCreate.
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region arg0, List<Beacon> beacons) {
Log.d("TAG", "Ranged beacons: " + beacons);
}
});
to
beaconManager = new BeaconManager(SignupActivity.this);
// Should be invoked in #onCreate.
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region arg0, List<Beacon> beacons) {
Log.d("TAG", "Ranged beacons: " + beacons.size());
}
});
Here you can see the size of near by beacons
Download jar file.
https://github.com/Estimote/Android-SDK
https://github.com/Estimote/Android-SDK/blob/master/EstimoteSDK/estimote-sdk-preview.jar
Mainifeast code.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.user.TempActivity"
android:configChanges="orientation|screenSize"
android:label="#string/app_name"
android:windowSoftInputMode="stateHidden|adjustPan" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.estimote.sdk.service.BeaconService"
android:exported="false" >
</service>
</application>
</manifest>
// Example activity
public class TempActivity extends Activity {
private static final String ESTIMOTE_PROXIMITY_UUID = "B9407F30-F5F8-466E-AFF9-25556B57FE6D";
private static final Region ALL_ESTIMOTE_BEACONS = new Region("regionId", ESTIMOTE_PROXIMITY_UUID, null, null);
private BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.temp_activity);
startBeaconDetectionService();
WebAsynk mWebAsynk= new WebAsynk();
mWebAsynk.execute(BEACON_WEB_SERVICE);
}
#Override
protected void onStart() {
super.onStart();
// Should be invoked in #onStart.
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS);
} catch (RemoteException e) {
Log.e("TAG", "Cannot start ranging", e);
}
}
});
}
#Override
protected void onStop() {
super.onStop();
try {
beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS);
} catch (RemoteException e) {
Log.e("TAG", "Cannot stop but it does not matter now", e);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.disconnect();
}
/**
* Beacon Detection Service response handle here
*/
private void startBeaconDetectionService(){
beaconManager = new com.estimote.sdk.BeaconManager(TempActivity.this);
beaconManager.setForegroundScanPeriod(2000,2000);
// Should be invoked in #onCreate.
beaconManager.setRangingListener(new com.estimote.sdk.BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region arg0, final List<Beacon> beacons) {
Log.d("TAG", "Ranged beacons: " + beacons);
Log.e("TAG", "Ranged beacons: " + beacons);
runOnUiThread(new Runnable() {
#Override
public void run() {
int test=0;
if(beacons.size()<=0){
Toast.makeText(TempActivity.this, "No beacon found",
Toast.LENGTH_SHORT).show();
}else{
for (int i = 0; i < beacons.size(); i++) {
String beac=beacons.get(i).getProximityUUID();
String macAddress=beacons.get(i).getMacAddress();
int major=beacons.get(i).getMajor();
int minor=beacons.get(i).getMinor();
int rssi=beacons.get(i).getRssi();
// Filter for right beacon detection
Toast.makeText(TempActivity.this, "I found a beacon with UUID; "+beac+" M-"+major,
Toast.LENGTH_SHORT).show();
}
}
}
});
}
});
}
}