- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发用于应用间通话的 VoIP 应用。我正在使用 Sinch API、FCM 在后台接收传入消息。它工作正常,但是当应用程序在后台被杀死时,我没有接到来电。
我的代码如下:
FCM-
public class FireBaseMsgService extends FirebaseMessagingService {
public static SinchClient sinchClient=null;
public static CallClient callClient=null;
String username;
@Override
public void onCreate() {
username=Common.getSavedUserData(this,"user_name");
super.onCreate();
if (username != null) {
initsinch();
}
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
//initsinch();
if (foregrounded()) {
return;
}
if (SinchHelpers.isSinchPushPayload(remoteMessage.getData())) {
initsinch();
NotificationResult result = sinchClient.relayRemotePushNotificationPayload(remoteMessage.getData()); // relay the background incoming call
}
}
// To check if the app is in foreground
public static boolean foregrounded() {
ActivityManager.RunningAppProcessInfo appProcessInfo =
new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
return (appProcessInfo.importance == IMPORTANCE_FOREGROUND
|| appProcessInfo.importance == IMPORTANCE_VISIBLE);
}
private void initsinch() {
if (sinchClient == null) {
android.content.Context context = this.getApplicationContext();
sinchClient = Sinch.getSinchClientBuilder().context(context)
.applicationKey(APP_KEY)
.applicationSecret(APP_SECRET)
.environmentHost(ENVIORNMENT)
.userId(username).build();
sinchClient.setSupportCalling(true);
sinchClient.setSupportActiveConnectionInBackground(true);
sinchClient.startListeningOnActiveConnection();
sinchClient.setSupportManagedPush(true);
sinchClient.setPushNotificationDisplayName("my display name");
sinchClient.addSinchClientListener(new SinchClientListener() {
public void onClientStarted(SinchClient client) {
}
public void onClientStopped(SinchClient client) {
}
public void onClientFailed(SinchClient client, SinchError error) {
}
public void onRegistrationCredentialsRequired(SinchClient client, ClientRegistration registrationCallback) {
}
public void onLogMessage(int level, String area, String message) {
}
});
callClient = sinchClient.getCallClient();
callClient.setRespectNativeCalls(true);
callClient.addCallClientListener(new CallClientListener() {
@Override
public void onIncomingCall(CallClient callClient, Call INCOMINGCALL) {
Intent it=new Intent(getApplicationContext(),IncomingCallScreenActivity.class);
it.putExtra("mCall", INCOMINGCALL.getCallId());
it.putExtra("mCall_caller", INCOMINGCALL.getRemoteUserId());
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(it);
}
});
}
if (sinchClient != null && !sinchClient.isStarted()) {
sinchClient.start();
}
}
}
Username是在Sinch User中初始化的登录用户名。我在 IncomingCallActivity.call 中创建了 mCall 对象并在 Onservice Connected() 中接收调用对象并调用 sinchCall 监听器,如下所示,
public class IncomingCallScreenActivity extends BaseActivity {
static final String TAG=IncomingCallScreenActivity.class.getSimpleName();
private String mCallId;
private String mCallLocation;
private AudioPlayer mAudioPlayer;
TextView highlight;
// private NotificationCallvo mCallVo;
Call fmcall;
ImageView img;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.incoming);
highlight=(TextView)findViewById(R.id.highlight);
Animation a = AnimationUtils.loadAnimation(this, R.anim.blink);
a.reset();
highlight.startAnimation(a);
img=(ImageView)findViewById(R.id.image);
// Animation shake = AnimationUtils.loadAnimation(this, R.anim.milkshake);
// img.startAnimation(shake);
ImageButton answer=(ImageButton)findViewById(R.id.answerButton);
Animation shake = AnimationUtils.loadAnimation(this, R.anim.milkshake);
answer.startAnimation(shake);
answer.setOnClickListener(mClickListener);
ImageButton decline=(ImageButton) findViewById(R.id.declineButton);
decline.startAnimation(shake);
decline.setOnClickListener(mClickListener);
mAudioPlayer=new AudioPlayer(this);
mAudioPlayer.playRingTone();
mCallId=getIntent().getStringExtra(SinchService.CALL_ID);
System.out.println("cllerid++"+mCallId);
mCallLocation=getIntent().getStringExtra(SinchService.LOCATION);
}
@Override
protected void onServiceConnected()
{
if(getIntent().getExtras().get("mCall")!=null){
fmcall=FireBaseMsgService.callClient.getCall((String) getIntent().getExtras().get("mCall"));
((Call) fmcall).addCallListener(new SinchCallListener());
TextView remoteUser = (TextView) findViewById(R.id.remoteUser);
remoteUser.setText(((Call) fmcall).getRemoteUserId());
// TextView remoteUserLocation = (TextView) findViewById(R.id.remoteUserLocation);
// remoteUserLocation.setText("Calling from " + mCallLocation);
}else {
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
call.addCallListener(new SinchCallListener());
TextView remoteUser = (TextView) findViewById(R.id.remoteUser);
remoteUser.setText(call.getRemoteUserId());
TextView remoteUserLocation = (TextView) findViewById(R.id.remoteUserLocation);
remoteUserLocation.setText("Calling from " + mCallLocation);
} else {
Log.e(TAG, "Started with invalid callId, aborting");
finish();
}
}
}
private void answerClicked() {
mAudioPlayer.stopRingtone();
if (getIntent().getExtras().get("mCall") != null) {
fmcall = FireBaseMsgService.callClient.getCall((String) getIntent().getExtras().get("mCall"));
fmcall.answer();
Intent intent = new Intent(this, CallScreenActivity.class);
intent.putExtra("fcallId", (String) getIntent().getExtras().get("mCall"));
startActivity(intent);
} else {
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
call.answer();
Intent intent = new Intent(this, CallScreenActivity.class);
intent.putExtra(SinchService.CALL_ID, mCallId);
startActivity(intent);
} else {
finish();
}
}
}
private void declineClicked(){
mAudioPlayer.stopRingtone();
if(getIntent().getExtras().get("mCall")!=null){
fmcall.hangup();
}else {
Call call=getSinchServiceInterface().getCall(mCallId);
if(call!=null)
{
call.hangup();
}
finish();
}
}
private class SinchCallListener implements CallListener {
@Override
public void onCallProgressing(Call call) {
Log.d(TAG,"Call progressing");
}
@Override
public void onCallEstablished(Call call) {
Log.d(TAG,"Call Established");
}
@Override
public void onCallEnded(Call call) {
CallEndCause cause=call.getDetails().getEndCause();
Log.d(TAG, "Call ended, cause: " + cause.toString());
mAudioPlayer.stopRingtone();
finish();
}
@Override
public void onShouldSendPushNotification(Call call, List<PushPair> list) {
}
}
private View.OnClickListener mClickListener=new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId())
{
case R.id.answerButton:
answerClicked();
break;
case R.id.declineButton:
declineClicked();
break;
}
}
};
}
当我在后台终止应用程序并调用用户名时另一台设备,我没有收到来电通知。请帮忙
最佳答案
为此,您需要准备一项服务。以下是服务代码。
public class SinchService extends Service {
private static final String APP_KEY = "REPLACE_WITH_YOUR_APP_KEY";
private static final String APP_SECRET = "REPLACE_WITH_APP_SECRET";
private static final String ENVIRONMENT = "sandbox.sinch.com";
public static final String LOCATION = "LOCATION";
public static final String CALL_ID = "CALL_ID";
static final String TAG = SinchService.class.getSimpleName();
private SinchServiceInterface mSinchServiceInterface = new SinchServiceInterface();
private SinchClient mSinchClient;
private String mUserId;
private StartFailedListener mListener;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
if (mSinchClient != null && mSinchClient.isStarted()) {
mSinchClient.terminate();
}
super.onDestroy();
}
private void start(String userName) {
if (mSinchClient == null) {
mUserId = userName;
mSinchClient = Sinch.getSinchClientBuilder().context(getApplicationContext()).userId(userName)
.applicationKey(APP_KEY)
.applicationSecret(APP_SECRET)
.environmentHost(ENVIRONMENT).build();
mSinchClient.setSupportCalling(true);
mSinchClient.startListeningOnActiveConnection();
mSinchClient.addSinchClientListener(new MySinchClientListener());
mSinchClient.getCallClient().addCallClientListener(new SinchCallClientListener());
mSinchClient.start();
}
}
private void stop() {
if (mSinchClient != null) {
mSinchClient.terminate();
mSinchClient = null;
}
}
private boolean isStarted() {
return (mSinchClient != null && mSinchClient.isStarted());
}
@Override
public IBinder onBind(Intent intent) {
return mSinchServiceInterface;
}
public class SinchServiceInterface extends Binder {
public Call callPhoneNumber(String phoneNumber) {
return mSinchClient.getCallClient().callPhoneNumber(phoneNumber);
}
public Call callUser(String userId) {
return mSinchClient.getCallClient().callUser(userId);
}
public Call callUser(String userId, Map<String, String> headers) {
return mSinchClient.getCallClient().callUser(userId, headers);
}
public String getUserName() {
return mUserId;
}
public boolean isStarted() {
return SinchService.this.isStarted();
}
public void startClient(String userName) {
start(userName);
}
public void stopClient() {
stop();
}
public void setStartListener(StartFailedListener listener) {
mListener = listener;
}
public Call getCall(String callId) {
return mSinchClient.getCallClient().getCall(callId);
}
public NotificationResult relayRemotePushNotificationPayload(final Map payload) {
if (mSinchClient == null && !mUserId.isEmpty()) {
start(mUserId);
} else if (mSinchClient == null && mUserId.isEmpty()) {
Log.e(TAG, "Can't start a SinchClient as no username is available, unable to relay push.");
return null;
}
return mSinchClient.relayRemotePushNotificationPayload(payload);
}
}
public interface StartFailedListener {
void onStartFailed(SinchError error);
void onStarted();
}
private class MySinchClientListener implements SinchClientListener {
@Override
public void onClientFailed(SinchClient client, SinchError error) {
if (mListener != null) {
mListener.onStartFailed(error);
}
mSinchClient.terminate();
mSinchClient = null;
}
@Override
public void onClientStarted(SinchClient client) {
Log.d(TAG, "SinchClient started");
if (mListener != null) {
mListener.onStarted();
}
}
@Override
public void onClientStopped(SinchClient client) {
Log.d(TAG, "SinchClient stopped");
}
@Override
public void onLogMessage(int level, String area, String message) {
switch (level) {
case Log.DEBUG:
Log.d(area, message);
break;
case Log.ERROR:
Log.e(area, message);
break;
case Log.INFO:
Log.i(area, message);
break;
case Log.VERBOSE:
Log.v(area, message);
break;
case Log.WARN:
Log.w(area, message);
break;
}
}
@Override
public void onRegistrationCredentialsRequired(SinchClient client,
ClientRegistration clientRegistration) {
}
}
private class SinchCallClientListener implements CallClientListener {
@Override
public void onIncomingCall(CallClient callClient, Call call) {
Log.d(TAG, "Incoming call");
Intent intent = new Intent(SinchService.this, IncomingCallScreenActivity.class);
intent.putExtra(CALL_ID, call.getCallId());
intent.putExtra(LOCATION, call.getHeaders().get("location"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SinchService.this.startActivity(intent);
}
}
在获得用户许可后,在您的主要 Activity 中使用以下代码启动此服务
FirebaseApp.initializeApp(this);
getApplicationContext().bindService(new Intent(this, SinchService.class), this,
BIND_AUTO_CREATE);
并用下面的代码替换你的 FireBaseMsgService
public class FireBaseMsgService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage){
Map data = remoteMessage.getData();
if (SinchHelpers.isSinchPushPayload(data)) {
new ServiceConnection() {
private Map payload;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (payload != null) {
SinchService.SinchServiceInterface sinchService = (SinchService.SinchServiceInterface) service;
if (sinchService != null) {
NotificationResult result = sinchService.relayRemotePushNotificationPayload(payload);
// handle result, e.g. show a notification or similar
}
}
payload = null;
}
@Override
public void onServiceDisconnected(ComponentName name) {}
public void relayMessageData(Map<String, String> data) {
payload = data;
getApplicationContext().bindService(new Intent(getApplicationContext(), SinchService.class), this, BIND_AUTO_CREATE);
}
}.relayMessageData(data);
}
}
创建临时前台服务
public class TempService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
return START_STICKY;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground(){
String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
并在主要 Activity 中启动该服务
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(this,TempService.class));
} else
startService(new Intent(this,TempService.class));
list 声明部分
<service
android:name=".TempService"
android:exported="true"/>
在你的代码中检查一次你没有下面的代码,如果有请评论它
getSinchServiceInterface().stopClient();
关于java - 在 Android 中使用 sinch 的来电通知,我正在使用 FireBase Messaging 服务,但当应用程序在后台被杀死时没有接到电话,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55057555/
我的一位客户刚刚告诉我,在使用我为他们开发的应用程序时,他们接到来电,但 iPhone 上没有显示警报。相反,调用电话的人听到一条消息,表明用户的服务暂时不可用。 如果我们暂时搁置以下可能性:调用电话
我正在尝试在 Android 上实现 iOS callkit 行为。我收到来自 firebase 的推送通知,我想向用户显示“来电”屏幕。为此,我使用了 android.telecom 包和其他类中的
我使用 WebRTC 制作了一个简单的调用应用程序。我已建立连接,现在可以从一个浏览器调用另一个浏览器。 我仍然无法弄清楚并且在 WebRTC 标准中找不到的一件事是......我如何拒绝通话提议。
我正在使用 Twilio Java API,但我似乎无法构建将调用 Sip 分机的响应。 TwiMLResponse twiml = new TwiMLResponse(); Sip sip = ne
“如何挂断来电(当然是在 Android 中)?” 首先,我知道这个问题已经被问过和回答过好几次了,而回答总是“你不能”。但是如果我们看看市场,我们会得到一些应用程序(所有私有(private)软件,
场景如下: 显示一个 Activity (active)。如果有电话来电,Activity 应该接收到 Intent(将“来电屏幕”发送到后台/从显示屏上隐藏它),并且 Activity 本身对用户保
我用过这个方法How do I get my AVPlayer to play while app is in background?让 AVPlayer 在后台播放,以便用户可以在浏览 safari
我正在编写一个基于闹钟的应用程序,我正在寻找一种持续唤醒用户的方法。理想情况下,我希望电话能够振动、响铃和显示消息。我尝试了几种不同的选择,这是我目前拥有的: 让后台服务启动振动和播放音乐的 Acti
我的对象使用 javascript 对象原型(prototype)。 我定义了以下内容: Game = function(id, userId, tiles){ this._userId =
我正在开发 VOIP 调用应用程序。当来电显示高达 android 5.0 版时,来电显示在锁定屏幕的顶部,但从 6.0 版开始显示为通知。未出现调用屏幕。 在做了一些研发之后,在 setConten
我在 Android 上编写自己的启动器,当我使用此启动器接到 Skype 电话时,我看到来电窗口,但我无法接听电话...之后我什么也做不了,它是封锁所有。使用默认启动器和其他启动器,Skype 可以
现在怎么样了 很多问题都讨论过这个问题,但都没有提供好的解决方案。事情看起来很简单,有了 BroadcastReceiver 之后真的很容易拦截和阻止调用。出现的主要问题是默认的 Android
我正在开发一个应用程序,这个应用程序需要在某些事件发生时向用户提供明确的指示。 到目前为止我唯一能做的就是在通知区域发出通知。但是,我需要提供更明显的通知,类似于来电时电话响铃时的行为。 据我了解,a
不幸的是,Twilio 文档不够清晰,无法回答我的问题,所以我来了。 当我的应用程序在前台/后台运行时,我能够在用户调用时接收 Twilio 传入连接,并且我可以正确处理此问题(在应用程序内显示弹出窗
这可能是个愚蠢的问题,我有点菜鸟。我正在阅读这篇文章:How do I access call log for android? 在代码底部的答案中,他们有这一行: int type = Intege
我是一名优秀的程序员,十分优秀!