updateperiodmillis studio example android android-layout android-widget broadcastreceiver android-broadcast

updateperiodmillis - android studio widget example



Ventana emergente sobre la pantalla de llamada entrante nativa de Android como la aplicaciĆ³n real de Android (11)

Estoy desarrollando un receptor de difusión para llamadas entrantes en Android y para recibir llamadas entrantes quiero inflar una ventana emergente sobre la pantalla de llamadas entrantes nativas.

Completé ese código. Pero ahora el problema es que en el nivel 17 de la API de Android 4.1 (Jelly Bean) cuando suena un teléfono, el PHONE_STATE viene como OFF HOOK , y si estoy llamando a una actividad, se llama, pero el código debajo no lo hace ser ejecutado Estoy enumerando el código:

Mi receptor de difusión

package com.example.popwindowonincomingcallscreen; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.TelephonyManager; import android.util.Log; public class IncomingBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("IncomingBroadcastReceiver: onReceive: ", "flag1"); String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); Log.d("IncomingBroadcastReceiver: onReceive: ", state); if (state.equals(TelephonyManager.EXTRA_STATE_RINGING) || state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { Log.d("Ringing", "Phone is ringing"); Intent i = new Intent(context, IncomingCallActivity.class); i.putExtras(intent); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); Wait.oneSec(); context.startActivity(i); } } }

Una actividad que estoy llamando:

