2013年11月30日 星期六

[Oracle] Oracle Install Weblogic 10.3.3



1. 到 Oracle 官網下載 Weblogic10.3.3 執行檔

2. 下載完後取得 wls1033_oepe111150_win32.exe 並點選它


3. 開始安裝


4. 選擇 Middleaware 目錄


5. 選擇安裝類型


6. 安裝摘要


7. 選擇安裝目錄


8.安裝完成


















其它文章

2013年11月27日 星期三

[Android]Android系統調用流程

本文介紹Android系統調用介紹很好,故轉載保留,如有侵權請告知,以刪除,感謝。
內容如下:

——摘錄一本書中的部分章節,對理解整個Android系統的架構有幫助,轉載如下。 )
       1.1.1 Android 的系統構架
        要深入學習Android,首先需要學習Android的系統構架。 Android的系統構架和其操作系統一樣,
採用了分層的構架,層次非常清晰,因此要掌握它的構架並不難。下圖為為Android 的系統構架圖,如果
你對該圖已經不陌生,並且理解圖中所示的構架,那麼你可以跳過這部分內容(或者快速瀏覽) ;如果
你是第一次見到該圖,建議你詳細閱讀該部分內容,因為整本書的內容都是以這幅圖為基礎的。我們會對
圖中的每一個模塊進行詳細地分析,讓你真正掌握Android 的技術內幕。

 Android 分為五層,從高層到低層分別是應用程序層(Applications) 、應用程序框架層(Application Framework) 、
系統運行庫層(Libraries和Android Runtime)和Linux內核層(Linux Kernel) 。下面分別來看各個層次為我們
提供了什麼功能,以及如何來運用這些功能。
       1.應用程序層
        Android會與核心應用程序包一起發布, 該應用程序包包括圖1為大家展示的主屏(Home) 、E-mail 客戶端、
SMS/MMS短消息程序、日曆、地圖、瀏覽器、聯繫人管理程序等。所有的應用程序都是使用Java語言編寫的,通過
調用應用程序框架層(Application Framework)所提供的API來完成。當然,你也可以使用Java通過JNI的方式,
配合Android NDK來開發原生的應用程序,這樣可以提高應用程序的效率,但是難度也大大增加——你需要精通C和
 C++等語言,並且對Android NDK所提供的為數不多的功能有很深的認識。因為 Android NDK提供的功能不是太多,
為了避免你做了很久之後才發現——原來NDK 不支持某項功能,大家可以根據自己的需求來選擇是否採NDK 開發原生程序。
     
  2.應用程序框架層
       應用程序框架層為開發人員提供了可以完全訪問核心應用程序所使用的API 框架。該應用程序的構架設計簡化了組
件的重用,任何一個應用程序(以及任何其他應用程序)都可以發布自己的功能模塊(在遵循框架的安全性限制的前提下) 。
同樣,該應用程序重用機制也使用戶可以方便地替換程序組件。下面來看一下該層的每一個模塊為我們提供的組件,
如表 1-1所示。

    
             
    3.系統運行庫層
                  系統運行庫層包括程序庫和Android 運行庫兩部分,下面分別來介紹這兩個部分。
                 (1)程序庫
                  Android 包含一些C/C++庫,這些庫能被Android 系統中的不同組件使用,它們通過應用程序框架為開發者提供服務,
表1-2 給出了這些核心庫的功能介紹。


         (2)Android 運行時庫
          從圖1 可以看出,Android 運行時庫又分為核心庫和Dalvik 虛擬機兩部分。核心庫提供了Java語言核心庫的大多數功能,
 這裡主要通過JNI的方式向應用程序框架層提供調用底層程序庫的接口。 Dalvik 虛擬機是為了能同時高效地運行多個VMs 而實現的。
Dalvik 虛擬機執行.dex 的Dalvik可執行文件,該格式的文件針對最小內存使用做了優化。 Dalvik虛擬機是基於寄存器的,所有的類都
經由Java彙編器編譯,然後通過SDK中的dx工具轉化成.dex格式並由虛擬機執行。 Dalvik虛擬機依賴Linux的一些功能,比如線程機制
和底層的內存管理機制。每一個Android應用程序都在它自己的進程中運行,都擁有一個獨立的Dalvik 虛擬機實例。關於這部分內容,
先簡單向大家介紹到這裡,後面會給大家詳細分析Android SDK 工具包和Dalvik 虛擬機。
         4. Linux內核層
         Android依賴於Linux 2.6 版內核提供的核心系統服務,例如安全、內存管理、進程管理、網絡棧、驅動模塊等。內核作為一個抽
