Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
256 views
in Technique[技术] by (71.8m points)

android - Can't do heavy work on broadcast receiver which is inside the Service

I created a Broadcast Receiver Which is inside the Service Class (Because of the Android Broadcast receiver restrictions Broadcast receiver stops after while, So I created Background Service, with foreground Service Notification Restriction in Android Oreo=< ). This Broadcast Receiver Listens to Phone Call States Changes IDLE, OFFHOOK, RINGING. According to the Phone call states changes(If the call ends), I get the last call details in the Cursor and Send to that details into the Firebase Realtime Database. everything works perfectly until I comment(//) on the saveDatafromCursor() method Which is inside the PhoneStateListener Class. (I write a Toast message before saving data method). it works very fine. and my service works very well. but if I uncomment my saveDatafromCursor() method After the call ended. My Service stops(notification icon and toast messages stop. I checked in the real device). Without implementing the Service, I send data to the Firebase it's working very well, Why My service stops if I try to save data to the firebase?

Service Class

public class HammerService extends Service {

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

        IntentFilter ifilter = new IntentFilter();
        ifilter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);

        registerReceiver(receiver, ifilter);

    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        String input = intent.getStringExtra("inputExtra");
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0);

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Hammer Service")
                .setContentText(input)
                .setSmallIcon(R.drawable.ic_android)
                .setContentIntent(pendingIntent)
                .build();

        startForeground(1, notification);

        //do heavy work on a background thread
        //stopSelf();
        return START_NOT_STICKY;

    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            String action = intent.getAction();
            if(action.equals("android.provider.Telephony.SMS_RECEIVED")){
                //action for sms received
            }
            else if(action.equals(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED)){
                runfirstTime(context,intent);
            }
        }
    };

    private void runfirstTime(Context context, Intent intent) {
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        MyPhoneStateListener customPhoneListener = new MyPhoneStateListener();

        telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);

        Bundle bundle = intent.getExtras();
        String phone_number = bundle.getString("incoming_number");

        String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
        int state = 0;

        if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
            state = TelephonyManager.CALL_STATE_IDLE;
        }
        else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
            state = TelephonyManager.CALL_STATE_OFFHOOK;
        }
        else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
            state = TelephonyManager.CALL_STATE_RINGING;
        }

        if (phone_number == null || "".equals(phone_number)) {
            return;
        }

        customPhoneListener.onCallStateChanged(context, state, phone_number);
    }
}

PhoneStateListener Class

public class MyPhoneStateListener extends PhoneStateListener {

    private static int lastState = TelephonyManager.CALL_STATE_IDLE;
    private static Date callStartTime;
    private static boolean isIncoming;

    static boolean calledAlready = false;

    private DatabaseReference databaseReference;
    private Context ctx;


    public void onCallStateChanged(Context context, int state, String phoneNumber) {
        if (lastState == state) {
            //No change, debounce extras
            return;
        }

        ctx = context;

        System.out.println("Number inside onCallStateChange : " + phoneNumber);

        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();

                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                if (lastState != TelephonyManager.CALL_STATE_RINGING) {
                    isIncoming = false;
                    callStartTime = new Date();

                }
                break;

            case TelephonyManager.CALL_STATE_IDLE:
                //Went to idle-  this is the end of a call.  What type depends on previous state(s)
                if (lastState == TelephonyManager.CALL_STATE_RINGING) {
                    //Ring but no pickup-  a miss
                    waitforlastcalllog();

                } else if (isIncoming) {

                    //  Toast.makeText(context, "Incoming " + phoneNumber + " Call time " + callStartTime  , Toast.LENGTH_SHORT).show();

                    waitforlastcalllog();
                } else {

                    //  Toast.makeText(context, "outgoing " + phoneNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();

                    waitforlastcalllog();
                }

                break;
        }

