Java – How Android 5.1 and below run applications in the foreground

How Android 5.1 and below run applications in the foreground… here is a solution to the problem.

How Android 5.1 and below run applications in the foreground

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 works in the lollipop 5.1 version, in the low-end version running in the background.

I need to run the app in the foreground of all devices, how do I do 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 Recipients:

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");

}

}
}

Solution

Here are the steps to
resolve the issue
1) Create a Receiver listener call (PhoneStatReceiver.java
).
2) Create a service to display View (such as a timer View
) above your phone call View (HBFloatingHead.java).
3) Also create a timer in the HBFloatingHead service and update the window layout based on the timer.
4) Update your AndroidManifest .xml

Sample 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) **Update 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 annotated in the 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" />

Related Problems and Solutions