象層,存在於軟件棧層和硬件層之間,Android 對內核進行了增強,主要表現在以下幾個方面:



        到這裡, 我們對Android系統構架的分析就告一段落了, 你現在至少應該明白整個Android系統的構架和每
個模塊的功能, 以便為後面的深入學習打下基礎。 Android系統是如何啟動的?啟動過程中需要初始化什麼內容?
如果你不知道(或不完全知道)這些問題的答案,不必擔心,下一小節將剖析Android 系統啟動時的初始化操作。
        1.1.2 Android 的初始化流程
       上一小節分析了Android的系統構架,讓大家對Android系統有了一個深入的認識;但是,Android 系統本身非常
龐大,在深入分析每個模塊的具體功能之前,有必要對其啟動過程進行分析。我們需要了解這麼一個龐大的系統在啟動
的時候需要執行哪些初始化操作。 Android 系統在啟動時首先會啟動Linux 基礎系統,然後引導加載Linux Kernel 並
啟動初始化進程(Init) ,如圖1-1 所示。

       接著,啟動Linux守護進程(daemons) 。這個過程主要需要啟動以下內容,如圖1-2所示。
        ‰ 啟動USB守護進程(usbd)來管理USB連接。
        ‰ 啟動Android Debug Bridge守護進程(adbd)來管理ADB連接。
        ‰ 啟動Debug 守護進程(debuggerd)來管理調試進程的請求(包括內存轉換等) 。
        ‰ 啟動無線接口守護進程(rild)來管理無線通信。




         在啟動Linux守護進程的同時還需要啟動Zygote進程,如圖1-3所示。它主要包括以下需要啟動和註冊的內容:
         ‰ 初始化一個 Dalvik 虛擬機實例。
         ‰ 裝載 Socket請求所需的類和監聽。
         ‰ 創建虛擬機實例來管理應用程序的進程。
                                                

 再接著,需要初始化runtime 進程,初始化過程如圖1-4 所示。在這個過程中需要處理以下操作:
           ‰ 初始化服務管理器。
           ‰ 註冊服務管理器,以它作為默認Binder 服務的Context管理器。

                                               
        runtime 進程初始化之後,runtime 進程將發送一個請求到Zygote,開始啟動系統服務,這時Zygote 將為系統服務進程建
立一個虛擬機實例,並啟動系統服務,如圖1-5 所示。
                                  

緊接著,系統服務將啟動原生系統服務,主要包括Surface Flinger和Audio Flinger。這些本地系統服務將註冊到服務
管理器(Service Manager)作為IPC服務的目標, 如圖1-6所示。
                                   

        系統服務將啟動Android 管理服務,Android 管理服務將都被註冊到服務管理器上,如圖1-7 所示。
                                

        最後,當系統加載完所有的服務之後會處於等待狀態,等待程序運行。但是,每一個應用程序都將啟動一個
單獨的進程。如圖1-8 所示,系統啟動了一個Home 進程和一個Contacts 進程。那麼,各個進程之間如何進行
交互呢?這就需要使用IPC機制了,後面會詳細介紹。
                

        到這裡, 系統的整個啟動過程就結束了, 可以在上面運行應用程序了。你也應該對Android系統啟動過程的
每一步都有了深入的理解。實際上,這個啟動過程就是從Android系統構架圖中最底層的Linux內核層一步一步加載和
註冊到應用程序框架層,最終在應用程序層運行我們自己的應用程序。那麼,各個層次之間又有什麼樣的關係呢?應用
程序在最上層又是如何調用到最底層的核心服務的呢?下一小節將為大家分析各個層次之間的關係。
        1.1.3 各個層次之間的相互關係
上一小節介紹了Android 系統的啟動過程,本小節將介紹Android 應用程序是如何按照層次關係來調用最底層的硬件和
服務的。如果你對上一節的內容理解得還不夠深入,那麼可以回去再仔細地看一遍,這樣才能更好地理解本小節的內容。
好的,相信你已經準備好了,開始吧。在Android 中運行的應用程序都是通過以下三種方式來層層深入的:
         ‰ App→Runtime Service→Lib
         ‰ App→Runtime Service→Native Service→Lib
         ‰ App→Runtime Service→Native Daemon→Lib
