que - kiosk app android
Android: ¿Tomando el control completo del teléfono(modo kiosco), es posible? ¿Cómo? (4)
Tenemos un programa que instalamos en los teléfonos y prestamos los teléfonos a los usuarios durante un cierto período. Nos gustaría que los teléfonos se utilicen únicamente para ejecutar nuestra aplicación (sin llamadas telefónicas, sin juegos, sin nada). Los teléfonos serán rooteados.
Entonces las cosas que necesitamos:
- Ejecutar en pantalla completa, nada más será visible
- El botón de inicio y otros botones del dispositivo no funcionarán
- Nuestra aplicación se ejecutará automáticamente al inicio
No tiene que ser "a prueba de hackers", pero debería ser suficiente para evitar que el usuario medio juegue con el dispositivo.
es posible? He hecho cosas similares en Symbian y Windows Mobile, pero no tengo mucha experiencia con esto en Android. ¿Cómo se puede lograr esto?
ACTUALIZACIÓN 2015: si no le importa limitar su aplicación a un único proveedor de telefonía, Samsung ha presentado KNOX SDK que le permite alcanzar el modo kiosco y mucho más fácilmente sin rootear el teléfono. Ver detalles en: https://seap.samsung.com/developer/sdk/knox-standard-android
@Vineet Shukla: El permiso READ_PHONE_STATE
no es suficiente para que funcione. También necesita el permiso CALL_PHONE
para finalizar la llamada.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
El MODIFY_PHONE_STATE
(según lo dicho por Zaki Choudhury) es un permiso del sistema y solo se puede usar en dispositivos rooteados y no es necesario para ninguna parte del código.
La solución de Vineet funciona. Sin embargo, creo que requiere dos permisos más que descubrí de here
Entonces los permisos necesarios son
android.permission.READ_PHONE_STATE, android.permission.MODIFY_PHONE_STATE, android.permission.CALL_PHONE
Aunque me funcionó así
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
También puedes echar un vistazo a esto: https://github.com/ligi/Setec-Astronomy disculpa por el autoenchufe sin vergüenza, pero tenemos problemas similares allí ;-)
Sí, es posible, pero no puede controlar el comportamiento de la Home key
de Home key
y la Home key
end call key
.
para pantalla completa agrega android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
a la etiqueta de actividad en el archivo de manifiesto.
Para deshabilitar la llamada entrante, necesita escuchar llamadas telefónicas:
import android.app.Service;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class MyPhoneStateListener extends Service{
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
StateListener phoneStateListener = new StateListener();
TelephonyManager telephonymanager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
telephonymanager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
class StateListener extends PhoneStateListener{
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
//Disconnect the call here...
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
}
}
};
@Override
public void onDestroy() {
}
}
Nota: Al detener el servicio, no intente eliminar el oyente y agregue estos permisos a su archivo de manifiesto:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
y desconecta la llamada de forma programática:
try{
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class c = Class.forName(manager.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephony = (ITelephony)m.invoke(manager);
telephony.endCall();
} catch(Exception e){
Log.d("",e.getMessage());
}
Nota: Agregue este archivo para desconectar la llamada: http://dl.dropbox.com/u/31740476/ITelephony.aidl
Para deshabilitar las claves que necesita anular:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(KeyEvent.KEYCODE_MENU == event.getKeyCode() || KeyEvent.KEYCODE_DPAD_LEFT==event.getKeyCode()
|| KeyEvent.KEYCODE_DPAD_DOWN==event.getKeyCode() || KeyEvent.KEYCODE_DPAD_RIGHT==event.getKeyCode()
|| KeyEvent.KEYCODE_DPAD_UP==event.getKeyCode() || KeyEvent.KEYCODE_DPAD_CENTER==event.getKeyCode()
|| KeyEvent.KEYCODE_BACK==event.getKeyCode())
{
return false;
}
return true;
}
Al presionar la tecla de inicio, aparecerá la pantalla de inicio, por lo que debe implementar un servicio y allí debe implementar un hilo infinito para reiniciar su aplicación de esta manera:
public class AppTrackingService extends Service {
private RunnableThread thread;
private Context ctx;
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(){
super.onCreate();
ctx = AppTrackingService.this;
thread = new RunnableThread();
}
public void onStart(Intent intent, int startid) {
try{
if(thread==null) thread = new RunnableThread();
thread.startThread();
}catch(Exception e){ }
}
class RunnableThread extends Thread {
Handler back_handler = new Handler();
boolean isContinue = false;
public RunnableThread(){
isContinue = false;
}
public void setIsContinue(boolean val){
this.isContinue = val;
}
public void startThread(){
isContinue = true;
start();
}
public void run(){
ActivityManager actMngr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
while(isContinue){
try{
//Maintain a boolean "isyourapprunning" to know if your app was running or not....
if(isyourapprunning){
String runningPkg = actMngr.getRunningTasks(1).get(0).topActivity.getPackageName();
if (!runningPkg.equals(ctx.getPackageName())){
launchApp(ctx.getPackageName());
}
Thread.sleep(2500); //2.5 secs
}else{
isContinue = false;
stopSelf();
}
}catch(Exception e){ }
}//end of while loop
}
protected void launchApp(String packageName) {
Intent mIntent = getPackageManager().getLaunchIntentForPackage(packageName);
mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
if (null != mIntent) {
try {
startActivity(mIntent);
} catch(Exception e) { }
}
}
}
}
EDITAR
Debería agregar el siguiente permiso para poder finalizar llamadas:
<uses-permission android:name="android.permission.CALL_PHONE" />
Y puede usar el siguiente archivo AIDL:
package com.android.internal.telephony;
/**
* Interface used to interact with the phone. Mostly this is used by the
* TelephonyManager class. A few places are still using this directly.
* Please clean them up if possible and use TelephonyManager instead.
*
* {@hide}
*/
interface ITelephony {
/**
* End call if there is a call in progress, otherwise does nothing.
*
* @return whether it hung up
*/
boolean endCall();
/**
* Silence the ringer if an incoming call is currently ringing.
* (If vibrating, stop the vibrator also.)
*
* It''s safe to call this if the ringer has already been silenced, or
* even if there''s no incoming call. (If so, this method will do nothing.)
*
* TODO: this should be a oneway call too (see above).
* (Actually *all* the methods here that return void can
* probably be oneway.)
*/
void silenceRinger();
}