我正在使用android版的Quickblox SDK开发视频通话应用程序。如果应用程序是打开的,应用程序运行良好且完美。但如果应用程序在后台,我将无法接听电话。我已经使用此链接创建了应用程序,请提供帮助。我试过以下几件事:
1) 当通知到达时,打开CallActivity,通知使用GCM,但作为接收通知的通话时间,这件事也不起作用。
谢谢。
创建一个粘性服务,该服务将在后台运行,甚至活动销毁,该服务负责QBsession和所有其他操作,因此它将在后台检测调用。Iam成功地实现了这一点,并通过这一点成功地在后台接收了呼叫。
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 的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);
}
}
我现在已经开始工作了。将以下方法添加到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推送通知是此操作的先决条件
在Android 的quickblox中获取后台调用的步骤
-
链接了你的应用Firebase。关注此链接以获得更多了解https://docs.quickblox.com/docs/android-push-notifications
-
将firebase控制台中的服务器密钥添加到quickblox管理面板中,如上面的链接所示。还要仔细检查Quickblox(开发、生产)中的环境。
-
在android的Manifest文件中添加元标签,如链接所示。
-
这是我的PushListener服务代码,供参考
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") } }
-
这是在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()}") } }) }
注意:请确保在用户登录时启动登录服务。quickblox