下面就分別來分析這三種方式,我們還是採用流程圖的方式來為大家展示。
App→Runtime Service→Lib 方式對應的流程圖如圖1-9 所示。
                       

        通過圖1-9我們可以看出, 在Android平台上, 應用程序首先是在應用程序層通過Binder IPC調用應用程序框架
層的Runtime Service,然後再通過JNI與運行庫中的原生服務綁定,並動態地加載Hal庫,進而調用Linux內核層
的Kernel Driver。為了便於大家更好地理解,我們通過一個實例(Location Manager)來為分析該流程,如圖1-10 所示。
                           

        以上就是第一種方式的調用過程,接下來我們再看一下第二種方式(App→Runtime Service→Native Service→Lib)
是如何調用的。這種方式通常被Android原生服務所採用,同樣先看一下調用流程圖,如圖1-11 所示。
                            

        圖1-11為我們展示了Android原生服務的調用流程,可以看出,與第一種方式相比,只多了一個通過IPC機制調用原
生服務並進行動態裝載的過程。所以,這裡我們就不再重複介紹,但還是給出一個Audio 的例子,如圖1-12 所示。
                                

        從圖1-12 可以看出,應用程序調用了應用程序框架層的MediaPlayer,然後調用系統運行庫層的MediaPlaye。這時MediaPlaye
又分別調用了Media Framework和AudioFlinger,而後通過AudioFlinger 調用指定的庫(libaudio.so) ,最後才調用到Kernel Driver。
下面來看一下最後一種方式“App→Runtime Service→Native Daemon→Lib” ,如圖1-13所示。這種方式通常用於守護進程的連接。
                                  

        從圖1-13可以看出,這種方式比原生服務的調用更簡單,它直接通過JNI綁定原生服務,再通過sockets調用守護進程進行動態加載。
下面就來看一個簡單的例子, 電話管理(Telephony Manager)的調用就是這樣一個原生的守護進程調用,其流程如圖1-14 所示。
                                 

         這個調用的過程非常簡單,相信圖1-14 已經表述得足夠清楚了。
        1.1.4 Android 系統開發(移植)和應用開發
        通過前面的學習,我們了解到Android 是一個龐大且完善的系統,我們可以基於Android來進行哪些開發工作?
每一種開發工作又有什麼不同?不同的開發工作需要掌握的技術有什麼差異?學完本小節的內容你就會知道應該如何
利用Android 來開發自己所需要的產品。因為Android 是一個開源的操作系統,所以可以選擇的開發方式主要有以下兩種:
         ‰ Android 系統開發(移植)
         ‰ Android 應用開發
        1. Android系統開發(移植)
         Android 系統開發(移植)屬於底層的開發工作,主要針對Android 系統本身進行完善和將其移植到其他的硬件平台,
因此需要掌握Android 系統構架中的Linux 內核層和系統運行庫層,如圖1-15 所示。 Android系統開發主要涉及 Libraries
和Android Runtime 這兩部分內容, 一般就是在本地編寫C/C++代碼,然後通過JNI 向上層提供調用接口,主要是為應用
開發提供服務等工作。 Android 系統移植則主要涉及硬件抽象層和Li​​nux 內核層,移植的主要工作是將驅動移植到不同的硬件上,
使其能完美地運行Android 系統。這些驅動又主要包括設備驅動和Android專用驅動。
     

      無論是系統開發還是系統移植, 都是由底層直接操作Android的源代碼, 因此在開發之前,我們首先就需要準備Android 的源碼。
下一節將向大家詳細介紹如何獲取和編譯Andorid 的源碼,以及Android 源碼的結構。
        2. Android應用開發
        Android 應用開發主要是根據Android 系統所提供的API 來完成各種應用程序的編寫,所使用的API屬於Android的應用框架層,
如圖1-16所示。如果Android系統沒有提供某些API,那麼只能通過在Android 系統底層編寫C/C++代碼來開發這些API 並向
Android 應用框架層提供接口。但是筆者不建議這樣做,因為這很可能會導致你的應用程序與其他Android 系統不兼容。
    

      我們自己所開發出來的應用程序與應用層的應用程序運行在同一個層次上,因此再次提醒大家,開發應用時一定要遵循
 Android API 框架的規定,以避免開發的應用程序不兼容。另外,應用開發屬於上層開發,不需要接觸底層的C/C++代碼,