        lastState = state;
    }

    private void waitforlastcalllog() {
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //String deviceMan = android.os.Build.MANUFACTURER;
                String deviceMan = Build.MANUFACTURER;

                String deviceName=deviceMan.toLowerCase();

                if(deviceName.equals("samsung"))
                {
                   // Toast.makeText(ctx, "dvv "+deviceMan, Toast.LENGTH_SHORT).show();
                    getCallLogs("samsung");
                }
                else
                {
                    getCallLogs("other");
                }


            }
        }, 500);

    }

    private void getCallLogs(String devicename) {

        ContentResolver cr = ctx.getContentResolver();
        if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        Cursor c = cr.query(CallLog.Calls.CONTENT_URI, null, null, null, null);

        if (c != null) {

            if(devicename.equals("samsung"))
            {
                if (c.moveToFirst()) { //starts pulling logs from last - you can use moveToFirst() for first logs
                    getCallDetails(c);
                }
            }else
            {
                if (c.moveToLast()) { //starts pulling logs from last - you can use moveToFirst() for first logs
                    getCallDetails(c);
                }
            }

            c.close();
        }
    }

    private void getCallDetails(Cursor c)
    {
        int totalCall=1;

        for (int j = 0; j < totalCall; j++) {

            String call_id = c.getString(c.getColumnIndexOrThrow(CallLog.Calls._ID));
            String phNumber = c.getString(c.getColumnIndexOrThrow(CallLog.Calls.NUMBER));
            String callDate = c.getString(c.getColumnIndexOrThrow(CallLog.Calls.DATE));
            String callDuration = c.getString(c.getColumnIndexOrThrow(CallLog.Calls.DURATION));
            Date dateFormat= new Date(Long.valueOf(callDate));
            String callDayTimes = String.valueOf(dateFormat);
            String callerName = c.getString(c.getColumnIndexOrThrow(CallLog.Calls.CACHED_NAME));


            String direction = null;
            switch (Integer.parseInt(c.getString(c.getColumnIndexOrThrow(CallLog.Calls.TYPE)))) {
                case CallLog.Calls.OUTGOING_TYPE:
                    direction = "OUTGOING";
                    break;
                case CallLog.Calls.INCOMING_TYPE:
                    direction = "INCOMING";
                    break;
                case CallLog.Calls.MISSED_TYPE:
                    direction = "MISSED";
                    break;
                case CallLog.Calls.VOICEMAIL_TYPE:
                    direction = "VOICEMAIL_TYPE";
                    break;
                case CallLog.Calls.REJECTED_TYPE:
                    direction = "REJECTED_TYPE";
                    break;
                case CallLog.Calls.BLOCKED_TYPE:
                    direction = "BLOCKED_TYPE";
                    break;
                case CallLog.Calls.ANSWERED_EXTERNALLY_TYPE:
                    direction = "ANS EXT TYPE";
                    break;
                default:
                    break;
            }

            c.moveToPrevious(); // if you used moveToFirst() for first logs, you should this line to moveToNext

            Toast.makeText(ctx, phNumber + callDuration + callDayTimes + direction +callerName , Toast.LENGTH_LONG).show(); // you can use strings in this line
            saveDatafromCursor(phNumber,callDuration,callDayTimes,direction,callerName);
        }
    }


    private void saveDatafromCursor(String phNumber, String callDuration, String callDayTimes, String direction,String callername)
    {
        ModelCursor mc=new ModelCursor();

        mc.setPhoneNumber(phNumber);
        mc.setCallDuration(callDuration);
        mc.setCallDayTimes(callDayTimes);
        mc.setDirection(direction);

        if(callername==null)
        {
            callername="Not in Contacts";
        }

        mc.setCallUsername(callername);


        if (!calledAlready) {
            FirebaseDatabase.getInstance().setPersistenceEnabled(true);
            calledAlready = true;
        }

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        databaseReference = database.getInstance().getReference().child("Call-Details-X");
        String key = databaseReference.push().getKey();

        String android_id = Settings.Secu

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...