Пользовательское приложение SIP VoIP продолжает закрываться Android - PullRequest
0 голосов
/ 22 сентября 2018

Я разработал версию родного демо-приложения SIP, предоставленного Google https://android.googlesource.com/platform/development/+/master/samples/SipDemo/

Приложение My Simple регистрируется на SIP-сервере, и когда на эту учетную запись SIP получено приглашение к вызову, уведомление и тостотображается с идентификатором звонящего.Я не разработал приложение для запуска в качестве службы или чего-либо еще.После запуска действия приложение регистрируется на SIP-сервере, а затем я просто нажимаю кнопку «Домой» и запускаю приложение в фоновом режиме, ожидая входящего вызова.

Приложение работает правильно, просто в течение ~ 12 - 24 часов приложение, кажется, было остановлено ОС Android.Я не уверен, связано ли это с собственным стеком SIP или диспетчером ресурсов Android, закрывающим приложение, но я попытался настроить все, что смогу, на самой трубке, чтобы предотвратить остановку приложения, например, удалить все настройки экономии заряда аккумулятора и т. Д.

Есть ли какие-либо советы, чтобы приложение работало в фоновом режиме с помощью собственного SIP API?

Мой код ниже:

CallerIDActivity.java -

package example.callerid;
//This app has been developed with a target API of 22 so as to avoid having to
//implement runtime permissions on the test handset with a higher API level.

import android.Manifest;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import android.net.sip.SipRegistrationListener;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;

public class CallerIDactivity extends Activity {

    public SipManager manager = null;
    public SipProfile me = null;
    public IncomingCallReceiver callReceiver;

    public CallerIDactivity (){
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createNotificationChannel();
    }//end constructor

        //define NotificationChannel method for use in the contructor above
        //IncomingCallReciever will then use this channel to send notification of CID

    public void createNotificationChannel(){
            //Create the Notification but only on API 26+ as the
            //notification class is new and not in the support lib
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                CharSequence name = "CHANNEL_NAME";
                String description = "CID_NOTIFY";
                int importance = NotificationManager.IMPORTANCE_HIGH;
                NotificationChannel channel = new NotificationChannel("CHANNEL_ID", name, importance);
                channel.setDescription(description);
                //Register the channel with the system: you can't change the importance
                //or other notification behaviour after this
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                if(notificationManager !=null) {
                    notificationManager.createNotificationChannel(channel);
                }
            }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.callerid);

        // Set up the intent filter.  This will be used to trigger an
        // IncomingCallReceiver when someone calls the SIP address used by this
        // application.
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.CallerID.INCOMING_CALL");
        callReceiver = new IncomingCallReceiver();
        this.registerReceiver(callReceiver, filter);

    }//end onCreate

    @Override
    public void onStart() {
       super.onStart();
        // When we get back from the preference setting Activity, assume
        // settings have changed, and re-login with new auth info.
       initializeManager();
   }

    @Override
    public void onDestroy() {
        super.onDestroy();

        closeLocalProfile();

        if (callReceiver != null) {
            this.unregisterReceiver(callReceiver);
            Log.d("CallerID", "UnRegisteringReceiverOnDestroy ");
            Toast toast = Toast.makeText(getApplicationContext(), "UnRegisteringReceiverOnDestroy", Toast.LENGTH_LONG);
            toast.show();
        }
    }//end onDestroy

    public void RegisterBtn(View callerid){
        initializeManager();
        Log.d("CallerIDactivity","RegisterBtn Press");
        Toast toast = Toast.makeText(getApplicationContext(),"Registering", Toast.LENGTH_SHORT);
        toast.show();
    }

    public void initializeManager() {
        if(manager == null) {
            manager = SipManager.newInstance(this);
        }

        initializeLocalProfile();
    }

    public void initializeLocalProfile() {
        if (manager == null) {
            return;
        }

        if (me != null) {
            closeLocalProfile();
        }

        try {
            SipProfile.Builder builder = new SipProfile.Builder("sipaccount", "my.sip.server");
            builder.setPassword("pass");
            me = builder.build();

            Intent i = new Intent();
            i.setAction("android.CallerID.INCOMING_CALL");
            PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
            manager.open(me,pi,null);


            // This listener must be added AFTER manager.open is called,
            // Otherwise the methods aren't guaranteed to fire.

            manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
                public void onRegistering(String localProfileUri) {
                    updateStatus("Registering with SIP Server...");
                }

                public void onRegistrationDone(String localProfileUri, long expiryTime) {
                    updateStatus("Ready");
                }

                public void onRegistrationFailed(String localProfileUri, int errorCode,
                                                 String errorMessage) {
                    updateStatus("Registration failed.  Please check settings.");
                }
            });

        }catch (ParseException pe) {
            updateStatus("Connection Error.");
        } catch (SipException se) {
            updateStatus("Connection error.");
        }


    }

    /**
     * Closes out your local profile, freeing associated objects into memory
     * and unregistering your device from the server.
     */
    public void closeLocalProfile() {
        if (manager == null) {
            Log.d("closeLocalProfile", "manager == null");
            return;
        }
        try {
            if (me != null) {
                manager.close(me.getUriString());
                Toast toast = Toast.makeText(getApplicationContext(), "ClosingProfileURI"+" "+me.getUriString(), Toast.LENGTH_SHORT);
                toast.show();
            }
         } catch (Exception ee) {

            Toast toast = Toast.makeText(getApplicationContext(), ee.getMessage(), Toast.LENGTH_SHORT);
            toast.show();
            Log.d("onDestroy", "Failed to close local profile.", ee);
        }
    }

    /**
     * Updates the status box at the top of the UI with a messege of your choice.
     * @param status The String to display in the status box.
     */
    public void updateStatus(final String status) {

        this.runOnUiThread(new Runnable() {
           public void run() {
               Toast toast = Toast.makeText(getApplicationContext(), status, Toast.LENGTH_SHORT);
               toast.show();

        }});

/*         Be a good citizen.  Make sure UI changes fire on the UI thread.
        this.runOnUiThread(new Runnable() {
            public void run() {
                Log.i("allenssip",status);
                TextView labelView = (TextView) findViewById(R.id.sipLabel);
                labelView.setText(status);
            }
        });
*/
    }//end updateStatus

}//end Class