所以,開發前​​我們只需要準備Android SDK 和模擬器即可(當然,你可能也需要使用一款IDE,推薦使用Eclipse) 。
最後,Android SDK 既可以通過編譯源碼獲得,也可以在Android 的官方網站下載編譯好的SDK。
下面將講解如何通過編譯
源碼的方式來取得Android SDK,以及SDK 的結構和開發工具包。


















其它文章

[Android]Android 系統架構圖及開發之轉檔過程


Android系統架構圖




Android的系統架構和其操作系統一樣,採用了分層的架構。
從架構圖看,Android分為四個層,
從高層到低層分別是:

  • 應用程序層
  • 應用程序框架層
  • 系統運行庫層-分二個部份為程序庫及Android 運行庫
  • Linux核心層


一、應用程序

Android會同一系列核心應用程序包一起發布,該應用程序包包括email客戶端,SMS短消息程序,日曆,地圖,瀏覽器,聯繫人管理程序等。
所有的應用程序都是使用JAVA語言編寫的。

二、應用程序框架

開發人員也可以完全訪問核心應用程序所使用的API框架。
該應用程序的架構設計簡化了組件的重用;
任何一個應用程序都可以發布它的功能塊並且任何其它的應用程序都可以使用其所發布的功能塊(不過得遵循框架的安全性限制)。
同樣,該應用程序重用機制也使用戶可以方便的替換程序組件。

隱藏在每個應用後面的是一系列的服務和系統, 其中包括;

  • 豐富而又可擴展的視圖(Views),可以用來構建應用程序, 它包括列表(lists),網格(grids),文本框(text boxes),按鈕(buttons), 甚至可嵌入的web瀏覽器。
  • 內容提供器(Content Providers)使得應用程序可以訪問另一個應用程序的數據(如聯繫人數據庫), 或者共享它們自己的數據
  •  資源管理器(Resource Manager)提供非代碼資源的訪問,如本地字符串,圖形,和佈局文件( layout files )。
  • 通知管理器(Notification Manager) 使得應用程序可以在狀態欄中顯示自定義的提示信息。
  • 活動管理器( Activity Manager) 用來管理應用程序生命週期並提供常用的導航回退功能。



三、系統運行庫

1、程序庫

Android 包含一些C/C++庫,這些庫能被Android系統中不同的組件使用。它們通過Android 應用程序框架為開發者提供服務。以下是一些核心庫:


  • 系統C 庫- 一個從BSD 繼承來的標準C 系統函數庫( libc ), 它是專門為基於embedded linux 的設備定制的。
  • 媒體庫- 基於PacketVideo OpenCORE;該庫支持多種常用的音頻、視頻格式回放和錄製,同時支持靜態圖像文件。編碼格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。
  • Surface Manager - 對顯示子系統的管理,並且為多個應用程序提供了2D和3D圖層的無縫融合。
  •  LibWebCore - 一個最新的web瀏覽器引擎用,支持Android瀏覽器和一個可嵌入的web視圖。
  • SGL - 底層的2D圖形引擎
  • 3D libraries - 基於OpenGL ES 1.0 APIs實現;該庫可以使用硬件3D加速(如果可用)或者使用高度優化的3D軟加速。
  • FreeType -位圖(bitmap)和矢量(vector)字體顯示。
  • SQLite - 一個對於所有應用程序可用,功能強勁的輕型關係型數據庫引擎。



2、Android 運行庫

Android 包括了一個核心庫,該核心庫提供了JAVA編程語言核心庫的大多數功能。

每一個Android應用程序都在它自己的進程中運行,都擁有一個獨立的Dalvik虛擬機實例。 Dalvik被設計成一個設備可以同時高效地運行多個虛擬系統。 Dalvik虛擬機執行(.dex)的Dalvik可執行文件,該格式文件針對小內存使用做了優化。同時虛擬機是基於寄存器的,所有的類都經由JAVA編譯器編譯,然後通過SDK中的"dx" 工具轉化成.dex格式由虛擬機執行。

Dalvik虛擬機依賴於linux內核的一些功能,比如線程機制和底層內存管理機制。

四、Linux 內核心

Android 的核心系統服務依賴於Linux 2.6 內核,如安全性,內存管理,進程管理, 網絡協議棧和驅動模型。 Linux 內核也同時作為硬件和軟件棧之間的抽象層。



