首页 文章

Android:完全控制手机(自助服务终端模式),有可能吗?怎么样?

提问于
浏览
33

我们有一个程序,我们在手机上安装并将电话借给用户一段时间 . 我们希望这些手机仅用于运行我们的应用程序(没有电话,没有游戏,没有任何东西) . 手机将扎根 .

所以我们需要的东西:

  • 全屏运行,其他任何内容都不可见

  • 主页按钮和其他设备按钮不起作用

  • 我们的应用程序将在启动时自动运行

它不一定是“黑客证明”,但应足以防止普通用户弄乱设备 .

这可能吗?我在Symbian和Windows Mobile上做过类似的事情,但我对Android上的这些东西没有多少经验 . 怎么可能实现这一目标?

UPDATE 2015: 如果您不介意将您的应用程序限制为单一手机供应商,三星已推出KNOX SDK,可让您轻松实现自助服务终端模式,而无需支持手机 . 详情请见:https://seap.samsung.com/developer/sdk/knox-standard-android

4 回答

  • 5

    是的,但是你无法控制 Home keyend call key 的行为 .

    对于全屏,将 android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 添加到清单文件中的活动标记 .

    要禁用来电,您需要拨打电话:

    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() {
    
        }
    }
    

    注意:停止服务时不要删除侦听器并将这些权限添加到清单文件中:

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

    并以编程方式断开呼叫:

    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());
    }
    

    注意:添加此文件以断开呼叫:http://dl.dropbox.com/u/31740476/ITelephony.aidl

    要禁用密钥,您需要覆盖:

    @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;
    }
    

    在主页按键上会出现主屏幕,所以为了解决这个问题,您需要实现一项服务,您需要实现一个无限的线程来重新启动您的应用程序,如下所示:

    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) { }
                }
            }
        }
    }
    

    EDIT

    您需要添加以下权限才能结束通话:

    <uses-permission android:name="android.permission.CALL_PHONE" />
    

    您可以使用以下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();
    }
    
  • 47

    Vineet的解决方案有效 . 但是,我认为它需要两个以上的权限,我发现here

    所以需要的权限是

    android.permission.READ_PHONE_STATE,android.permission.MODIFY_PHONE_STATE,android.permission.CALL_PHONE

    虽然这样对我有用

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

    <uses-permission android:name="android.permission.CALL_PHONE"/>

  • 1

    你也可以看看这个:https://github.com/ligi/Setec-Astronomy对于无耻的自我插件感到抱歉但我们有相同的问题;-)

  • 1

    @Vineet Shukla: READ_PHONE_STATE 权限不足以使它工作 . 您还需要 CALL_PHONE 权限才能结束通话 .

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

    MODIFY_PHONE_STATE (如Zaki Choudhury所说)是系统权限,只能在有根设备上使用,代码的任何部分都不需要 .

相关问题