How to run a application in the foreground on Android versions below 5.1

浪尽此生 提交于 2019-12-22 08:50:51

问题


I have implemented a small timer application and it is starting whenever I received a call, Like after receiving an incoming call I am starting my timer application and displaying timer in foreground.

But it is working in lollipop 5.1 version in lower end version it is running in background.

I need to run application in foreground in all devices, how to achieve this?

My code:

Intent it = new Intent("intent.my.action");
it.setComponent(new ComponentName(context.getPackageName(), timer.class.getName()));
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(it);

My reciever:

public class CallerToActivity extends BroadcastReceiver {
    static boolean wasRinging = false;
    static boolean finish = false;
    SessionManager session;
    private boolean enable;

    public void onReceive(Context context, Intent intent) {
        session = new SessionManager(context);
        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        enable = session.Is_Enabled();
        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {

            Log.d("Status", "Phone is Ringing");
        } else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {

                    Intent it = new Intent("intent.my.action");
                    it.putExtra("Call", "true");
                    it.setComponent(new ComponentName(context.getPackageName(), timer.class.getName()));
                    it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.getApplicationContext().startActivity(it);



        } else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
            // Call Dropped or rejected
            Toast.makeText(context, "phone is neither ringing nor in a call",
                    Toast.LENGTH_SHORT).show();
            // wasRinging = false;
            finish = true;

            System.exit(0);
            Log.d("Status", "Phone is dropped");

        }

    }
}

回答1:


Here are the steps to solve your problem
1) Create Receiver to listen call (PhoneStatReceiver.java)
2) Create service to show view (Ex. Timer View) above your phone call view (HBFloatingHead.java)
3) Also create timer inside HBFloatingHead service and update window layout as per timer.
4) Update your AndroidManifest.xml

Example code: 1) PhoneStatReceiver.java

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;


public class PhoneStatReceiver extends BroadcastReceiver{

    private static final String TAG = "PhoneStatReceiver";

//        private static MyPhoneStateListener phoneListener = new MyPhoneStateListener();

    private static boolean incomingFlag = false;

    private static String incoming_number = null;

    @Override
    public void onReceive(Context context, Intent intent) {

        if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){
            incomingFlag = false;
            String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            Log.i(TAG, "call OUT:"+phoneNumber);
            startService(context);
        }else{

            TelephonyManager tm =
                    (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);

            switch (tm.getCallState()) {
                case TelephonyManager.CALL_STATE_RINGING:
                    incomingFlag = true;
                    incoming_number = intent.getStringExtra("incoming_number");
                    Log.i(TAG, "RINGING :"+ incoming_number);
                    startService(context);
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    if(incomingFlag){
                        Log.i(TAG, "incoming ACCEPT :"+ incoming_number);
                    }
                    break;

                case TelephonyManager.CALL_STATE_IDLE:
                    if(incomingFlag){
                        Log.i(TAG, "incoming IDLE");
                    }
                    break;
            }
        }
    }

    public void startService(Context context){
        Intent intent = new Intent(context, HBFloatingHead.class);
        context.startService(intent);
    }
}

2) **Updated HBFloatingHead.java**

 import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.TextView;

public class HBFloatingHead extends Service {

    private WindowManager mhbWindow;
    private TextView mfloatingHead;
    private Intent intent;
    public static final String BROADCAST_ACTION = "com.fragmentsample";


    private final IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        HBFloatingHead getService() {
            return HBFloatingHead.this;
        }
    }

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

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mfloatingHead != null) {
            mhbWindow.removeView(mfloatingHead);
            countDownTimer.cancel();
        }
    }

    WindowManager.LayoutParams params;

    @Override
    public void onCreate() {
        super.onCreate();
        intent = new Intent(BROADCAST_ACTION);

        mhbWindow = (WindowManager) getSystemService(WINDOW_SERVICE);
        mfloatingHead = new TextView(this);
        mfloatingHead.setBackgroundResource(R.drawable.floating4);
        mfloatingHead.setTextColor(Color.WHITE);
        mfloatingHead.setTextSize(20f);
        mfloatingHead.setHint("00.00 sec");
        mfloatingHead.setGravity(Gravity.CENTER);
        mfloatingHead.setPadding(20, 20, 20, 20);

        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 100;

        mhbWindow.addView(mfloatingHead, params);

        try {
            mfloatingHead.setOnTouchListener(new View.OnTouchListener() {

                private WindowManager.LayoutParams paramsF = params;
                private int initialX;
                private int initialY;
                private float initialTouchX;
                private float initialTouchY;

                @Override
                public boolean onTouch(View v, MotionEvent event) {

                    switch (event.getAction()) {
                        case MotionEvent.ACTION_UP:

                            break;

                        case MotionEvent.ACTION_DOWN:

                            initialX = paramsF.x;
                            initialY = paramsF.y;
                            initialTouchX = event.getRawX();
                            initialTouchY = event.getRawY();

                            break;

                        case MotionEvent.ACTION_MOVE:

                            paramsF.x = initialX
                                    + (int) (event.getRawX() - initialTouchX);
                            paramsF.y = initialY
                                    + (int) (event.getRawY() - initialTouchY);
                            mhbWindow.updateViewLayout(mfloatingHead, paramsF);

                            break;
                        default:
                            break;
                    }

                    return false;
                }
            });
        } catch (Exception e) {
            Log.e("#HB#", e.getMessage().toString());
        }

        mfloatingHead.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //HBFloatingHead.this.stopSelf();


            }
        });
        startTimer(1);
    }

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

        return START_STICKY;
    }

    android.os.Handler handler = new android.os.Handler(new android.os.Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            try {
                long seconds = msg.what;
                String text = String.format("%02d", seconds / 60) + ":"
                        + String.format("%02d", seconds % 60);
                Log.e("TAG", "Updated text : " + text);
                mfloatingHead.setText(text);
                mhbWindow.updateViewLayout(mfloatingHead, params);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    });

    CountDownTimer countDownTimer;

    private void startTimer(final int minuti) {
        countDownTimer = new CountDownTimer(60 * minuti * 1000, 500) {
            @Override
            public void onTick(long millisUntilFinished) {
                int seconds = (int) (millisUntilFinished / 1000);

                if (seconds > 0)
                    handler.sendEmptyMessage(seconds);
                else
                    HBFloatingHead.this.stopSelf();

//              Log.d("TIME", mTvTime.getText().toString());
            }

            @Override
            public void onFinish() {

            }
        };

        countDownTimer.start();
    }
}


3) Create your layout as commented in HBFloatingService class
4) Update your AndroidManifest.xml

Add Permissions

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE">     </uses-permission>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission> 


Declare your Android components

 <receiver android:name=".PhoneStatReceiver">
      <intent-filter>
         <action android:name="android.intent.action.PHONE_STATE" />
         <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
      </intent-filter>
 </receiver>

 <service
      android:name=".HBFloatingHead"
      android:exported="true" />


来源:https://stackoverflow.com/questions/34409102/how-to-run-a-application-in-the-foreground-on-android-versions-below-5-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!