Android 應用程式開發之轉檔過程

相關參考網站:
http://android.91.com/content/2009-03-10/20090310200215684.shtml

http://style77125tech.pixnet.net/blog/post/161633594-%5Bandroid%5D-%E7%B3%BB%E7%B5%B1%E6%9E%B6%E6%A7%8B


















其它文章

[Android]Android程式BluetoothChat範例程式學藍芽連線原理

一、前言
Bluetooth藍芽裝置在手機界已經存在很久了,
也早就成為連低階Android手機都有的基本配備。
官方也提供了一個利用藍芽連線互相對話的範例程式
讓我們能快速地了解藍芽在Android中的使用方式。 
  
二、文章開始 
首先,
我們先建立一個觀念︰ 
藍芽一定分成2個端點,
分別為被動的Server端主動的Client端

底下是BluetoothChat的Sample Code程式流程︰

=========現在在BluetoothChat.java底下==============

1.在onCreate()時,呼叫
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();


一起來看看官方文件裡怎麼說BluetoothAdapter
BluetoothAdapter represents the local Bluetooth adapter (Bluetooth radio).
The BluetoothAdapter is the entry-point for all Bluetooth interaction.
Using this, you can discover other Bluetooth devices, query a list of bonded (paired) devices, instantiate a BluetoothDevice using a known MAC address, and create a BluetoothServerSocket to listen for communications from other devices.
BluetoothAdapter是區域藍芽接口(藍芽廣播)。BluetoothAdapter也是所有藍芽交易互動的啟始點。用這個接口,我們可以偵 測區域內有哪些其它的藍芽裝置、查詢已配對過的藍芽列表、用已知的MAC地址建立一個BluetoothDevice實體、建立一個 BluetoothServerSocket來監聽是否有其它藍芽裝置傳來的通訊…等。

2-1.得到一個BluetoothAdapter實體之後,
在onStart()裡, 
如果沒有啟動藍芽,則要求使用者開啟藍芽。
指令是︰
if (!mBluetoothAdapter.isEnabled()) {
    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
}else {
    if (mChatService == null) setupChat();
}

2-2.透過setupChat()建立起基本的對話視窗和BluetoothChatService背景服務,並把主Thread的Handler傳給Service以供日後傳回message。
mChatService = new BluetoothChatService(this, mHandler);


3.在onResume()裡,也做一樣的事,如果檢查沒有開啟藍芽BluetoothChatService背景服務,則再次開始該服務。 
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
}

=========現在進入BluetoothChatService.java裡==============

程式碼才剛開出來,
馬上就看到這個Service的程式架構中,塞了3個執行緒, 
分別為︰
(1)AcceptThread
(2)ConnectThread
(3)ConnectedThread

馬上來看看它們在Service裡,分別擔任什麼樣的任務︰

// Cancel any thread attempting to make a connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
 
// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
 
// Start the thread to listen on a BluetoothServerSocket
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}

1.在onStart()中,
檢查如果ConnectThread和ConnectedThread存在,則將他們關掉。
2.啟動一個AcceptThread(現在的流程是在藍芽開啟中的狀態,開啟了一個AcceptThread待命)。
這個AcceptThread存在的目的,是因為程式先假設每臺裝置都有可能想要跟它做藍芽連線。

來看一下這個程式一啟動後就執行的AcceptThread裡面做了些什麼︰

/**
   * This thread runs while listening for incoming connections. It behaves
   * like a server-side client. It runs until a connection is accepted
   * (or until cancelled).
   */
  private class AcceptThread extends Thread {
      // The local server socket
      private final BluetoothServerSocket mmServerSocket;
 
      public AcceptThread() {
          BluetoothServerSocket tmp = null;
 
          // Create a new listening server socket
          try {
              tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
          } catch (IOException e) {
              Log.e(TAG, "listen() failed", e);
          }
          mmServerSocket = tmp;
      }
 
      public void run() {
          if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
          setName("AcceptThread");
          BluetoothSocket socket = null;
 
          // Listen to the server socket if we're not connected
          while (mState != STATE_CONNECTED) {
              try {
                  // This is a blocking call and will only return on a
                  // successful connection or an exception
                  socket = mmServerSocket.accept();
              } catch (IOException e) {
                  Log.e(TAG, "accept() failed", e);
                  break;
              }
 
              // If a connection was accepted
              if (socket != null) {
                  synchronized (BluetoothChatService.this) {
                      switch (mState) {
                      case STATE_LISTEN:
                      case STATE_CONNECTING:
                          // Situation normal. Start the connected thread.
                          connected(socket, socket.getRemoteDevice());
                          break;
                      case STATE_NONE:
                      case STATE_CONNECTED:
                          // Either not ready or already connected. Terminate new socket.
                          try {
                              socket.close();
                          } catch (IOException e) {
                              Log.e(TAG, "Could not close unwanted socket", e);
                          }
                          break;
                      }
                  }
              }
          }
          if (D) Log.i(TAG, "END mAcceptThread");
      }
 
      public void cancel() {
          if (D) Log.d(TAG, "cancel " + this);
          try {
              mmServerSocket.close();
          } catch (IOException e) {
              Log.e(TAG, "close() of server failed", e);
          }
      }
  }