import android.app.Activity; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; import android.view.View.MeasureSpec; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; public class IncomingCallActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { try { Log.d("IncomingCallActivity: onCreate: ", "flag2"); */ After this line, the code is not executed in Android 4.1 (Jelly Bean) only/* // TODO Auto-generated method stub super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); getWindow().addFlags( WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); Log.d("IncomingCallActivity: onCreate: ", "flagy"); setContentView(R.layout.main); Log.d("IncomingCallActivity: onCreate: ", "flagz"); String number = getIntent().getStringExtra( TelephonyManager.EXTRA_INCOMING_NUMBER); TextView text = (TextView) findViewById(R.id.text); text.setText("Incoming call from " + number); } catch (Exception e) { Log.d("Exception", e.toString()); // TODO Auto-generated catch block e.printStackTrace(); } } }

Después

try { Log.d("IncomingCallActivity: onCreate: ", "flag2"); }

El código no se está ejecutando en Android 4.1 (Jelly Bean), pero en otras versiones está funcionando.

He intentado casi todas las formas en que puedo hacerlo. Este código muestra una actividad translúcida sobre la pantalla de llamada nativa y no bloquea los controles de fondo, como levantar el teléfono. Pero lo quiero como verdadero llamador. He adjuntado una instantánea de cómo la persona que llama muestra una ventana en la pantalla de llamadas entrantes.

¿Cómo puedo lograr esta funcionalidad para una aplicación de Android?

Así es como funciona una verdadera persona que llama:

Mi producto actual:

Actualización 1

Después de la recompensa también, no estoy obteniendo exactamente lo que estoy buscando, pero volveré a todos; Estoy trabajando en eso. De todos modos, este código funciona para la mayoría de los teléfonos con Android. Si alguien va a utilizar y atrapar la solución, escriba aquí para que todos puedan obtener el beneficio.

Actualización 2

Traté de implementar Toast en el método onReceive del receptor de difusión porque toast es un componente nativo de Android, pero tampoco se muestra en Android 4.1 (Jelly Bean).

Mi idea era implementar Toast en el método onReceive del receptor de difusión y luego cambiar su diseño según nuestras necesidades y ajustar su duración de visualización. Pero un problema más es que findViewById no funciona en el receptor de difusión, por lo que creo que tenemos que hacer un LinearLayout programáticamente para personalizar el brindis.


Acabo de probar en el emulador de Android 4.2 (Jelly Bean) , y funciona perfectamente bloqueando toda la pantalla de llamadas entrantes como truecaller:

public void onReceive(Context context, Intent intent) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT); params.height = LayoutParams.MATCH_PARENT; params.width = LayoutParams.MATCH_PARENT; params.format = PixelFormat.TRANSLUCENT; params.gravity = Gravity.TOP; LinearLayout ly = new LinearLayout(context); ly.setBackgroundColor(Color.RED); ly.setOrientation(LinearLayout.VERTICAL); wm.addView(ly, params); }

En el manifiesto:

<receiver android:name="" android:enabled="true" > <intent-filter android:priority="-1"> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver>


Creo que no deberías comenzar la actividad para lograr el resultado descrito. Necesita una vista separada que tenga LayoutParams.TYPE_SYSTEM_OVERLAY establecido en sus parámetros de diseño.

Puede colocar esta vista donde desee en la pantalla, o simplemente cubrir toda la pantalla.

Aquí hay algunas líneas de código:

_av = new ActivatorView(this); _avLayoutParams = new WindowManager.LayoutParams(0, 0, 0, 0, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.OPAQUE); _avLayoutParams.screenBrightness = _fScreenBrightness = 20f; WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); wm.addView(_av, _avLayoutParams);

https://bitbucket.org/gyrussolutions/yaab/src/f01cc8aff690cae1b1107287cb17835b8a3c1643/src/biz/gyrus/yaab/LightMonitorService.java?at=default#cl-338 - el código fuente completo, considérelo una muestra.


Estoy intentando algo similar, agregando un botón adicional a la pantalla de llamadas entrantes.

La respuesta que Sam Adams publicó está funcionando para mí, aunque estoy llamando al código de un PhoneStateListener. Aparte de eso, la única diferencia real en su código es que estoy inflando un diseño:

overlay = (RelativeLayout) inflater.inflate(R.layout.overlay, null); wm.addView(overlay, params);

Está funcionando tanto en emuladores como en un HTC One S (con Android 4.1.1).

Algo que debe tener en cuenta es mantener una referencia a la vista de superposición que está agregando, y eliminarla de nuevo (llamar a removeView () en la instancia de windowmanager) cuando el teléfono vuelva a estar inactivo (cuando el oyente reciba TelephonyManager.CALL_STATE_IDLE), de lo contrario su superposición permanecerá en la pantalla.

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if(overlay!=null) { wm.removeView(overlay); overlay = null; }


Mi método:

  1. usar el receptor para recibir eventos de llamada telefónica
  2. use el servicio para hacer la superposición

    ps:wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;


No estoy seguro de que su GUI personalizada siempre estará encima de la predeterminada, porque el receptor de difusión del sistema y su receptor están tratando de mostrar su GUI en la parte superior de la pantalla. No estamos seguros de cuál es el primero que se llama, pero un trabajo complicado para hacer que su GUI aparezca en la parte superior de la pantalla es cuando el teléfono está sonando llama a su actividad después de 1-2 segundos de uso del controlador para eso.

new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Intent intent = new Intent(context, AcceptReject.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } }, 2000);

Espero que te pueda ayudar.


Pruebe el código antes del método super.onCreate . Creo que después de llamar al súper se omite el código. En algún momento este tipo de trucos funcionó para mí.


También estoy trabajando en eso (podría estar equivocado al entenderte aquí). Lo que desea lograr es mostrar esa actividad en Android 4.2 (Jelly Bean). Acabo de colocar un retraso para mostrar la actividad. He usado PhoneStateListener en diferentes clases. Puedo mostrar nueva actividad en la pantalla de la persona que llama. Aquí está mi código completo:

Archivo MyBroadcastReceiver.java

public class MyBroadcastReceiver extends BroadcastReceiver { static CustomPhoneStateListener phoneStateListener; Context context; Intent intent; @Override public void onReceive(Context context, Intent intent) { this.context = context; this.intent = intent; // TODO Auto-generated method stub TelephonyManager telephonyManager = (TelephonyManager) context .getSystemService(Context.TELEPHONY_SERVICE); phoneStateListener = new CustomPhoneStateListener(context); telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } }

Archivo CustomPhoneStateListener.java

public class CustomPhoneStateListener extends PhoneStateListener { // private static final String TAG = "PhoneStateChanged"; Context context; // Context to make Toast if required private AudioManager amanager; Intent i1; public CustomPhoneStateListener(Context context) { super(); this.context = context; i1 = new Intent(context, YourActivity.class); i1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); } @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: Toast.makeText(context, "Phone state Idle", Toast.LENGTH_LONG) .show(); break; case TelephonyManager.CALL_STATE_OFFHOOK: Toast.makeText(context, "Phone state Off hook", Toast.LENGTH_LONG) .show(); break; case TelephonyManager.CALL_STATE_RINGING: try { Thread.sleep(3000); context.startActivity(i1); } catch (Exception e) { e.getLocalizedMessage(); } default: break; } }

y YourActivity se mantendrá como lo ha creado ... Nota: También estoy enfrentando algunos problemas en este código.

  1. Cuando la llamada cerrada es clolse (llamada perdida o rechazada), la actividad no se cierra.
  2. No puedo hacer clic en Actividad (quiero poner un botón allí para mi aplicación)
  3. Funciona solo la primera vez. Cuando llamo por segunda vez, mi aplicación se detiene (creo que se debe a que la actividad no se cierra cuando se cierra la llamada).

(Ayuda aceptada para estos problemas. Gracias. Podría ayudar a alguien)

ACTUALIZAR

AQUÍ ESTÁ EL ENLACE DE LA PEQUEÑA DEMO COMO LOGRAR ESTO.

  1. Cuando la llamada cerrada es clolse (llamada perdida o rechazada), la actividad no se cierra. - SOLUCIONADO
  2. No puedo hacer clic en Actividad (quiero poner un botón allí para mi aplicación) - SOLUCIONADO
  3. Funciona solo la primera vez. Cuando llamo por segunda vez, mi aplicación se detiene (creo que es porque la actividad no se cierra cuando se descarta la llamada) - SOLUCIONADO

También nos enfrentamos a un problema similar que la superposición no se muestra en un dispositivo con bloqueo de pin. La solución que funcionó para nosotros es la siguiente:

mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mParams = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_SYSTEM_ERROR, LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);

Fue LayoutParams.TYPE_SYSTEM_ERROR que marcó la diferencia.


Use un receptor de difusión simple y coloque este código en el receptor de difusión:

public void onReceive(final Context context, final Intent intent) { Log.v(LOG_TAG, "Receieved notification about network status"); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT); params.height = WindowManager.LayoutParams.MATCH_PARENT; params.width = WindowManager.LayoutParams.MATCH_PARENT; params.format = PixelFormat.TRANSLUCENT; params.gravity = Gravity.TOP; LinearLayout ly = new LinearLayout(context); ly.setBackgroundColor(Color.RED); ly.setOrientation(LinearLayout.VERTICAL); wm.addView(ly, params); }


prueba esto

AlertDialog.Builder builder = new AlertDialog.Builder(context.getApplicationContext()); LayoutInflater inflater = LayoutInflater.from(context); View dialogView = inflater.inflate(R.layout.caller_dialog, null); ImageView button = dialogView.findViewById(R.id.close_btn); builder.setView(dialogView); final AlertDialog alert = builder.create(); alert.getWindow().requestFeature(Window.FEATURE_NO_TITLE); alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE); alert.setCanceledOnTouchOutside(true); alert.show(); WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); Window window = alert.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); window.setGravity(Gravity.TOP); lp.copyFrom(window.getAttributes()); //This makes the dialog take up the full width lp.width = WindowManager.LayoutParams.MATCH_PARENT; lp.height = WindowManager.LayoutParams.WRAP_CONTENT; window.setAttributes(lp); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //close the service and remove the from from the window alert.dismiss(); } });


new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Intent i = new Intent(context, CallingIncoming.class); i.putExtras(intent); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK /*| Intent.FLAG_ACTIVITY_CLEAR_TASK*/); context.startActivity(i); } }, 450);//It will help you to delay your screen and after it your screen will be top of default app screen