Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android小項目藍牙電子鐘

Android小項目藍牙電子鐘

編輯:關於Android編程

Android小項目藍牙電子鐘

請支持原創,尊重原創,轉載請注明出處:http://blog.csdn.net/kangweijian(來自kangweijian的csdn博客)

  1. Android藍牙電子鐘應用程序通過藍牙設備發送消息給多功能數字電子鐘,實現更新電子鐘時間、設定電子鐘監控時間、設定電子鐘鬧鐘時間和調整電子鐘時間誤差等功能。
  2. 該應用程序的UI主要基於http://blog.csdn.net/kangweijian/article/details/43404801。
  3. 本章主要講解藍牙設備的應用,包括藍牙設備獲取、啟用、搜索、配對、連接、發送、接收等。

    最終效果圖

    前四個效果圖可通過左右滑動或者點擊頂層四個控件切換得,點擊連接按鈕得到查找藍牙設備的效果圖
    這裡寫圖片描述 這裡寫圖片描述這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述


    主Activity(MainActivity.java)


    設定MainActivity的視圖,該視圖頂層4個Button,底層2個Button,中間一個fragment碎片,設定fragment碎片為ViewPager視圖
    BluetoothAdapter.getDefaultAdapter()獲取本地藍牙設備,如果本地藍牙設備為空,則提示信息,並結束程序
    .enable(),打開本地藍牙適配器。
    連接按鈕實例化,並設置點擊監聽器。該監聽器函數中,如果.isEnabled()本地藍牙未啟用,則提示信息,本返回。如果BluetoothSocket為null,則使用startActivityFZ喎?/kf/ware/vc/" target="_blank" class="keylink">vclJlc3VsdCguLinM+Neqtb3AttHAyeixuLLp1dJBY3Rpdml0eaOst/HU8su1w/dTb2NrZXTS0cGsvdOjrLTLyrHU8tKqts+/qlNvY2tldMGsvdOhozxicj4Kzcuz9rC0xaXKtcD9u6+jrLKiyejWw7Xju/e84Mz9xveho9K7tam147v3vLTNy7P2s8zQ8qGjPGJyPgpvbkFjdGl2aXR5UmVzdWx0KKGtKbqvyv3W0KOs0ru1qURldmljZUxpc3RBY3Rpdml0ebe1u9i94bn7zqpBY3Rpdml0eS5SRVNVTFRfT0ujrNTy08lJbnRlbnQuZ2V0RXh0cmFzKCkuZ2V0U3RyaW5nKCm6r8r9tcO1vURldmljZUxpc3RBY3Rpdml0ebSrtd25/cC0tcTUtrPMwLbRwMnosbi12Na3o6zTyUJsdWV0b290aERldmljZS5nZXRSZW1vdGVEZXZpY2UoYWRkcmVzcym1w7W91LazzMC20cDJ6LG4o6zTyUJsdWV0b290aERldmljZS5jcmVhdGVSZmNvbW1Tb2NrZXRUb1NlcnZpY2VSZWNvcmQoVVVJRC5mcm9tU3RyaW5nKFVVSUQpKbqvyv21w7W9Qmx1ZXRvb3RoU29ja2V0o6zX7rrz08lCbHVldG9vdGhTb2NrZXQKIGNvbm5lY3QoKbqvyv3BrL3Tsb612MC20cDJ6LG4us3UtrPMwLbRwMnosbihozxicj4K1+6687zHtcPU2kFjdGl2aXR5yfrD/Nbcxtq1xG9uRGVzdHJveSgp1tCjrC5jbG9zZSgpudix1UJsdWV0b290aFNvY2tldMGsvdMsLmRpc2FibGUoKbnYsdVCbHVldG9vdGhBZGFwdGVywLbRwLf+zvGho9LRsaPWpNTas8zQ8s3Ls/a686Osys23xbXXsuPJ6LG4vuSx+qGjPGJyPgqyubPky7XD96O6yrnTw3N0YXJ0QWN0aXZpdHlGb3JSZXN1bHQoLi4pzPjXqkFjdGl2aXR5tcTX99PDysdNYWluQWN0aXZpdHnQ6NKq1NpEZXZpY2VMaXN0QWN0aXZpdHnW0Na00NDIzs7xo6xEZXZpY2VMaXN0QWN0aXZpdHnWtNDQyM7O8c3qsc+687e1u9i94bn7uPhNYWluQWN0aXZpdHmjrE1haW5BY3Rpdml0edTab25BY3Rpdml0eVJlc3VsdCihrSnW0LXDtb3L+dDotcS94bn7oaNvbkFjdGl2aXR5UmVzdWx0KKGtKdbQ09DI/bj2ss7K/aOstdrSu7j2ss7K/crHx+vH87T6wutyZXF1ZXN0Q29kZaOsysfTyU1haW5BY3Rpdml0ebeis/ajrLXatv649rLOyv3Kx73hyvi0+sLrcmVzdWx0Q29kZaOsysfTyURldmljZUxpc3RBY3Rpdml0ebe1u9ijrNfuuvPSu7j2ss7K/crHSW50ZW50oaO5ytTab25BY3Rpdml0eVJlc3VsdCihrSm6r8r91tCjrMrXz8jF0LbPcmVxdWVzdENvZGWjrLy0xdC2z01haW5BY3Rpdml0ecfrx/PExLj2QWN0aXZpdHnWtNDQyM7O8aOsxuS0ztTZxdC2z3Jlc3VsdENvZGWjrLy0xdC2z8THuPZBY3Rpdml0eda00NDIzs7xuvO3tbvYwcu6ztbWveG5+6GjPGJyPgpwYWNrYWdlIGNvbS5leGFtcGxlLnRpbWVyYmx1ZXRvb3RoMi5BY3Rpdml0eTs8YnI+CjxwcmUgY2xhc3M9"brush:java;"> import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.example.timerbluetooth2.R; import com.example.timerbluetooth2.Fragment.ViewPagerFragment; public class MainActivity extends FragmentActivity { private final static int REQUEST_CONNECT_DEVICE = 1; //宏定義查詢設備句柄 private final static String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; //SPP服務UUID號 private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); //獲取本地藍牙適配器,即藍牙設備 private InputStream is; //輸入流,用來接收藍牙數據 private OutputStream os; //輸出流,用來發送藍牙數據 BluetoothDevice _device = null; //藍牙設備 public BluetoothSocket _socket = null; //藍牙通信socket private Button connectButton,quitButton; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); //設置MainActivity視圖 setContentView(R.layout.activity_main); //設置fragment碎片為ViewPager視圖 FragmentManager fm = getSupportFragmentManager(); android.support.v4.app.Fragment fragment= fm.findFragmentById(R.id.fragmentContainer); if (fragment==null) { fragment = new ViewPagerFragment(); fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit(); } //如果本地藍牙設備為空,提示信息,結束程序 if (_bluetooth == null){ Toast.makeText(this, "無法打開手機藍牙,請確認手機是否有藍牙功能!", Toast.LENGTH_LONG).show(); finish(); return; } //設置設備可以被搜索 new Thread(){ public void run(){ if(_bluetooth.isEnabled()==false){ _bluetooth.enable(); } } }.start(); connectButton = (Button) findViewById(R.id.ConnectButton); quitButton = (Button) findViewById(R.id.QuitButton); connectButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //如果藍牙服務不可用則提示 if(_bluetooth.isEnabled()==false){ Toast.makeText(MainActivity.this, " 打開藍牙中...", Toast.LENGTH_LONG).show(); return; } //如未連接設備則打開DeviceListActivity進行設備搜索 if(_socket==null){ Intent serverIntent = new Intent(MainActivity.this, DeviceListActivity.class); //跳轉程序設置 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); //設置返回宏定義 } else{ //關閉連接socket try{ is.close(); _socket.close(); _socket = null; connectButton.setText("連接"); }catch(IOException e){} } } }); quitButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub finish(); } }); } //接收活動結果,響應startActivityForResult() public void onActivityResult(int requestCode, int resultCode, Intent data) { switch(requestCode){ // 響應返回結果//連接結果,由DeviceListActivity設置返回 case REQUEST_CONNECT_DEVICE: //連接成功,由DeviceListActivity設置返回 if (resultCode == Activity.RESULT_OK) { // MAC地址,由DeviceListActivity設置返回 String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); // 得到遠程藍牙設備句柄 _device = _bluetooth.getRemoteDevice(address); // 用服務號得到socket try{ _socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID)); }catch(IOException e){ Toast.makeText(this, "連接失敗!", Toast.LENGTH_SHORT).show(); } //連接socket try{ _socket.connect(); Toast.makeText(this, "連接"+_device.getName()+"成功!", Toast.LENGTH_SHORT).show(); connectButton.setText("斷開"); }catch(IOException e){ try{ Toast.makeText(this, "連接失敗!", Toast.LENGTH_SHORT).show(); _socket.close(); _socket = null; }catch(IOException ee){ Toast.makeText(this, "連接失敗!", Toast.LENGTH_SHORT).show(); } return; } // //打開接收線程 // try{ // is = _socket.getInputStream(); //得到藍牙數據輸入流 // ReadThread.start(); // }catch(IOException e){ // Toast.makeText(this, "接收數據失敗!", Toast.LENGTH_SHORT).show(); // return; // } } break; default:break; } } //接收數據線程 // Thread ReadThread=new Thread(){ // // public void run(){ // // try { // // while (!Thread.interrupted()) { // // // the number of bytes that can be read from the input stream without blocking. // // 返回輸入流中可被讀取的字節數 // int count = is.available(); // if (count <= 0) { // Thread.sleep(10); // continue;//等待有效數據讀取 // } // // // create buffer // byte[] buf = new byte[count]; // // // read data into buffer // is.read(buf); // // // // // } // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (NullPointerException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (Exception e) { // // TODO: handle exception // } // } // }; //關閉程序掉用處理部分 public void onDestroy(){ super.onDestroy(); //如果Socket不為空,則關閉連接Socket if(_socket!=null) try{ _socket.close(); }catch(IOException e){} //關閉藍牙服務 _bluetooth.disable(); } }
    藍牙設備查找Activity(DeviceListActivity.java)

    設定DeviceListActivity的視圖,使用LinearLayout布局,從上到下,已配對設備的TextView和ListView、未配對設備的TextView和ListView,最後一個查找設備Button和一個取消Button。除了兩個Button,其他的可見性都為隱藏。
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)設定Activity應用程序窗口顯示特性為:不確定的進度
    設定startActivityForResult的默認返回值為Activity.RESULT_CANCELED
    掃描按鈕實例化,並設置點擊監聽器。該監聽器函數中,設置按鈕可見性為隱藏,並開始服務和設備的查找。首先設置在Activity窗口的標題欄顯示進度條的效果,設置標題欄的標題為”查找設備中”,以及設置未配對設備的可見性為可見。BluetoothAdapter.getDefaultAdapter()獲取本地藍牙設備,然後由.startDiscovery()函數開始對遠程設備進行查找。
    取消按鈕實例化,並設置點擊監聽器。一旦點擊即退出程序。
    已配對設備適配器和已配對設備視圖實例化,已配對視圖添加已配對適配器,並設置點擊監聽器OnItemClickListener()。該監聽器函數中,首先由BluetoothAdapter調用.cancelDiscovery()函數取消當前的設備發現查找進程。然後由OnItemClickListener()的第二個參數((TextView)View).getText().toString()得到遠程藍牙設備地址字符串,如果該地址等於NO_FOUND_DEVICE “沒有找到新設備”,則提示消息,並返回。如果不是,則取出該String.substring(s.length() - 17)字符串的最後17個字符,返回程序,設定startActivityForResult的默認返回值為Activity.RESULT_OK。
    未配對設備適配器和未配對設備視圖同上。
    注冊查找到設備action的廣播接收器IntentFilter filter = newIntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver,filter);注冊查找結束action的廣播接收器filter = new IntentFilter(BluetoothAdapter. ACTION_DISCOVERY_FINISHED);this.registerReceiver(mReceiver, filter);
    廣播接收器中,監聽查找到設備和查找結束action。。。
    最後記得在Activity生命周期的onDestroy()中,BluetoothAdapter.cancelDiscovery()取消當前的設備發現查找進程。注銷action接收器 this.unregisterReceiver(mReceiver);
    package com.example.timerbluetooth2.Activity;

    import com.example.timerbluetooth2.*; 
    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.View.OnClickListener;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.Toast;
    public class DeviceListActivity extends Activity { 
        // 返回時數據標簽
        public static String EXTRA_DEVICE_ADDRESS = "設備地址";
        public final static String NO_FOUND_DEVICE = "沒有找到新設備";
        // 本地的藍牙適配器設備,BluetoothAdapter類讓用戶能執行基本的藍牙任務
        private BluetoothAdapter mBtAdapter;
        // 數組適配器,存入String集合,代表已配對和未配對的藍牙設備的地址
        private ArrayAdapter mPairedDevicesArrayAdapter;
        private ArrayAdapter mNewDevicesArrayAdapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // Android應用程序的窗體顯示,設置其特性為:不確定的進度
            requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);   
            setContentView(R.layout.device_list);
    
            // 設定startActivityForResult的默認返回值為取消
            setResult(Activity.RESULT_CANCELED);
            // 掃描按鈕實例化 
            Button scanButton = (Button) findViewById(R.id.button_scan);
            // 設置掃描按鈕點擊監聽器
            scanButton.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    //開始服務和設備查找
                    doDiscovery();
                    //設置按鈕可見性為隱藏
                    v.setVisibility(View.GONE);
                }
            });
            // 取消按鈕實例化
            Button cancelButton = (Button) findViewById(R.id.button_cancel);
            // 設置取消按鈕點擊監聽器
            cancelButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub 
                    finish();
                }
            });
            // 已配對設備適配器實例化
            mPairedDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name);
            // 新的未配對過的設備適配器實例化
            mNewDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name);
            // 已配對視圖實例化
            ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
            // 已配對視圖添加適配器
            pairedListView.setAdapter(mPairedDevicesArrayAdapter);
            // 已配對視圖設置點擊監聽器
            pairedListView.setOnItemClickListener(mDeviceClickListener);
            // 新的未配對過的視圖實例化
            ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
            // 新的未配對過的視圖添加適配器
            newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
            // 新的未配對過的視圖設置點擊監聽器
            newDevicesListView.setOnItemClickListener(mDeviceClickListener);
            // 注冊接收查找到設備action接收器
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            this.registerReceiver(mReceiver, filter);
            // 注冊查找結束action接收器
            filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
            this.registerReceiver(mReceiver, filter);
            // 獲取默認本地藍牙適配器的操作權限
            mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        }
    
        /***************************************************************************
         * 
         * Activity銷毀時
         * 
         */
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 關閉服務查找
            if (mBtAdapter != null) {
                mBtAdapter.cancelDiscovery();
            }
            // 注銷action接收器
            this.unregisterReceiver(mReceiver);
        }
    
        /****************************************************************************
         * 
         * 開始服務和設備查找
         * 
         */
        private void doDiscovery() { 
    
            // 設置在Activity的窗口的標題欄顯示進度條的效果
            setProgressBarIndeterminateVisibility(true);
            setTitle("查找設備中...");
    
            // 設定其它設備(未配對設備)列表的能見度為:可見的
            findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
    
            // 如果當前藍牙適配器正處於設備發現查找進程中,則返回真
            if (mBtAdapter.isDiscovering()) {
                // 取消當前的設備發現查找進程 
                mBtAdapter.cancelDiscovery();
            }
    // 開始對遠程設備進行查找的進程  
            mBtAdapter.startDiscovery();
        }
    
        /*****************************************************************************
         * 
         * 視圖點擊選擇設備連接函數 
         * 
         */ 
        private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
            public void onItemClick(AdapterView av, View v, int arg2, long arg3) {
                // 取消當前的設備發現查找進程 
                mBtAdapter.cancelDiscovery();
                // 得到mac地址
                String info = ((TextView) v).getText().toString();
                if (info.equals(NO_FOUND_DEVICE)) {
                    Toast.makeText(DeviceListActivity.this, "沒有找到藍牙設備,無法連接", Toast.LENGTH_LONG).show();
                    return ;
                }
                String address = info.substring(info.length() - 17);
                // 設置返回數據
                Intent intent = new Intent();
                intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
                // 設置連接成功返回值
                setResult(Activity.RESULT_OK, intent);
                // 結束程序
                finish();
            }
        };
        // 廣播接收器,監聽查找到設備和搜索完成action
        private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                // 查找到設備action
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    // 得到藍牙設備
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    
                    // 如果是已配對的則略過,已得到顯示,其余的在添加到列表中進行顯示
                    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                        mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                    }else{  //添加到已配對設備列表
                        mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                    }
    
                // 搜索完成action
                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
    
                    // 取消在Activity的窗口的標題欄顯示進度條的效果
                    setProgressBarIndeterminateVisibility(false);
                    setTitle("選擇要連接的設備");
    
                    //如果沒有找到新設備,則添加"沒有找到新設備"到新設備適配器列表
                    if (mNewDevicesArrayAdapter.getCount() == 0) { 
                        mNewDevicesArrayAdapter.add(NO_FOUND_DEVICE);
                    }
    //                if(mPairedDevicesArrayAdapter.getCount() > 0)
    //                  findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
                }
            }
        };
    }

    創建通信協議類(Communications_Protocol)

    定義各個功能鍵發送消息的起始位
    package com.example.timerbluetooth2.Other;
    public class Communications_Protocol {
     public final static byte Timer=(byte) 0xf0;
        public final static byte OpenClock=(byte) 0xf1;
        public final static byte CloseClock=(byte) 0xf2;
        public final static byte OpenMonitor=(byte) 0xf3;
        public final static byte CloseMonitor=(byte) 0xf4;
        public final static byte Adjustment=(byte) 0xf5;
    }

    創建ViewPager的Fragment類(ViewPagerFragment.java)
    詳細敘述見http://blog.csdn.net/kangweijian/article/details/43404801
    package com.example.timerbluetooth2.Fragment;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.support.v4.view.ViewPager.OnPageChangeListener;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button;
    import com.example.timerbluetooth2.R;
    public class ViewPagerFragment extends Fragment {
    
        public Button []TextButton=new Button[4];
       private ViewPager mViewPager;  
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            // TODO Auto-generated method stub  
            super.onCreate(savedInstanceState);  
        }  
        @Override  
        public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                Bundle savedInstanceState) {  
            // TODO Auto-generated method stub  
            //實例化TextButton
            TextButton[0] = (Button) getActivity().findViewById(R.id.TextButton1); 
            TextButton[1] = (Button) getActivity().findViewById(R.id.TextButton2);
            TextButton[2] = (Button) getActivity().findViewById(R.id.TextButton3); 
            TextButton[3] = (Button) getActivity().findViewById(R.id.TextButton4); 
    
            //創建ViewPager實例
            mViewPager=new ViewPager(getActivity());
    
            //創建資源ID(res/values/ids.xml),並配置mViewPager
            mViewPager.setId(R.id.viewPager);  
    
            //獲取Activity的FragmentManager實例
            FragmentManager fm = getActivity().getSupportFragmentManager();
    
            //設置adapter為FagmentStatePagerAdapter的一個匿名實例
            //FragmentStatePagerAdapter負責管理與ViewPager的對話並協同工作。
            mViewPager.setAdapter(new FragmentPagerAdapter(fm) { 
    
                    //getCount()返回mViewPager包含的列表項數目
                    @Override
                    public int getCount() {
                        // TODO Auto-generated method stub
                        //return mCrimes.size();
                        return 4;
                    }
    
                    //根據列表項ID,返回一個有效配置的Fragment
                    @Override
                    public Fragment getItem(int pos) {
                        // TODO Auto-generated method stub 
                        switch (pos) {
                        case 0: 
                            return TimerFragment.newInstance(); 
                        case 1:
                            return TimeMonitorFragment.newInstance(); 
                        case 2:
                            return ClockFragment.newInstance(); 
                        case 3:
                            return AdjustmentFragment.newInstance(); 
                        default:
                            return TimerFragment.newInstance();
                        }         }
                });  
                //設置當前要顯示的列表項 
                mViewPager.setCurrentItem(0);
                LightUpSingleButton(0);
                //設置監聽器,監聽ViewPager當前顯示頁面的狀態變化
                mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
    
                    //onPageSelected()方法告知我們當前哪個頁面會被選中
                    @Override
                    public void onPageSelected(int pos) {
                        // TODO Auto-generated method stub 
    
                        LightUpSingleButton(pos);
                    }
                    //onPageScrolled()方法告知我們頁面將會滑向哪裡
                    @Override
                    public void onPageScrolled(int arg0, float arg1, int arg2) {
                        // TODO Auto-generated method stub
                    }
                    //onPageScrollStateChanged()方法告知我們當前頁面所處的行為狀態,如正在被用戶滑動,頁面滑動入位到完全靜止以及頁面切換完成後的閒置狀態
                    @Override
                    public void onPageScrollStateChanged(int arg0) {
                        // TODO Auto-generated method stub 
                    }
                });
            //設置ViewPager為activity的內容視圖  
            return mViewPager;   
        }
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onActivityCreated(savedInstanceState); 
            TextButton[0].setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    mViewPager.setCurrentItem(0);
                    LightUpSingleButton(0);
                }
            });
            TextButton[1].setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    mViewPager.setCurrentItem(1);
                    LightUpSingleButton(1);
                }
            });
            TextButton[2].setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    mViewPager.setCurrentItem(2);
                    LightUpSingleButton(2);
                }
            });
            TextButton[3].setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    mViewPager.setCurrentItem(3);
                    LightUpSingleButton(3);
                }
            });
        }
        public void LightUpSingleButton(int num){
            for (int i = 0; i < TextButton.length; i++) {
              if (num==i) {
                    TextButton[i].setTextColor(0xFFDB7093);
                }else {
                    TextButton[i].setTextColor(0xFFA9A9A9);
                }
            }
        }
    }

    創建第一個列表項的Fragment(TimerFragment.java)

    TimePicker控件實例化,.setIs24HourView(true)設置是使用24小時制, .getCurrentHour();.getCurrentMinute();得到該控件當前所顯示的小時和分鐘。
    由getActivity()函數得到fragment所綁定的Activity,並強制轉換成MainActivity,從而可得到MainActivity中的所有的public變量。我們由該方法獲取所需的BluetoothSocket,由.getOutputStream()函數得到藍牙的輸出流,最後經.write(buf)函數發出對應的消息。
    時間更新按鈕對應發送的數據的起始位是由通信協議類中雙方約定好的數據,第一位和第二位是TimePicker控件的小時和分鐘的BCD碼,第三位本來應該是秒的BCD碼,目前暫且設為0。最後一位結束位0xFF。
    package com.example.timerbluetooth2.Fragment;
    import java.io.IOException; 
    import java.io.OutputStream;
    import com.example.timerbluetooth2.*;
    import com.example.timerbluetooth2.Activity.MainActivity;
    import com.example.timerbluetooth2.Other.Communications_Protocol;
    import android.bluetooth.BluetoothSocket;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager; 
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button; 
    import android.widget.TimePicker;
    import android.widget.Toast;
    
    public class TimerFragment extends Fragment {
        private Button TimerUpdateButton; 
        private TimePicker mTimerPicker;
    
        /*********************************
         * 
         * 1、onCreate(Bundle)是公共方法,因此可以被托管fragment的任何activity調用
         * 2、類似activity,fragment同樣具有保存及獲取狀態的bundle,可以根據需要覆蓋Fragment.onSaveInstanceState(Bundle)
         * 3、onCreate(Bundle)中,沒有生成fragment視圖。
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState); 
    
        }
        /*************************************
         * 
         * 通過該方法生成fragment視圖的布局,然後將生成的View返回給托管activity。
         * LayoutInflater及ViewGroup是用來生成布局的必要參數。
         * Bundle包含了該方法的保存狀態下重建視圖所使用的數據。
         */
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup parent,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
    
            // 調用LayoutInflater.inflate(...)方法並傳入布局的資源ID生成的。第二個參數是視圖的父視圖,通過父視圖來正確配置組件。
            // 第三個參數告知布局生成器是否將生成的視圖添加給父視圖。這裡我們傳入了false,因為我們將通過activity代碼的方式添加視圖。
            View v = inflater.inflate(R.layout.fragment_timer, parent, false);
    
            //mTimerPicker實例化
            mTimerPicker = (TimePicker) v.findViewById(R.id.Timer_Picker);
            //mTimerPicker是否使用24小時制  
            mTimerPicker.setIs24HourView(true);    
            TimerUpdateButton = (Button) v.findViewById(R.id.Timer_UpdateButton);  
            TimerUpdateButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    byte []buf =new byte[5];
                    int h=mTimerPicker.getCurrentHour();  
                    int m=mTimerPicker.getCurrentMinute();    
                    buf[0] = Communications_Protocol.Timer; 
                    buf[1] = (byte)((h/10)*16+(h%10));
                    buf[2] = (byte)((m/10)*16+(m%10));
                    buf[3] = 0;
                    buf[4] = (byte) 0xff;
    
                    BluetoothSocket socket = ((MainActivity)getActivity())._socket;
    
                    if (socket == null) {
                        Toast.makeText(getActivity(), "請先連接藍牙設備",Toast.LENGTH_SHORT).show();
                    }else { 
                        try {
                            OutputStream os=socket.getOutputStream();
                            os.write(buf);
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
            return v;
        }
    
        /**************************************
         * 目的:附加argument bundle給Fragment,需要調用Fragment.setArguments(Bundle)方法。
         * 要求:該任務必須在fragment創建後,添加給activity前完成
         * 方法:使用newInstance()方法,完成Fragment實例及bundle對象的創建,然後將argument放入bundle中,最後附加給Fragment
         * 其他:托管activity需要fragment實例時,需要調用newInstance()方法,而非直接調用其構造方法。而且,為滿足fragment創建argument的要求,activity可傳入
         *      任何需要的參數給newInstance()方法。
         * 
         * @param crimeID
         * @return
         */
        public static TimerFragment newInstance(){
            Bundle args = new Bundle(); 
            TimerFragment fragment=new TimerFragment();
            fragment.setArguments(args);
            return fragment; 
        }
    }

    創建第二個列表項的Fragment(TimeMonitorFragment.java)

    與第一個列表項基本雷同,不再贅述
    package com.example.timerbluetooth2.Fragment;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import com.example.timerbluetooth2.*;
    import com.example.timerbluetooth2.Activity.MainActivity;
    import com.example.timerbluetooth2.Other.Communications_Protocol;
    import android.bluetooth.BluetoothSocket;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;  
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button; 
    import android.widget.CompoundButton;
    import android.widget.CompoundButton.OnCheckedChangeListener;
    import android.widget.Switch;
    import android.widget.TimePicker;
    import android.widget.Toast;
    
    public class TimeMonitorFragment extends Fragment {
        private TimePicker TimeMonitorPicker1,TimeMonitorPicker2; 
        private Switch TimeMonitorSwitch;
        /*********************************
         * 
         * 1、onCreate(Bundle)是公共方法,因此可以被托管fragment的任何activity調用
         * 2、類似activity,fragment同樣具有保存及獲取狀態的bundle,可以根據需要覆蓋Fragment.onSaveInstanceState(Bundle)
         * 3、onCreate(Bundle)中,沒有生成fragment視圖。
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
        }
        /*************************************
         * 
         * 通過該方法生成fragment視圖的布局,然後將生成的View返回給托管activity。
         * LayoutInflater及ViewGroup是用來生成布局的必要參數。
         * Bundle包含了該方法的保存狀態下重建視圖所使用的數據。
         */
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup parent,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            // 調用LayoutInflater.inflate(...)方法並傳入布局的資源ID生成的。第二個參數是視圖的父視圖,通過父視圖來正確配置組件。
            // 第三個參數告知布局生成器是否將生成的視圖添加給父視圖。這裡我們傳入了false,因為我們將通過activity代碼的方式添加視圖。
            View v = inflater.inflate(R.layout.fragment_time_monitor, parent, false); 
    
           //TimeMonitorSwitch實例化
            TimeMonitorSwitch = (Switch) v.findViewById(R.id.TimeMonitor_Switch);
            //TimeMonitorPicker1實例化
            TimeMonitorPicker1 = (TimePicker) v.findViewById(R.id.TimeMonitor_Picker1);
            //TimeMonitorPicker1是否使用24小時制  
            TimeMonitorPicker1.setIs24HourView(true);    
           //TimeMonitorPicker2實例化
            TimeMonitorPicker2 = (TimePicker) v.findViewById(R.id.TimeMonitor_Picker2);
            //mTimerPicker是否使用24小時制  
            TimeMonitorPicker2.setIs24HourView(true);    
        TimeMonitorSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
                    // TODO Auto-generated method stub
                    byte []buf =new byte[6];
                    int h1=TimeMonitorPicker1.getCurrentHour();  
                    int m1=TimeMonitorPicker1.getCurrentMinute();   
                    int h2=TimeMonitorPicker2.getCurrentHour();  
                    int m2=TimeMonitorPicker2.getCurrentMinute();   
    
                    if (TimeMonitorSwitch.isChecked()) {
                        buf[0] = Communications_Protocol.OpenMonitor;
                    }else {
                        buf[0] = Communications_Protocol.CloseMonitor;
                    }  
                    buf[1] = (byte)((h1/10)*16+(h1%10));
                    buf[2] = (byte)((m1/10)*16+(m1%10));
                    buf[3] = (byte)((h2/10)*16+(h2%10));
                    buf[4] = (byte)((m2/10)*16+(m2%10));
    
                    buf[5] = (byte) 0xff;
                    BluetoothSocket socket = ((MainActivity)getActivity())._socket;
                    if (socket == null) {
                        Toast.makeText(getActivity(), "請先連接藍牙設備",Toast.LENGTH_SHORT).show();
                    }else { 
                        try {
                            OutputStream os=socket.getOutputStream();
                            os.write(buf);
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
           return v;
        }
        /**************************************
         * 目的:附加argument bundle給Fragment,需要調用Fragment.setArguments(Bundle)方法。
         * 要求:該任務必須在fragment創建後,添加給activity前完成
         * 方法:使用newInstance()方法,完成Fragment實例及bundle對象的創建,然後將argument放入bundle中,最後附加給Fragment
         * 其他:托管activity需要fragment實例時,需要調用newInstance()方法,而非直接調用其構造方法。而且,為滿足fragment創建argument的要求,activity可傳入
         *      任何需要的參數給newInstance()方法。
         * 
         * @param crimeID
         * @return
         */
        public static TimeMonitorFragment newInstance(){
            Bundle args = new Bundle(); 
            TimeMonitorFragment fragment=new TimeMonitorFragment();
            fragment.setArguments(args);
            return fragment; 
        }
    }

    創建第三個列表項的Fragment(ClockFragment.java)

    與第一個列表項基本雷同,不再贅述
    package com.example.timerbluetooth2.Fragment;
    import java.io.IOException;
    import java.io.OutputStream;
    import com.example.timerbluetooth2.*;
    import com.example.timerbluetooth2.Activity.MainActivity;
    import com.example.timerbluetooth2.Other.Communications_Protocol;
    import android.bluetooth.BluetoothSocket;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.CheckBox; 
    import android.widget.CompoundButton;
    import android.widget.CompoundButton.OnCheckedChangeListener;
    import android.widget.Switch;
    import android.widget.TimePicker;
    import android.widget.Toast;
    
    public class ClockFragment extends Fragment {
    
        private Button Clock_UpdateButton;
        private TimePicker mTimePicker; 
        private Switch mSwitch;
    
       /*********************************
         * 
         * 1、onCreate(Bundle)是公共方法,因此可以被托管fragment的任何activity調用
         * 2、類似activity,fragment同樣具有保存及獲取狀態的bundle,可以根據需要覆蓋Fragment.onSaveInstanceState(Bundle)
         * 3、onCreate(Bundle)中,沒有生成fragment視圖。
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
        }
    
        /*************************************
         * 
         * 通過該方法生成fragment視圖的布局,然後將生成的View返回給托管activity。
         * LayoutInflater及ViewGroup是用來生成布局的必要參數。
         * Bundle包含了該方法的保存狀態下重建視圖所使用的數據。
         */
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup parent,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
    
            // 調用LayoutInflater.inflate(...)方法並傳入布局的資源ID生成的。第二個參數是視圖的父視圖,通過父視圖來正確配置組件。
            // 第三個參數告知布局生成器是否將生成的視圖添加給父視圖。這裡我們傳入了false,因為我們將通過activity代碼的方式添加視圖。
            View v = inflater.inflate(R.layout.fragment_clock, parent, false);
    
           //mSwitch實例化
            mSwitch = (Switch) v.findViewById(R.id.Clock_Switch);
    
            //mTimePicker實例化
            mTimePicker = (TimePicker) v.findViewById(R.id.Clock_Picker);
            //mTimePicker是否使用24小時制  
            mTimePicker.setIs24HourView(true);  
    
            mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
                @Override
                public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
                    // TODO Auto-generated method stub
                    byte []buf =new byte[4];
                    int h=mTimePicker.getCurrentHour();  
                    int m=mTimePicker.getCurrentMinute();     
    
                    if (mSwitch.isChecked()) {
                        buf[0] = Communications_Protocol.OpenClock;
                    }else {
                        buf[0] = Communications_Protocol.CloseClock;
                    } 
                    buf[1] = (byte)((h/10)*16+(h%10));
                    buf[2] = (byte)((m/10)*16+(m%10));
                    buf[3] = (byte) 0xff;
                    BluetoothSocket socket = ((MainActivity)getActivity())._socket;
                    if (socket == null) {
                        Toast.makeText(getActivity(), "請先連接藍牙設備",Toast.LENGTH_SHORT).show();
                    }else { 
                        try {
                            OutputStream os=socket.getOutputStream();
                            os.write(buf);
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
            return v;
        }
        /**************************************
         * 目的:附加argument bundle給Fragment,需要調用Fragment.setArguments(Bundle)方法。
         * 要求:該任務必須在fragment創建後,添加給activity前完成
         * 方法:使用newInstance()方法,完成Fragment實例及bundle對象的創建,然後將argument放入bundle中,最後附加給Fragment
         * 其他:托管activity需要fragment實例時,需要調用newInstance()方法,而非直接調用其構造方法。而且,為滿足fragment創建argument的要求,activity可傳入
         *      任何需要的參數給newInstance()方法。
         * 
         * @param crimeID
         * @return
         */
        public static ClockFragment newInstance(){
            Bundle args = new Bundle(); 
            ClockFragment fragment=new ClockFragment();
            fragment.setArguments(args);
            return fragment; 
     }
    }

    創建第四個列表項的Fragment(AdjustmentFragment.java)

    與第一個列表項基本雷同,不再贅述
    package com.example.timerbluetooth2.Fragment;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import com.example.timerbluetooth2.*;
    import com.example.timerbluetooth2.Activity.MainActivity;
    import com.example.timerbluetooth2.Other.Communications_Protocol;
    import android.bluetooth.BluetoothSocket;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager; 
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.webkit.WebView.FindListener;
    import android.widget.Button; 
    import android.widget.ScrollView;
    import android.widget.TimePicker;
    import android.widget.Toast;
    
    public class AdjustmentFragment extends Fragment { 
        private TimePicker mTimePicker;
        private Button Adjustment_Button; 
    
        /*********************************
         * 
         * 1、onCreate(Bundle)是公共方法,因此可以被托管fragment的任何activity調用
         * 2、類似activity,fragment同樣具有保存及獲取狀態的bundle,可以根據需要覆蓋Fragment.onSaveInstanceState(Bundle)
         * 3、onCreate(Bundle)中,沒有生成fragment視圖。
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState); 
    
        }
    
        /*************************************
         * 
         * 通過該方法生成fragment視圖的布局,然後將生成的View返回給托管activity。
         * LayoutInflater及ViewGroup是用來生成布局的必要參數。
         * Bundle包含了該方法的保存狀態下重建視圖所使用的數據。
         */
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup parent,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
    
            // 調用LayoutInflater.inflate(...)方法並傳入布局的資源ID生成的。第二個參數是視圖的父視圖,通過父視圖來正確配置組件。
            // 第三個參數告知布局生成器是否將生成的視圖添加給父視圖。這裡我們傳入了false,因為我們將通過activity代碼的方式添加視圖。
            View v = inflater.inflate(R.layout.fragment_adjustment, parent, false);
    
            //mTimePicker實例化
            mTimePicker = (TimePicker) v.findViewById(R.id.Adjustment_Picker);
            //mTimePicker是否使用24小時制  
            mTimePicker.setIs24HourView(true);
            //mTimePicker設置當前時間為0
            mTimePicker.setCurrentHour(0);
            mTimePicker.setCurrentMinute(0);
            Adjustment_Button = (Button) v.findViewById(R.id.Adjustment_UpdateButton);  
            Adjustment_Button.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
    
                    byte []buf =new byte[4];
                    int h=mTimePicker.getCurrentHour();  
                    int m=mTimePicker.getCurrentMinute();    
                buf[0] = Communications_Protocol.Adjustment; 
                  buf[1] = (byte)h;
                    buf[2] = (byte)m; 
                    buf[3] = (byte) 0xff;
                    BluetoothSocket socket = ((MainActivity)getActivity())._socket;
                    if (socket == null) {
                        Toast.makeText(getActivity(), "請先連接藍牙設備",Toast.LENGTH_SHORT).show();
                    }else { 
                        try {
                            OutputStream os=socket.getOutputStream();
                            os.write(buf);
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
          return v;
        }
    
        /**************************************
         * 目的:附加argument bundle給Fragment,需要調用Fragment.setArguments(Bundle)方法。
         * 要求:該任務必須在fragment創建後,添加給activity前完成
         * 方法:使用newInstance()方法,完成Fragment實例及bundle對象的創建,然後將argument放入bundle中,最後附加給Fragment
         * 其他:托管activity需要fragment實例時,需要調用newInstance()方法,而非直接調用其構造方法。而且,為滿足fragment創建argument的要求,activity可傳入
         *      任何需要的參數給newInstance()方法。
         * 
         * @param crimeID
         * @return
         */
        public static AdjustmentFragment newInstance(){
    
            Bundle args = new Bundle(); 
            AdjustmentFragment fragment=new AdjustmentFragment();
            fragment.setArguments(args);
            return fragment; 
        }
    }

    創建主框架的布局文件(activity_main.xml)

    包含頂上4個Button、底下2個Button以及中間的fragment
    
         
            
                

    創建第一個列表項的布局文件(fragment_timer.xml)
    
    
        
        

    創建第二個列表項的布局文件(fragment_time_monitor.xml)

    
    
    
         
            
    
            
         
        
         
    
    
    創建第三個列表項的布局文件(fragment_clock.xml)

    
    
        
    
        
         
    

    創建第四個列表項的布局文件(fragment_adjustment.xml)
    
    
       
        
    AndroidManifest.xml添加權限和activity清單
    將DeviceListActivity的主題改為對話框主題
    
        
        
        
    
      

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved