- 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/
如何在终止父进程时关闭我的子文件描述符? 我创建了一个执行以下操作的程序: 派生 2 个子进程。 进程 1 是一个读取器。它从 STDIN_FILENO 读取并使用 scanf/printf 写入 S
我试着写了一个小的暴力破解程序。密码程序在密码正确时返回 1,错误时返回 0。所以它很简单。 在 bruteforce 程序中,我使用 createprocess() 调用 pw 程序。 我的问题是,
谁能帮我解释一下我从一本书中得到的这个脚本。练习是编写一个名为 killalljobs 的脚本来终止所有后台作业。 为此给出的代码是: kill "$@" $( jobs -p) 我确定我在这里真
我正在开发一个包含许多库的应用程序。后来我注意到有几次应用程序进程在关闭应用程序后仍在耗尽 CPU。 我先终止了进程,但它继续运行。我卸载了该应用程序 - 但它仍然存在! (使用开发人员选项中的“显示
有没有办法在无人机完成或超时之前杀死它? 无人机的默认超时时间为 6 小时 ( https://github.com/drone/drone/blob/master/cmd/drone/drone.g
我有几个自动启动的菜单栏程序/进程/应用程序。我希望能够使用单个命令或脚本将它们全部关闭;有时带宽受到限制或受限,它们会导致(或至少导致)旋转的沙滩球死亡。目前,我手动关闭每一个。 关注 answer
当我阅读 learnyousomeerlang.com 上的一篇文章时,我有一个问题。 http://learnyousomeerlang.com/errors-and-processes 它说: E
有什么方法可以通过 OpenCL API 终止正在运行的 OpenCL 内核吗?我没有在规范中找到任何内容。 我能想出的唯一解决方案是 1) 定期检查内核中的标志,当主机希望内核停止时写入该标志,或
我已经对套接字(使用fsockopen()和stream_socket_client())和cURL进行了一些测试,以强制关闭连接(TCP/HTTP)。但是,没有运气。 无论我使用的是1毫秒的超时时间
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
我以不太优雅的方式杀死了 IRB 提示符(从 heroku run irb 开始),现在我有一个僵尸进程,但我似乎无法杀死它: Process State Co
致kill background process inside Codeship我们需要使用以下命令: #!/bin/bash nohup bash -c "YOUR_COMMAND 2>&1 &"
我第一次在这里发帖,因为我在互联网上找不到干净的解决方案。 我的目标很简单,我需要创建 一个 后台操作 (goroutine 或进程或其他...)我可以 正确杀死 (不要留在后台)。 我尝试了很多事情
我有一个进程调用: p=multiprocessing.Process(target=func_a) 然后func_a启动一个子进程: subprocess.Popen(["nc", "-l", "-
我正在运行一个基本上运行一堆服务器以进行本地测试的脚本。 这些 jar 在不同的 screen 中运行,因为它们需要独立地接受键盘输入。为此,我使用了 screen 。 command1="java
我有一个用 java 编写的应用程序,它在 Unix 上运行,并在启动时启动两个子进程(通过 Runtime.getRuntime().exec())。如果应用程序由于某种原因崩溃,子进程不会被终止。
我想要像 Pushbullet、SmartLockScreen 或 WhatsApp 那样独立运行的服务,它正在等待某个事件的发生。我已经尝试过前台服务,在 onStartCommand 中返回 ST
强制停止应用程序后,是否可以在 Android 应用程序中获取位置更新。在 IOS 中,如果我们强制停止应用程序,则有可能获得位置更新,以类似的方式,是否有任何服务可以为在 android 中被杀死的
我正在调查是否有任何方法可以防止 android 服务因未捕获的异常而被杀死。 我们有 10 个 UI 应用程序与 5-6 个服务通信。该平台是Android 2.2。 由于不可预见的情况,服务中的某
我刚刚将我的 javascript 转移到 jQuery 来实现简单的 AJAX 功能。不过,我尝试将灯箱插件与 jQuery 结合使用,因为我想保留相同的功能,但不想包含 10 个不同的库。如果我删
我是一名优秀的程序员,十分优秀!