android 如何寫一個service的分析與源碼

android 如何寫一個service呢
我想我們的基本流程是理清需求
構思狀態轉換圖
描述需求與代碼的功能
考慮功能的維護性
實施高內聚低耦合的思想
語言選擇與可移植選擇
我的這個例子
描述爲總體: 下位機 與 上位機 通訊,上位機通時要與上位機其它模塊通訊與業務處理
通訊功能:事實通訊 、有瞬間數據量大的問題、
其它模塊:接收上位機的信息、分發處理狀態並按需返回狀態
考慮爲:是一個常駐性service. 實現回調的機制
消息處理:誰接收、誰解析、誰處理的方法
負荷考慮:因爲功能太強大,模塊多,在一個service處理,負荷太重,代碼不清晰、結構複雜、高內聚低耦合
總體系統考慮:service沒有放在系統中,放在app中,闡明原因,android系統異常,要分析的要素很多
尤其自己還要負責驅動、硬件、系統。沒有球可踢。哈哈哈
必須保證硬件一致性時、驅動一致性時、系統一致性時、有問題明確爲上層問題、維護成本低
基本版本:一個線程  一個回調

public class xxxAppService extends Service implements Runnable, xxxCallback {
    private static final long MCU_SLEEP_DURIATION = 50;
    private static xxxAppService sInstance = null;
    private Context mContext;
    private SerialManager mSerialManager;
    private SerialPort mSerialPort;
    private ByteBuffer mRxBuffer;
    private boolean need_stop_mcu;
    private SerialBuffer mSerialBuffer;
    private static String TAG = "xxxAppService" ;
    private static String MCU_SERIAL_PORT = "/dev/ttyS1";
    private static String SERIAL_SERVICE = "serial";
    private Thread xxxxServiceThread;
    protected HashMap<Integer,Set<McuCallback>>mCallbacks;
    
    private AudioEffectControl mAudioEffectControl;
    private boolean mMuteFlag = false; /*true:mute, false:unmute*/
    private Timer mTimer = null;
    private MyTask mMyTask = null;

    private static boolean DEBUG_TX_RX = true;
    private static boolean DEBUG_PARSE = false;
    
     // constants
    public static final String OP_CODE = "op";    
    public static final String CMD_MSG = "cmd message";
    public static final String RES_ID = "response id";
    public static final String SHUTDOWN_PERIODS = "shutdown period";
    
      // operations ids for different service functionality.
     public static final int OP_CMD = 1;
     public   static final int OP_RESPONSE = 2;
     public   static final int OP_LAUNCH_APP = 3;
     public static final int OP_SHUTDOWN = 4;
     public   static final int OP_BOOT_COMPLETED = 5;
     public static final int OP_DELAYED_MSG = 6;
        
     protected static final int OP_PARSE = 7;
     protected static final int OP_RESTART_MCU_THREAD = 8;
     private static final int OP_INIT_BROADCAST = 9;
     private static final int OP_CAR_ACC = 10;
     private static final int OP_CAR_BRAKE = 11;
     private static final int OP_CAR_ILL = 12;
     private static final int OP_CAR_REVERSE = 13;
     public static final  int OP_SWITCH_AUDIO_CHANNEL  = 14;

      
        private static final String PACKAGE_NAME = "com.xxxxxx";
        private static final String MISC_ACTIVITY_NAME = PACKAGE_NAME  +".misc.MiscCarActivity";
        private static final boolean DEBUG_USER_KEY = true;
        protected static final String MCU_INIT_ACTION = "com.xxxxxx.xxxxService.Init";
        protected static final int ACC_OFF_PERIODS = 2000;
        public static final String AUDIO_CHANNEL = "audio channel";
        public static final String AUDIO_ON_OFF = "audio on off";
        public static final int AUDIO_CHANNEL_AUX = 0;
        public static final int AUDIO_CHANNEL_FM = 1;
        
        protected static final int ACC_LOST = 0;
        
