【问题标题】:Quickblox -SDK for android App not receive call when app is in backgroundQuickblox -SDK for android App 在后台时未收到呼叫
【发布时间】:2016-12-03 17:24:19
【问题描述】:

我正在使用 Quickblox-SDK for android 开发视频通话应用程序。如果应用程序打开,应用程序运行良好且完美但如果应用程序在后台,我无法接听电话。我已经使用这个link 创建了应用程序,请帮忙。 我尝试了以下事情:

1) 通知到达时打开 CallActivity,使用 GCM 通知,但作为接收通知的通话时间,这件事也不起作用。

谢谢。

【问题讨论】:

    标签: android video call quickblox-android


    【解决方案1】:

    创建一个粘性服务,即使活动破坏也会在后台运行,该服务负责 QBsession 和所有其他操作,因此它将检测后台调用。我成功地实现了这一点,并且我成功地在后台接收了调用。

    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();
        }
    
    }
    

    【讨论】:

    • 你能发布你的CallActivity吗? ?
    • 你能帮忙吗?
    • callActivity 没有大的变化。当从 onReceiveNewSession() 接收呼叫时,您必须从服务中触发 callActivity 我无法在此处发布,因为我已根据需要对其进行了修改,因此代码太长而且没有更改
    • 我已经创建了粘性服务,但重定向到无法接收调用异常抛出,例如 chatService is already initialized 或 channel is already initialized 。您已将 rtcClient 用作 Global 吗?
    • 这里是CallActivity的链接paste.ofcode.org/V9VR5vBzMhh5AXtwhRzNLF
    【解决方案2】:

    终于找到了解决方案。您可以在 CallActivity 的 ReveiveNewSession 覆盖方法上启动活动

     @Override
    public void onReceiveNewSession(final QBRTCSession session) {
    
        Log.e("PLog", "Session " + session.getSessionID() + " are income");
    
    
        Log.d(TAG, "Session " + session.getSessionID() + " are income");
        String curSession = (getCurrentSession() == null) ? null : getCurrentSession().getSessionID();
    
        if (getCurrentSession() == null) {
            Log.d(TAG, "Start new session");
            initCurrentSession(session);
    
            setOptionsForSession(session, getDefaultSharedPrefs());
             addIncomeCallFragment(session);
    
            isInCommingCall = true;
            initIncommingCallTask();
            Intent i = new Intent(CallActivity.this, CallActivity.class);
            i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(i);
        } else {
            Log.d(TAG, "Stop new session. Device now is busy");
            Map<String, String> infoMap = new HashMap<>();
            infoMap.put(Consts.REJECT_REASON, "I'm on a call right now!");
            session.rejectCall(infoMap);
        }
    
    }
    

    【讨论】:

    • 什么是 setOptionsForSession() 方法?
    【解决方案3】:

    我现在已经开始工作了。在 PushListenerService 中添加以下方法

    class PushListenerService : QBFcmPushListenerService() {
    
        private val TAG = PushListenerService::class.java.simpleName
    
        override fun onMessageReceived(remoteMessage: RemoteMessage) {
            super.onMessageReceived(remoteMessage)
            if (SharedPrefsHelper.hasQbUser()) {
                val qbUser: QBUser = SharedPrefsHelper.getQbUser()
                Log.v(TAG, "App has logged user" + qbUser.id)
                LoginService.start(this, qbUser)
            }
        }
    
        override fun sendPushMessage(data: MutableMap<Any?, Any?>?, from: String?, message: String?) {
            super.sendPushMessage(data, from, message)
            Log.v(TAG, "From: $from")
            Log.v(TAG, "Message: $message")
            if (SharedPrefsHelper.hasQbUser()) {
                val qbUser: QBUser = SharedPrefsHelper.getQbUser()
                Log.v(TAG, "App has logged user" + qbUser.id)
                LoginService.start(this, qbUser)
            }
        }
    }
    

    还将服务添加到 manifest.xml

    <service
        android:name=".quickblox.services.fcm.PushListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    
    <service
        android:name="com.quickblox.messages.services.fcm.QBFcmPushInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>
    

    Firebase 推送通知是此操作的先决条件

    【讨论】:

      【解决方案4】:

      在 quickblox for Android 中获取后台调用的步骤

      1. 已关联您的应用 Firebase。 点击此链接了解更多https://docs.quickblox.com/docs/android-push-notifications

      2. 将服务器密钥从 firebase 控制台添加到 quickblox 管理面板,如上面的链接所示。还要仔细检查 Quickblox 中的环境(开发、生产)。

      3. 在android的Manifest文件中添加meta标签,如链接所示。

      4. 这是我的 PushListenerService 代码供参考

        class PushListenerService : QBFcmPushListenerService() {
         private val TAG = PushListenerService::class.java.simpleName
         override fun onNewToken(token: String) {
             super.onNewToken(token)
        
             val tokenRefreshed = true
             SharedPrefs.storeFcmToken(this, token)
             SubscribeService.subscribeToPushes(MyApplication.getInstance(), tokenRefreshed)
        
         }
        
         override fun onMessageReceived(p0: RemoteMessage) {
             Log.d(TAG, "onMessageReceived: $p0")
        
             if (SharedPrefsHelper.hasQbUser()) {
                 val qbUser: QBUser? = SharedPrefsHelper.getQbUser()
                 if (qbUser != null) {
                     Log.d(TAG, "App has logged user" + qbUser.id)
                     LoginService.start(this, qbUser)
        
                 }
             }
         }
        
         override fun sendPushMessage(data: MutableMap<Any?, Any?>?, from: String?, message: String?) {
             super.sendPushMessage(data, from, message)
             Log.v(TAG, "From: $from")
             Log.v(TAG, "Message: $message")
         }
        }
        
      5. 这是 quickblox 示例视频应用的 CallActivity.kt 中调用的 sendPushMessage 代码

         fun sendPushMessage(recipients: ArrayList<Int>,
                         senderName: String,
                         newSessionID: String,
                         opponentsIDs: String,
                         opponentsNames: String,
                         isVideoCall: Boolean) {
         val outMessage = String.format(R.string.text_push_notification_message.toString(), senderName)
        
         val currentTime = Calendar.getInstance().time
         val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
         val eventDate = simpleDateFormat.format(currentTime)
        
         // Send Push: create QuickBlox Push Notification Event
         val qbEvent = QBEvent()
         qbEvent.notificationType = QBNotificationType.PUSH
         qbEvent.environment = QBEnvironment.DEVELOPMENT
         // Generic push - will be delivered to all platforms (Android, iOS, WP, Blackberry..)
        
         val json = JSONObject()
         try {
             json.put("message", outMessage)
             json.put("ios_voip", "1")
             json.put("VOIPCall", "1")
             json.put("sessionID", newSessionID)
             json.put("opponentsIDs", opponentsIDs)
             json.put("contactIdentifier", opponentsNames)
             json.put("conferenceType", if (isVideoCall) "1" else "2")
             json.put("timestamp", eventDate)
         } catch (e: JSONException) {
             e.printStackTrace()
         }
        
         qbEvent.message = json.toString()
        
         val userIds = StringifyArrayList(recipients)
         qbEvent.userIds = userIds
        
         QBPushNotifications.createEvents(qbEvent).performAsync(object : QBEntityCallback<List<QBEvent>> {
             override fun onSuccess(p0: List<QBEvent>?, p1: Bundle?) {
                 Log.d("FCM", "onSuccess: ")
             }
        
             override fun onError(p0: QBResponseException?) {
                 Log.d("FCM", "onError: ${p0?.printStackTrace()}")
             }
         })
        }
        

      注意:请确保在用户登录时启动LoginService。在quickblox的示例代码中提到了LoginService

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-29
        • 1970-01-01
        • 1970-01-01
        • 2018-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多