Sinch没有在后台运行(Android)

时间:2016-07-24 20:20:23

标签: android audio call sinch android-sinch-api

美好的一天。我正在使用sinch进行音频通话。我不知道该怎么做,并且没有明确的sinch文件(这是非常令人费解的),这会让我知道如何让sinch客户端在后台运行在应用程序被杀时,在后台监听来电。同时我认为我强迫sinch客户端不被终止,但每次应用程序打开时,客户端都会被启动。所以,如果有人遇到这样的事情,你能不能请帮帮我,告诉我怎样才能在Sinch的后台听取来电?发布我已经启动并运行的代码。

我所有活动都继承的基本活动。

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

import ink.service.SinchService;

/**
 * Created by USER on 2016-07-24.
 */
public abstract class BaseActivity extends AppCompatActivity implements ServiceConnection {
    private SinchService.SinchServiceInterface mSinchServiceInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getApplicationContext().bindService(new Intent(this, SinchService.class), this,
                BIND_AUTO_CREATE);
    }

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        if (SinchService.class.getName().equals(componentName.getClassName())) {
            mSinchServiceInterface = (SinchService.SinchServiceInterface) iBinder;
            onServiceConnected();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Toast.makeText(BaseActivity.this, "Service disconnected", Toast.LENGTH_SHORT).show();
        if (SinchService.class.getName().equals(componentName.getClassName())) {
            mSinchServiceInterface = null;
            onServiceDisconnected();
        }
    }

    protected void onServiceConnected() {
        // for subclasses
    }

    protected void onServiceDisconnected() {
        // for subclasses
    }

    protected SinchService.SinchServiceInterface getSinchServiceInterface() {
        return mSinchServiceInterface;
    }

}

sinch服务

 * Created by USER on 2016-07-24.
 */
public class SinchService extends Service {

    private static final String APP_KEY = "HIDDEN";
    private static final String APP_SECRET = "HIDDEN";
    private static final String ENVIRONMENT = "HIDDEN";

    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();
        Toast.makeText(SinchService.this, "Service created", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDestroy() {
//        if (mSinchClient != null && mSinchClient.isStarted()) {
//            mSinchClient.terminate();
//        }
        Toast.makeText(SinchService.this, "Service destroyed", Toast.LENGTH_SHORT).show();
        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.setSupportActiveConnectionInBackground(true);

            mSinchClient.addSinchClientListener(new ClientListener());
            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 interface StartFailedListener {
        void onStartFailed(SinchError error);

        void onStarted();
    }

    private class ClientListener 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) {
            Toast.makeText(SinchService.this, "Sinch client stopped", Toast.LENGTH_SHORT).show();
            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("callerName"));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            SinchService.this.startActivity(intent);
        }
    }

}

以下是我在启动器活动中启动sinch服务的方法。

   @Override
    protected void onServiceConnected() {
        if (!getSinchServiceInterface().isStarted()) {
            getSinchServiceInterface().startClient(mSharedHelper.getUserId());
        }
        getSinchServiceInterface().setStartListener(this);
    }

3 个答案:

答案 0 :(得分:4)

1)添加到您的sinchClient mSinchClient.setSupportManagedPush(true);以在接到电话时收到推送通知消息

2)在您的应用上设置Firebase云消息传递

3)onMessageReceived将数据传输到IncomingTransparentCallActivity

    public class FirebaseMsgService extends FirebaseMessagingService {
            @Override
            public void onMessageReceived(RemoteMessage remoteMessage) {
                super.onMessageReceived(remoteMessage);

        Map<String, String> map = remoteMessage.getData();
                    HashMap dataHashMap =
                            (map instanceof HashMap)
                                    ? (HashMap) map
                                    : new HashMap<>(map);
                    if (SinchHelpers.isSinchPushPayload(map)) {
        ///Check if the application is in foreground if in foreground the SinchService already run //// 
          if (foregrounded()){
                        return;
                    }
                        Intent intent = new Intent(this, IncomingCallActivity.class);
                        NotificationCallVo callVo = new  NotificationCallVo();
                        callVo.setData(dataHashMap);
                        intent.putExtra(Constants.PARCELABLE, callVo);
                        startActivity(intent);

                    }

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

        }

NotificationCallVo

  public class NotificationCallVo implements Parcelable {

        private HashMap data;

        public NotificationCallVo() {
        }

        private NotificationCallVo(Parcel in) {
            data = (HashMap) in.readValue(HashMap.class.getClassLoader());
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeValue(data);
        }

        @SuppressWarnings("unused")
        public static final Parcelable.Creator<NotificationCallVo> CREATOR = new Parcelable.Creator<NotificationCallVo>() {
            @Override
            public NotificationCallVo createFromParcel(Parcel in) {
                return new NotificationCallVo(in);
            }

            @Override
            public NotificationCallVo[] newArray(int size) {
                return new NotificationCallVo[size];
            }
        };

        public HashMap getData() {
            return data;
        }

        public void setData(HashMap<String, String> data) {
            this.data = data;
        }
    }

4)在SinchServiceInterface上添加方法

public NotificationResult relayRemotePushNotificationPayload(final Map payload) {
            if (mSinchClient == null && !mSettings.getUsername().isEmpty()) {
                startClient(mSettings.getUsername());
            } else if (mSinchClient == null && mSettings.getUsername().isEmpty()) {
                Log.e(TAG, "Can't start a SinchClient as no username is available, unable to relay push.");
                return null;
            }
            return mSinchClient.relayRemotePushNotificationPayload(payload);
        } 

5)关于IncomingTransparentCallActivity连接到SinchService和onServiceConnected传输数据到sinchServiceInterface

