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