我們看到了在AcceptThread裡面,埋入了一個BluetoothServerSocket。
看一下Bluetooth Android官方對它的解釋︰
BluetoothServerSocket represents an open server socket that listens for incoming requests (similar to a TCP ServerSocket). In order to connect two Android devices, one device must open a server socket with this class. When a remote Bluetooth device makes a connection request to the this device, the BluetoothServerSocket will return a connectedBluetoothSocket when the connection is accepted.
BluetoothServerSocket是一個開放式的server socket,用來監聽任何傳進來的請求(原理類似TCP ServerSocket)。為了讓2隻Android devices能夠連線,其中一隻裝置必須開啟server socket。當遠端的藍芽裝置向手上這隻裝備請求連線後,這隻裝置上的BluetoothServerSocket會回傳一個accepted的 BluetoothSocket給呼叫那一方。

因此我們知道,上面程式碼中

BluetoothSocket  socket = mmServerSocket.accept();


就是應證了BluetoothServerSocket會吐BluetoothSocket出來這件事。

回到一開始呼叫AcceptThread.start()的那個時間點,
也就是說,
程式在一啟動時,
都先要求使用者開啟藍芽,
然後隨時準備接收別臺藍芽裝置會傳送連線請求的事件。

我們取到了BluetoothSocket後,
看看這個BluetoothSocket能做些什麼。

首先,
在官方技術文件提到︰
BluetoothSocket represents the interface for a Bluetooth socket (similar to a TCP Socket). This is the connection point that allows an application to exchange data with another Bluetooth device via InputStream and OutputStream.
BluetoothSocket是一個Bluetooth socket的接口(原理類似TCP Socket)。這個連結點允許APP透過InputStream和OutpusStream互相交換資料。

因此我們得知,
BluetoothSocket可以讓我們做到資料交換的功能。

因為在Service onStart()呼叫AcceptThread.start()後,
馬上將藍芽狀態設定成setState(STATE_LISTEN);
因此,在switch迴圈中,
程式執行了connected()函式。

這段程式碼如下︰

case STATE_LISTEN:
case STATE_CONNECTING:
    // Situation normal. Start the connected thread.
    connected(socket, socket.getRemoteDevice());
    break;

馬上來看看connected()函式做了哪些事

/**
 * Start the ConnectedThread to begin managing a Bluetooth connection
 * @param socket  The BluetoothSocket on which the connection was made
 * @param device  The BluetoothDevice that has been connected
 */
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
    if (D) Log.d(TAG, "connected");
 
    // Cancel the thread that completed the connection
    if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
 
    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
 
    // Cancel the accept thread because we only want to connect to one device
    if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
 
    // Start the thread to manage the connection and perform transmissions
    mConnectedThread = new ConnectedThread(socket);
    mConnectedThread.start();
 
    // Send the name of the connected device back to the UI Activity
    Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
    Bundle bundle = new Bundle();
    bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
    msg.setData(bundle);
    mHandler.sendMessage(msg);
 
    setState(STATE_CONNECTED);
}

為了避免重覆連線,
先檢查有沒有已存在的ConectThread、ConnectedThrad和AcceptThread。
如果有,一律先關掉。
然後,啟動ConnectedThread,
並將MESSAGE_DEVICE_NAME用handler(mHandler,還記得我們前面有提到在BluetoothChat.java傳了一個主Thread的Handler給Service嗎?)傳訊的方式,
將Client端的裝置資料傳回BluetoothChat.java,
讓Server端知道是誰在跟它做連結。