public class IncomingTransparentCallActivity extends BaseCallActivity {
    private NotificationCallVo mCallVo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getIntent().getParcelableExtra(Constants.PARCELABLE) != null &&
                getIntent().getParcelableExtra(Constants.PARCELABLE) instanceof NotificationCallVo) {
            mCallVo = getIntent().getParcelableExtra(Constants.PARCELABLE);
        }
    }

    @Override
    protected void onServiceConnected(IBinder iBinder) {
        SinchService.SinchServiceInterface sinchServiceInterface = getSinchServiceInterface();
        if (mCallVo != null) {
            NotificationResult result = sinchServiceInterface.relayRemotePushNotificationPayload(mCallVo.getData());
            setContentView(R.layout.activity_incoming_call);
        }
    }
}

6)BaseCallActivity

public abstract class BaseCallActivity extends AppCompatActivity implements ServiceConnection {
    private SinchService.SinchServiceInterface mSinchServiceInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bindService(new Intent(this, SinchService.class), this,
                Context.BIND_AUTO_CREATE);
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder iBinder) {
        if (SinchService.class.getName().equals(name.getClassName())) {
            mSinchServiceInterface = (SinchService.SinchServiceInterface) iBinder;
            onServiceConnected(iBinder);
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        if (SinchService.class.getName().equals(name.getClassName())) {
            mSinchServiceInterface = null;
            onServiceDisconnected();
        }
    }

    @Override
    public void onBindingDied(ComponentName name) {

    }

    protected void onServiceConnected(IBinder iBinder) {
        // for subclasses
    }

    protected void onServiceDisconnected() {
        // for subclasses
    }

    protected SinchService.SinchServiceInterface getSinchServiceInterface() {
        return mSinchServiceInterface;
    }

    public void setmSinchServiceInterface(SinchService.SinchServiceInterface mSinchServiceInterface) {
        this.mSinchServiceInterface = mSinchServiceInterface;
    }



    @Override
    protected void onDestroy() {
        unbindService(this);
        super.onDestroy();
    }
}

7)SinchCallClientListener将收听您的来电并打开您的活动

检查以下链接 [https://www.sinch.com/learn/sinch-managed-push-calling-android/][1]

答案 1 :(得分:1)

好像您还没有在清单文件中声明您的服务。按照以下方式进行:

<service
        android:name=".SinchService"   
        android:exported="false" />

如果有,请与我们分享您的清单文件。

答案 2 :(得分:0)

我的回答可能有点晚了,但我希望它会有用。不久前,我遇到了同样的问题,并使用sinch的文档(link here)解决了该问题,如果您在应用中使用FCM进行推送通知,请按照以下步骤操作:

1。使用这些变量在您的应用中创建FCM服务,并在打开应用以初始化前台调用时调用startservice:

public static SinchClient sinchClient=null;
public static CallClient callClient=null;

 @Override
public void onCreate() {
    initsinch();
    Log.d(MY_TAG,"onCreate FCM");
    super.onCreate();
}

2。根据sinch的文档:

  

在以下情况下,应用程序被视为离线:

     
      
  • 应用程序未运行时
  •   
  • 已为Sinch客户端禁用后台模式,并且应用程序不在前台。
  •   
     

对于这两种情况,推送通知必须在   能够接收来电和即时消息的应用程序。   以下各节介绍如何支持接听电话和   通过推送通知发送消息。

所以您需要在onMessageReceived()中做什么:

if (SinchHelpers.isSinchPushPayload(remoteMessage.getData())) { //it sinch payload
        initsinch(); // init sinch and callclient for background call
        NotificationResult result = sinchClient.relayRemotePushNotificationPayload(remoteMessage.getData());     // relay the background incomming call     
    }else { //push your own notifications }

3。在imcommingcall活动中,您应该使用在FCM服务类中创建的sinchclient创建mCall对象。(这就是sinchclient变量需要公开的原因):

  if (getIntent().getExtras().get("mCall")!=null)
        {
            mCall =MyFirebaseMessaging.callClient.getCall(getIntent().getExtras().get("mCall").toString());
            mCall.addCallListener(callListener);
  }

这就是您需要做的。我没有将sinch用作绑定服务。只是将其用作公共变量。让我知道它是否有效

这是我的initsinch()方法:

private void initsinch() {
    if (sinchClient==null){

     Log.d(MY_TAG,"Init sinch FCM");
        android.content.Context context = this.getApplicationContext();
        sinchClient = Sinch.getSinchClientBuilder().context(context)
                .applicationKey("your own applicationKey")
                .applicationSecret("your own applicationSecret")
                .environmentHost("sandbox.sinch.com")
                .userId("your own user id").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) {

                Log.d(MY_TAG,"Sinch started");

            }
            public void onClientStopped(SinchClient client) {
                Log.d(MY_TAG,"Sinch stopped");
            }
            public void onClientFailed(SinchClient client, SinchError error) {
                Log.d(MY_TAG,"Sinch Fail");
            }
            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 INCOMMINGCALL) {

                if (INCOMMINGCALL.getDetails().isVideoOffered()){
                    Intent it=new Intent(getApplicationContext(),Video_imcomming_call.class);
                    it.putExtra("mCall", INCOMMINGCALL.getCallId());
                    it.putExtra("mCall_caller", INCOMMINGCALL.getRemoteUserId());
                    it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(it);
                }else {
                    Intent it=new Intent(getApplicationContext(),Incomming_call.class);
                    it.putExtra("mCall", INCOMMINGCALL.getCallId());
                    it.putExtra("mCall_caller", INCOMMINGCALL.getRemoteUserId());
                    it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(it);
                }


            }

        });

    }
    if (sinchClient!=null && !sinchClient.isStarted()){
        sinchClient.start();
    }
}