        private BlockingQueue<byte[]> mMcuCmdQueue;
        private BlockingQueue<byte[]> mCpuCmdQueue;
        private Queue<Integer> mKeyQueue = new LinkedList<Integer>();  
        private Token mTxToken = null;
        private static final int MAX_CMD_LEN = 1024;
        protected static final int MAX_TX_TIMES = 50;
        private CarAction mCarAction = null;
        private McuUpdate mucupdater = null;
        
        private class Token {  
            
            byte cmd;
            
            public byte getCmd() {
                return cmd;
            }

            public void setCmd(byte cmd) {
                this.cmd = cmd;
            }

            public Token() {  
                 setCmd((byte)0x00);
             }
        }
        private Thread mRxThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while(!need_stop_mcu){
                    if(mMcuCmdQueue.isEmpty())
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }                    
                    byte[] cmd = null;
                    try {
                        cmd = mMcuCmdQueue.poll(2,TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }                    
                    if(cmd != null) {                        
                    //    dispatchCmd(cmd,cmd.length);
                    }
                    
                }
            }
            
        });
        
        private Thread mTxThread = new Thread(new Runnable() {        
            private void sendTxDataMultiCount(byte[] cmd, int count) {
                try {
                    for(int i = 0; i <  count; i++ ) {
                        sendData(cmd,cmd.length);
                        synchronized (mTxToken){                            
                            mTxToken.wait(500);                            
                            if(mTxToken.getCmd() == cmd[0]) 
                                break;
                            if(i > 0 )
                                Log.d(TAG, "resend  cmd = " + Utils.dump(cmd, cmd.length)
                                            + ", count = " + i);
                        }
                    }
                    synchronized (mTxToken){
                        mTxToken.setCmd((byte)0x00);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            @Override
            public void run() {
                while(!need_stop_mcu){
                    if(mCpuCmdQueue.isEmpty())
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }                    
                    byte[] cmd = null;
                    try {
                        cmd = mCpuCmdQueue.poll(2, TimeUnit.SECONDS);
                        //cmd = mCpuCmdQueue.take();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }                    
                    if(cmd != null) {                        
                        sendTxDataMultiCount(cmd,MAX_TX_TIMES);
                    }
                    
                }
            }
            
        });
        private Timer accTimer = null;
        private TimerTask accTimerTask = new TimerTask() {

            @Override
            public void run() {
                shutDown();
            }
            
        };
        private void shutDown() {
                Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");
                intent.putExtra("android.intent.extra.KEY_CONFIRM", false);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
            }
    
        private String hex2Time(byte[] buf, int index) {
            String time = String.format("%02d",buf[index++]) + "-" +
                    String.format("%02d",buf[index++]) + "-" + String.format("%02d",buf[index++])
                    +" " +     String.format("%02d",buf[index++]) + ":"
                    + String.format("%02d",buf[index++]);
            return time;
        }

    
     Handler mHandler = new Handler() {
            

            @Override
            public void handleMessage(Message msg) {
                
                switch(msg.arg1    ) {
                case OP_BOOT_COMPLETED:
                    Log.d(TAG, "boot completed");
                    break;
                case OP_CMD:
                    break;
                case OP_RESPONSE:
                    break;
                case OP_LAUNCH_APP:
                    Log.d(TAG, "launch");
                //    launchMiscApp();
                    break;
                case  OP_SHUTDOWN:
                    shutDown();
                    break;
                case OP_PARSE:
                     parseMessage();
                     break;
                case OP_RESTART_MCU_THREAD:
                     need_stop_mcu = true;
                     try {
                         xxxxServiceThread.join();
                         Thread.sleep(1000);
                         mSerialBuffer.lock();
                         mSerialBuffer.clear();
                         mSerialBuffer.unlock();
                         need_stop_mcu = true;
                         xxxxServiceThread.start();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }                    
                     break;
                case OP_INIT_BROADCAST:
                     Intent intent = new Intent();
                     intent.setAction(MCU_INIT_ACTION);  
                     byte[] buf = (byte[]) msg.obj;    
                     intent.putExtra("data", buf);
                     String mcu_version,radio_version;
                     mcu_version = String.format("%02x",buf[12]) + "/" 
                            + hex2Time(buf,16);
                     radio_version = String.format("%02d", buf[13])
                             + String.format("%02d", buf[14]);
                     System.out.println( Utils.dump(buf, buf.length));
                     SystemProperties.set("sys.mcu.version", mcu_version);
                     SystemProperties.set("sys.radio.version", radio_version);
                     intent.putExtra("msg", "Mcu works ok"); 
                     sendBroadcast(intent); 
                      
                    break;
                case OP_CAR_ACC:
                    Log.d(TAG, "you should turn off the screen");
                    if(msg.arg2 == ACC_LOST ) // off     
                    {
                        accTimer = new Timer(true);
                        accTimer.schedule(accTimerTask, ACC_OFF_PERIODS);
                    } else {
                        if(accTimer != null )
                            accTimer.cancel();
                    }
                    
                    break;
                case OP_CAR_BRAKE:
                    Log.d(TAG, "brake detect");
                    mCarAction.setBrake(msg.arg2 == 1);
                    break;
                case OP_CAR_ILL:
                    Log.d(TAG, "ill detect");
                    mCarAction.setIll(msg.arg2 == 1);
                    break;
                case OP_CAR_REVERSE:
                    Log.d(TAG, "reverse detect");
                    mCarAction.setReverse(msg.arg2 == 1);
                if (1 == msg.arg2) { /*1: start, 0: end*/
                    mAudioEffectControl.VolumeMute(true);
                } else if (0 == msg.arg2){
                    mAudioEffectControl.VolumeMute(false);
                }
                    break;
                case OP_SWITCH_AUDIO_CHANNEL:
                    int audio_channel = msg.arg2; 
                    boolean on_off = (Boolean) msg.obj;
                    switchAudio(audio_channel,on_off);
                    break;
                default:    
                    break;
                }
            }

            

        };
    private void switchAudio(int audio_channel, boolean on_off) {
            
            Intent intent=new Intent("com.auxservice.REMOTE_SERVICE");
            intent.putExtra("AModeSet",audio_channel);
            intent.putExtra("AOutSet",on_off?1:0);
            startService(intent);
     }

     
     
      public xxxAppService(){
             mCallbacks = new HashMap<Integer,Set<McuCallback>>();
             xxxProtocol.initCarKeyCodeMap();
        }
    @Override
    public void run() {
        int ret = 0;    
        mRxBuffer = ByteBuffer.allocateDirect(1024);
        while(!need_stop_mcu) {
            try {                
                mRxBuffer.clear();
    
                Thread.sleep(MCU_SLEEP_DURIATION);
                ret = mSerialPort.read(mRxBuffer);
                if(DEBUG_TX_RX)
                    Log.d(TAG,"MCU << " + Utils.dump(mRxBuffer.array(), ret));
                mSerialBuffer.lock();
                mSerialBuffer.putBuffer(mRxBuffer.array(), ret);
                mSerialBuffer.unlock();    
            //    if(DEBUG_TX_RX)
            //        Log.d(TAG,"availableByte = " + mSerialBuffer.availableByte());
                if(mSerialBuffer.availableByte() >= McuCmdType.MIN_PACKET_LEN  ) {                            
                    Message msg = mHandler.obtainMessage();
                    msg.arg1 = OP_PARSE;
                    mHandler.sendMessageDelayed(msg,10);
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                 Log.d(TAG,"mSerialBuffer error " + e);    
                 String str = mSerialBuffer.dump();                    
                Log.d(TAG,"mSerialBuffer = "+ str);
                 try {
                    Thread.sleep(9000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                 mSerialBuffer.lock();
                 mSerialBuffer.clear();
                 mSerialBuffer.unlock();
            }
        }
    }

    private byte calcChecksum(byte[] data, int offset,int datalen) {
        int sum = 0;
    
        if(offset >= datalen ) 
            throw new IndexOutOfBoundsException("offset=" + offset + ",datalen = " + datalen);
        for(int i = offset; i < datalen; i++) {
            sum += data[i];
        }
        return (byte)((sum ^ 0xFF) +1 );
    }

    public  void queueTxData(byte[] data, int datalen)
    {        
        Log.d(TAG,"queueTxData = " + Utils.dump(data, datalen) );
        mCpuCmdQueue.offer(data);
    }
    
    public  synchronized  void sendData(byte[] data, int datalen) throws IOException {
        ByteBuffer outputBuffer = ByteBuffer.allocateDirect(xxxProtocol.HEAD_LEN +  datalen + 1);
        outputBuffer.clear();

        outputBuffer.put(xxxProtocol.HEAD1);
        outputBuffer.put(xxxProtocol.HEAD2);
        outputBuffer.put( (byte) ( (0xff00 &  (datalen + 1) )  >> 8) );
        outputBuffer.put( (byte) (0xff &  (datalen + 1) )   );
        outputBuffer.put(data);
        byte checksum = calcChecksum(outputBuffer.array(), 2, xxxProtocol.HEAD_LEN + datalen);
        outputBuffer.put(checksum);
        mSerialPort.write(outputBuffer, xxxProtocol.HEAD_LEN +  datalen + 1);
        
        if(DEBUG_TX_RX)
            Log.d(TAG,"MCU >> " + Utils.dump(outputBuffer.array(),outputBuffer.array().length));
    }

    static public xxxAppService getInstance() {
            return sInstance;
        }

     @Override
     public void onStart(Intent intent, int startId) {
        
         if (intent == null) {
                return;
            }
         Bundle args = intent.getExtras();
         if (args == null) {
                return;
            }
        
          Message msg = mHandler.obtainMessage();
            msg.arg1 = args.getInt(OP_CODE);
            switch(msg.arg1) {
            case OP_CMD:
                msg.obj = args.getParcelable(CMD_MSG);
                break;
            case OP_RESPONSE:
                msg.obj = args;
                /* falls through */
            case OP_LAUNCH_APP:
                break;
            case OP_SHUTDOWN:
                break;
            case OP_BOOT_COMPLETED:
                break;
            case OP_SWITCH_AUDIO_CHANNEL:
                int audio_channel = args.getInt(AUDIO_CHANNEL); 
                boolean on_off = args.getBoolean(AUDIO_ON_OFF);
                msg.arg2 = audio_channel;
                msg.obj = on_off;
                break;
                
            default:
                return;
            }
            mHandler.sendMessage(msg);
            Log.d(TAG, "onStart");
         
         
     }
      @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            flags = START_STICKY;
            Log.d(TAG,"onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    @Override
    public IBinder onBind(Intent intent) {        
        Log.d(TAG,"bind");
        return null;
    }
    
     @Override
     public void onCreate() {    
         mContext = getBaseContext();
         mucupdater = new McuUpdate(mContext);
         Log.d(TAG, "onCreate");
         //open GPS
         Settings.Secure.setLocationProviderEnabled( getContentResolver(), LocationManager.GPS_PROVIDER, true);
         Utils.CopyAssetsFilesToDataFolder(mContext); // generate PinTables.txt 
         mCarAction = new CarAction(mContext);
         mCarAction.setBrake(true);
        // mMcuCmdQueue = new LinkedBlockingQueue<byte[]>(MAX_CMD_LEN);
        // mRxThread.start();
         
         mCpuCmdQueue = new LinkedBlockingQueue<byte[]>(MAX_CMD_LEN);
         mTxToken = new Token();
         mTxThread.start();

        mAudioEffectControl = new AudioEffectControl();
        mAudioEffectControl.VolumeInit();
        if (mTimer == null) {
            mTimer = new Timer();
            //startTimer();
        }

         mSerialManager = (SerialManager)getSystemService(SERIAL_SERVICE);
         try {
            mSerialPort = mSerialManager.openSerialPort(MCU_SERIAL_PORT, 115200);
            if (mSerialPort != null) {                
                xxxxServiceThread = new Thread(null,this,"MCU Thread");
                need_stop_mcu = false;
                mSerialBuffer = new SerialBuffer();
                xxxxServiceThread.start();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
         sInstance = this;
         registerMcuCallBack(McuCmdType.ADC_USERKEY_TYPE,this);
         registerMcuCallBack(McuCmdType.MISC_TYPE,this);         
         initMcu();
         muteOrUnmuteSpeaker(false);
            
     }
     private void initMcu() {
         final byte[] init_byte = {xxxProtocol.SYS_INIT_OK};
         queueTxData(init_byte,init_byte.length);        
    }


    @Override
     public void onDestroy() {
        
        Intent intent = new Intent("com.xxxxxx.xxxxService.destroy");
        sendBroadcast(intent);
        
         need_stop_mcu = true;
         try {
            xxxxServiceThread.join();
            mRxThread.join();
            mTxThread.join();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
         
         try {
            mSerialPort.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        unregisterMcuCallBack(this);
        super.onDestroy();
        Log.d(TAG,"onDestroy");
     }
     
     private boolean verifyChecksum(byte[] buf,int len) {
         try {
         int checksum = 0;;
         for(int i=0;i<len-1;i++){
             checksum += buf[i];
         }
         checksum ^= 0xFF;
         checksum += 1;
         
         return ((byte)checksum ==  buf[len-1]);
         
         } catch(Exception e) {
             System.err.print(e);
             return false;
         }
        
     }

     private void parseMessage() {
            byte[] cmd_buf;
            do {
                try {
                    mSerialBuffer.lock();
                    cmd_buf = mSerialBuffer.getAvailableCmdBuf();
                    mSerialBuffer.unlock();
                    if(cmd_buf == null) {                    
                        return;
                    }
                    if(verifyChecksum(cmd_buf,cmd_buf.length)) {
                        byte[] cmd =  Arrays.copyOfRange(cmd_buf,  xxxProtocol.LEN_LEN ,cmd_buf.length - 1) ;
                        dispatchCmd(cmd,cmd.length);
                    } else {
                        String str = Utils.dump(cmd_buf, cmd_buf.length );
                        Log.d(TAG,"verifychecksum error  " + str);
                    }
                } catch(Exception e) {
                    e.printStackTrace();
                }
            } while(true);
            
        }
    
    private void dispatchCmd(byte[] cmd_buf, int length) {
        int type;
        byte protocol  ;
        protocol = (byte) (cmd_buf[0] & 0xf0);
        if(DEBUG_PARSE){
            String str = Utils.dump(cmd_buf, cmd_buf.length);
            Log.d(TAG,"dispatchCmd "+ str);
        }
        switch(protocol ) {
            case xxxProtocol.RADIO_CMD:
                type = McuCmdType.RADIO_TYPE;
                break;
            case xxxProtocol.ADC_USERKEY_CMD:
                type = McuCmdType.ADC_USERKEY_TYPE;
                break;
            case xxxProtocol.MRPT_ACK_SYS_TYPE:    
                type = McuCmdType.MISC_TYPE;
                break;
            case xxxProtocol.MRPT_McuInIAP://cjb 2015-05-26 for mcu update
                type = McuCmdType.MCU_UPDATE_TYPE;
                break;
            case xxxProtocol.ADC_KEY_CONFIG_CMD://cjb 2015-05-05 add
                type = McuCmdType.STEER_CONTROL_TYPE;
                break;
            default:
                return;
        }
        Set<McuCallback> callbacks = mCallbacks.get(type);
        if(callbacks != null) {
                for(final McuCallback callback : callbacks){
                    callback.onRecv(cmd_buf, length);
                }
        }        
    }

    public void registerMcuCallBack(Integer type,McuCallback callback) {
        if(type == null) 
            throw new NullPointerException("type is null");
        if(callback == null)
            throw new NullPointerException("callback is null");
        Set<McuCallback> callbacks = mCallbacks.get(type);
        if (callbacks == null) {
            callbacks = new HashSet<McuCallback>();
            mCallbacks.put(type, callbacks);
        }
        callbacks.add(callback);

    }
    public void unregisterMcuCallBack(McuCallback callback) {
        for (final Integer type : mCallbacks.keySet()) {
            final Set<McuCallback> callbacks = mCallbacks.get(type);
            callbacks.remove(callback);
        }
    }
    
    
    private void sendKeyEvent(final int keyCode) {
        if(mKeyQueue.isEmpty())  {
            mKeyQueue.offer(keyCode);
             new Thread () {
                 @Override
                    public void run() {
                     while(!mKeyQueue.isEmpty()) {
                         final int key;
                         try {
                            key = mKeyQueue.poll();
                         } catch(Exception ex) {
                             Log.d(TAG, "ex = " + ex.getMessage());
                             break;
                         }
                         long now = SystemClock.uptimeMillis();
                         KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, key,0 ,
                                    0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                                    KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                                    InputDevice.SOURCE_KEYBOARD);
                            InputManager.getInstance().injectInputEvent(down,
                                      InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
                            
                            long up_time = SystemClock.uptimeMillis();
                            KeyEvent up = new KeyEvent(up_time, up_time, KeyEvent.ACTION_UP,key,0
                                       , 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                                        KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                                        InputDevice.SOURCE_KEYBOARD);
                            
                            InputManager.getInstance().injectInputEvent(up,
                                      InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);

                         
                         if(DEBUG_USER_KEY)
                             Log.d(TAG,"sendADCKey code = " +  keyCode + ",msecs = " + (SystemClock.uptimeMillis() - now));
                     }
                 }
            }.start(); 
        }  else 
            mKeyQueue.offer(keyCode);
    }

    private void processADCKey(byte adc_val) {
    
        int i;
        
        CarKeyCodeAction   carkey_action = xxxProtocol.CARKEYCODE_MAP.get(adc_val & 0xFF);
        if( carkey_action != null ) {
            Intent intent;            
            if(carkey_action.isPackage()) {                
                PackageManager packageManager = getPackageManager();   
                intent =packageManager.getLaunchIntentForPackage(carkey_action.getPackageNameForIntent()); 
            } else 
                intent = new Intent(carkey_action.getIntent());
            try {
                if(carkey_action.getIntent_extra() != null)
                    intent.putExtra(carkey_action.getIntent_extra(),(Boolean) carkey_action.getExtra_val());
                
                intent.setFlags(carkey_action.getIntent_flags());
            } catch(Exception ex) {
                ex.printStackTrace();
            }
            try {
                startActivity(intent); 
            } catch ( ActivityNotFoundException ex  ){
                ex.printStackTrace();
            }
            
            if(carkey_action.getMcuMessage()!=null) {            
                queueTxData(carkey_action.getMcuMessage(),carkey_action.getMcuMessage().length);
            }
            
        }  else {
            for(i= 0; i < xxxProtocol.KEYCODE_MAP.length ;i++) {
                if( (0xff & adc_val) ==  xxxProtocol.KEYCODE_MAP[i][0] ) {
                    switch (xxxProtocol.KEYCODE_MAP[i][0]) {
                    case 0x31: // volume mute
                        if (true == mMuteFlag) {
                            mAudioEffectControl.VolumeMute(false); /*unmute*/
                        } else {
                            mAudioEffectControl.VolumeMute(true); /*Mute*/
                        }
                        showVolumeDialog();
                        break;
                        
                    case 0x32: // volume add
                        mAudioEffectControl.controlVolume(true);
                        showVolumeDialog();
                        break;
                    
                    case 0x33: // volume sub
                        mAudioEffectControl.controlVolume(false);
                        showVolumeDialog();
                        break;

                    default:
                        sendKeyEvent(xxxProtocol.KEYCODE_MAP[i][1]);
                        break;
                    }
                }
            }
        }
        
    }
    
    @Override
    public void onRecv(byte[] buf, int len) {
        if(len >= 2 &&  (buf[0] == xxxProtocol.ADC_USERKEY_CMD ) ) {
            processADCKey(buf[1]);
        } else if (len >= 1 &&  ((byte)(buf[0] & 0xF0) == xxxProtocol.MRPT_ACK_SYS_TYPE ) ) {
            processSys(buf);
        }
    }

    private void muteOrUnmuteSpeaker(boolean on){
        byte[] buf = {xxxProtocol.SYS_MUTE,0x01};
        if(on) {
            buf[1] = 0x01;
        } else {
            buf[1] = 0x00;
        }
        queueTxData(buf,buf.length);
    }

    
    private void processSys(byte[] buf) {
        Message msg;
        switch(buf[0]) {
            case xxxProtocol.MRPT_ACK_SYS_INIT_DATA:
                //Bundle args = new Bundle();
                byte[] init_buf = new byte[buf.length-1];
                System.arraycopy(buf, 1, init_buf, 0,buf.length-1);
                msg = mHandler.obtainMessage();
                msg.arg1 = OP_INIT_BROADCAST;
                msg.obj  =  init_buf;
                mHandler.sendMessage(msg);
                break;
            case xxxProtocol.MRPT_SYS_CAR_ACC:
                if(buf.length >=2){
                    msg = mHandler.obtainMessage();
                    msg.arg1 = OP_CAR_ACC;
                    msg.arg2 = 0xFF & buf[1];
                    mHandler.sendMessage(msg);
                }
                break;
            case xxxProtocol.MRPT_SYS_CAR_REVERSE:
                if(buf.length >=2){
                    msg = mHandler.obtainMessage();
                    msg.arg1 = OP_CAR_REVERSE;
                    msg.arg2 = 0xFF & buf[1];
                    mHandler.sendMessage(msg);
                }
                break;
            case xxxProtocol.MRPT_SYS_CAR_BRAKE:
                if(buf.length >=2){
                    msg = mHandler.obtainMessage();
                    msg.arg1 = OP_CAR_BRAKE;
                    msg.arg2 = 0xFF & buf[1];
                    mHandler.sendMessage(msg);
                }
                break;
            case xxxProtocol.MRPT_SYS_CAR_ILL:
                if(buf.length >=2){
                    msg = mHandler.obtainMessage();
                    msg.arg1 = OP_CAR_ILL;
                    msg.arg2 = 0xFF & buf[1];
                    mHandler.sendMessage(msg);
                }
                break;
            case xxxProtocol.MRPT_ACK_SYS_ACK:
                synchronized (mTxToken){
                    mTxToken.setCmd(buf[1]);
                    mTxToken.notify();                    
                }
                break;        
            default:
                break;
        }
    }
    
    private boolean mFirstFlag = true;
    private boolean misHideFlag = true;
    private View mView;
    private AlertDialog.Builder mBuilder;
    private AlertDialog mDialog;
    private TextView mVolumeVol;
    private TextView mVolumeValue;
    private void showVolumeDialog() {
        if (mFirstFlag) {
            mView = View.inflate(mContext, R.layout.dialog_volume_adjust, null);
            mBuilder = new AlertDialog.Builder(mContext);
            mBuilder.setView(mView);
            mDialog = mBuilder.create();
            mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            mVolumeVol = (TextView) mView.findViewById(R.id.audiovoldialogtv);
            mVolumeValue = (TextView) mView.findViewById(R.id.audiovaluedialogtv);
            mFirstFlag = false;
//            mDialog.show();
        }
        
//        if (misHideFlag) {
            mDialog.show();
//            misHideFlag = false;
//        }

        if (0x0 != mAudioEffectControl.getVolumeNum()) {
            mVolumeVol.setText(R.string.adjustvolume);
            mVolumeValue.setText(String.valueOf(mAudioEffectControl.getVolumeNum()));
        } else {
            mVolumeVol.setText(R.string.adjustmute);
            mVolumeValue.setText("");
        }
        
        startTimer();
    }
    
    private void hideVolumeDialog() {
        misHideFlag = true;
        mDialog.dismiss();
    }
    
    private void startTimer() {
        if (mTimer != null) {
            if (mMyTask != null) {
                Log.d(TAG, "### cancel task");
                mMyTask.cancel();
            }
            Log.d(TAG, "### start task");
            mMyTask = new MyTask();
            mTimer.schedule(mMyTask, 3 * 1000);
        }
    }

    class MyTask extends TimerTask {
        @Override
        public void run() {
            Log.d(TAG, "####run ...");
            hideVolumeDialog();
        }
    }  
        
}
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章