前面提到,
一旦取得了BluetoothSocket之後,
就可以開始執行互相傳遞資料的工作了 。
這個被啟動的ConnectedThread就是在做資料互傳的監聽工作
我們看看ConnectedThread做了些什麼

/**
  * This thread runs during a connection with a remote device.
  * It handles all incoming and outgoing transmissions.
  */
 private class ConnectedThread extends Thread {
     private final BluetoothSocket mmSocket;
     private final InputStream mmInStream;
     private final OutputStream mmOutStream;
 
     public ConnectedThread(BluetoothSocket socket) {
         Log.d(TAG, "create ConnectedThread");
         mmSocket = socket;
         InputStream tmpIn = null;
         OutputStream tmpOut = null;
 
         // Get the BluetoothSocket input and output streams
         try {
             tmpIn = socket.getInputStream();
             tmpOut = socket.getOutputStream();
         } catch (IOException e) {
             Log.e(TAG, "temp sockets not created", e);
         }
 
         mmInStream = tmpIn;
         mmOutStream = tmpOut;
     }
 
     public void run() {
         Log.i(TAG, "BEGIN mConnectedThread");
         byte[] buffer = new byte[1024];
         int bytes;
 
         // Keep listening to the InputStream while connected
         while (true) {
             try {
                 // Read from the InputStream
                 bytes = mmInStream.read(buffer);
 
                 // Send the obtained bytes to the UI Activity
                 mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
                         .sendToTarget();
             } catch (IOException e) {
                 Log.e(TAG, "disconnected", e);
                 connectionLost();
                 break;
             }
         }
     }
 
     /**
      * Write to the connected OutStream.
      * @param buffer  The bytes to write
      */
     public void write(byte[] buffer) {
         try {
             mmOutStream.write(buffer);
 
             // Share the sent message back to the UI Activity
             mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
                     .sendToTarget();
         } catch (IOException e) {
             Log.e(TAG, "Exception during write", e);
         }
     }
 
     public void cancel() {
         try {
             mmSocket.close();
         } catch (IOException e) {
             Log.e(TAG, "close() of connect socket failed", e);
         }
     }
 }

是的!
有看到嗎?
ConnectedThread正在用BluetoothSocket取得InputStream和OutputStream,
並透過旗下的write()和read()在做2隻藍芽裝置的溝通!

現在剩下ConnectThread還沒有去理解了,
查了一下ConnectThread被start的時間是發生在一開始對話頁面的menu鍵中!

原來ConnectThread的目的是要主動連接其它已開啟藍芽的裝置。 
當使用者點擊Connect a device時,
會啟動ConnectThread,
開始尋找附近的藍芽裝置,
並對對方發出連線訊號,
對方監聽到你的配對要求後,
對方手機裡原本程式就開啟中的AcceptThread便答應你的請求,
然後開啟ConnectedThread, 
並利用連結成功後得到的BluetoothSocket和你做藍芽傳輸溝通。

主動連線端是Client端,被動接收端是Server端,
就好像精子與受精卵… 

三、總結
在這裡我把整個程式流程重覆敍述一次︰

在連線的一開始,兩隻手機的程式一開始都先建立一個AcceptThread
(因為誰都不知道誰最後會成為被動接收的Server端,誰又是主動的Client端),
然後都跟RFCOMM頻道索取這隻app專屬的BluetoothServerSocket實體。

Server方做了些什麼︰ 
用BluetoothServerSocket這個實體去等待Client端用ConnectThread發出的請求連線事件
連線若成功會得到這次藍芽溝通專用的BluetoothSocket。

Client方做了些什麼︰ 
Client端執行ConnectThread
1.Client端在與Server方連線(Connect a deivce)之前,
會先取得到Server端的身份證MAC address,
並用該address得到Server端的BluetoothDevice實體。
2.Client端藉由自己的MY_UUID和Server端的BluetoothDevice實體,
從RFCOMM頻道拿到這次藍芽溝通專用的BluetoothSocket。

兩方在這個時候都拿到這次藍芽溝通專用的BluetootheSocket, 
也都在此時知道了對方的BluetoothDevice實體(知道對方的身份)。
這時候雙方都同時開啟ConnectedThread, 
彼此利用BluetoothSocket互相做資料傳輸。

註︰資料傳輸利用 InputStream和OutputStream。 

轉載:小鰻的Android學習筆記




