IncomingCallReceiver.java -

package example.callerid;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.sip.*;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import android.widget.Toast;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;


/**
 * Listens for incoming SIP calls, intercepts and hands them off to CallerIDactivity.
 */
 public class IncomingCallReceiver extends BroadcastReceiver {

    public Calendar calendar;
    public SimpleDateFormat dateFormat;
    public String date;
    public SipManager mSipManager;
    public SipSession mSipSesion;
    public SipProfile peerProfile;
    static private int notifyNum = 1;

    /**
     * Processes the incoming call, answers it, and hands it over to the
     * CallerIDactivity.
     * @param context The context under which the receiver is running.
     * @param intent The intent being received.
     */
    @Override
    public void onReceive(Context context, Intent intent) {

            mSipManager = SipManager.newInstance(context);
            try {
                mSipSesion = mSipManager.getSessionFor(intent);
            } catch (SipException e) {
                e.printStackTrace();
            }

            peerProfile = mSipSesion.getPeerProfile();
            calendar = Calendar.getInstance();
            dateFormat = new SimpleDateFormat("dd/MM/yyyy");
            date = dateFormat.format(calendar.getTime());

            Log.d("CallerID", "OnReceive");

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, "CHANNEL_ID")
                    .setSmallIcon(R.mipmap.ic_launcher_round)
                    .setContentTitle("CallerID" + " " + date)
                    .setContentText(peerProfile.getDisplayName())
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setAutoCancel(true);

            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
            if(notifyNum <= 9) {
                notificationManager.notify(notifyNum++, mBuilder.build());
            }else {notificationManager.notify(notifyNum, mBuilder.build());
                    notifyNum = 1;
            }
            int count = 0;
            while (count <= 10) {
                Toast toast = Toast.makeText(context, peerProfile.getDisplayName(), Toast.LENGTH_SHORT);
                toast.show();
                count++;
            }//end while

    }//end onReceive

}//end Class
...