其它文章

標籤

Oracle (150) Oracle DB (144) Oracle_DB (143) Oracle SQL (135) JAVA (84) css-基本類 (65) MySQL (59) CSS Selector (58) jQuery (49) JavaScript-基本類 (39) Spring Boot (38) JavaScript (37) JavaScript HTML DOM (37) JavaScript-HTML_DOM (36) CSS3 (30) JAVA-基本類 (28) jQuery UI (27) Apache (23) Oracle GROUP BY (20) datepicker (20) Android (18) Oracle Date (17) c (17) JAVA-lang套件 (16) Linux (16) Oracle Sub Query (16) Spring-基本類 (16) jQuery-基本類 (16) MySQL-進階系列教學 (15) Android基本類 (14) Grails (14) Oracle join (14) SQLite (13) Spring (13) WIN7-基本類 (13) grails-基本類 (13) linux cent os (13) CKEditor (12) JAVA-流程控制類 (12) JAVA_Spring (12) PHP (11) Spring MVC (11) MySQL-基本系列教學 (10) Notepad (10) Notepad++ (10) SQLite for java (10) Windows (10) c/c++ (10) eclipse (9) jQuery-Selector (9) sqldeveloper (9) DB_Toad (8) JAVA_IDE_Eclipse (8) JavaScript-String類 (8) MySQL DB Toad (8) MySQL-DATE相關 (8) MySQL-函式相關 (8) Spring Bean (8) Android Studio (7) HTML5 (7) Hibernate (7) JAVA-OCWCD (7) JavaScript-陣列類 (7) Docker (6) JAVA-程式分享 (6) JAVA.util套件 (6) JavaScript-數學類 (6) MinGw (6) MySQL-其它類 (6) Servlet (6) centos (6) Apache_Tomcat (5) Apache套件_POI (5) CSS (5) JavaScript-Date物件 (5) JavaScript-其它類 (5) PostgreSQL (5) httpd (5) log4j (5) 基本資訊 (5) 開發工具 (5) CSS Properties (4) Dev-C++ (4) IntelliJ IDEA (4) Oracle DDL (4) Sublime (4) TortoiseSVN (4) apache_Maven (4) Android NDK (3) Eclipse IDE for C/C++ (3) Hibernate-基本類 (3) JAVA-問題 (3) JAVA-綀習分享 (3) JVM (3) Linux 指令 (3) Proxy Server (3) Spring Mobile (3) Spring web (3) Squid (3) VirtualBox (3) maven (3) zk (3) 生活其它 (3) Bootstrap (2) Filter (2) JAVA_IO (2) JAVA_其它_itext套件 (2) JBoss-問題 (2) JSP (2) Jboss (2) Listener (2) MySQL-語法快速查詢 (2) Spring AOP (2) Spring Batch (2) Spring Boot Actuator (2) Spring i18n (2) Subversive (2) Tomcat 8 (2) UML (2) WebJars (2) WinMerge (2) c++ (2) c語言綀習題 (2) jQuery Mobile (2) jQuery-事件處理 (2) jQuery-套件類 (2) putty (2) svn (2) weblogic (2) Apache_JMeter (1) Apache套件_BeanUtils (1) Apache套件_StringUtils (1) Base64 (1) Google API (1) HTML5-基本類 (1) Heap (1) JAVA 7 (1) JAVA SE 、JAVA EE、JAVA ME (1) JAVA 日期 (1) JAVA-OCJP (1) JAVA-WEB (1) JAVA_IDE (1) JAVA其它 (1) JBoss Server (1) JDK (1) JMX (1) JRE (1) Java RMI (1) Java String (1) Joda Time (1) Linux_其它 (1) MySQL教學 (1) Oracle_VirtualBox (1) SQL Server (1) SWT (1) Session (1) Stack (1) Struts 2 (1) Tool (1) ZK Studio (1) csv (1) grails-其它類 (1) jQuery-進階 (1) java mail (1) java web (1) java8 (1) jsoup (1) mockmvc (1) modules (1) tomcat (1) win10 (1) 其它類 (1) 圖片工具 (1) 模擬器 (1) 讀書分享 (1) 開發資訊 (1)

精選文章

初學 Java 的 HelloWorld 程式

撰寫一個JAVA程式 public class HelloWorld{ public static void main(String[ ] args){ System.out.println("我第一支Java程式!!"); } } ...