<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    amp@java

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      99 隨筆 :: 0 文章 :: 228 評論 :: 0 Trackbacks

    #

    JMF(Java Media Framework)是Java平臺使用攝像頭、麥克風等媒體設備的應用程序框架,但到了2.1.1e就不再更新,在Windows 7 X64上還能正常運行,只是安裝的界面讓你感覺回到了Windows98的時代。


    不過年代久遠的東西,雖然還能用,但可能會遇到一些奇怪的問題,折騰了兩個月,發現了兩個比較大的問題:

    第一個是在Windows 7 x64上提示攝像頭初始化失敗的問題。這個問題很奇怪,電腦剛開機的時候可以順利找到一次攝像頭并正常操作,但是第二次就會提示攝像頭初始化失敗。有人提出的解決方法是安裝一個叫ManyCamera的程序,這個程序可以把一個攝像頭供多個程序同時使用,其實就等于中間加了一層轉換,效果會有點差別,免費版還會加上水印,要求比較高的人可能會不爽,但是目前找不到其他辦法。

    第二個是在程序中找不到攝像頭,不光找不到攝像頭,其他媒體設備通通找不到,使用以下語句:
    vector = CaptureDeviceManager.getDeviceList ( null )
    按照文檔說明是返回所有媒體設備,但每次vector都是null。
    在Eclipse中運行又能正常,導出成jar之后運行就會找不到攝像頭。
    原因在于找不到jmf.properities文件,該文件包含所有檢測到的媒體設備的信息,最簡單的解決方法就是把JMF安裝目錄下lib子目錄中的jmf.properties文件復制到最后運行的jar所在的目錄,不過如果攝像頭改過的話,重新檢測后要把新的文件復制到jar目錄,因為檢測到的媒體設備信息都會存放在JMF安裝目錄里面的jmf.properties文件里。

    StackOverflow里面有個人對這個問題解釋得比較清楚:
    http://stackoverflow.com/questions/8768142/java-capturedevicemanagergetdevicelist-is-empty


    雖然問題解決了,但是還是不明白為何在Eclipse中可以正常運行,導出jar后運行卻找不到攝像頭,即使把JMF所有jar和lib目錄都加入系統的CLASSPATH環境變量里還是不行。


    另外,JMF安裝程序會自動把它的jar和lib目錄加入系統的%CLASSPATH%環境變量,但是如果你卸載了再重新安裝到其他目錄,并不會改變%CLASSPATH%的值,需要手動修改。不過這個環境變量似乎沒啥用處。
    最好不要把JMF安裝到默認的Program Files目錄,可能會運行不了,安裝到短目錄會比較保險,它似乎還是只認Dos時代的8.3目錄結構,但偏偏又默認安裝到Program Files里面。
    posted @ 2014-07-01 10:33 amp@java 閱讀(7275) | 評論 (0)編輯 收藏

    其實我也搞不懂Windows的域,反正能用就行了。
    但是最近有一臺客戶端的時間改不了,總是提示特權級不夠,按理說應該是組策略限制了,但是我把那臺計算機從包含該組策略的OU中移出來,還是不行,這就奇怪了,難道組策略不是指針對OU里面的成員的嗎?百思不得其解啊,最后只能在BIOS里面把時間改了。
    今天發現我自己的電腦設置不了屏幕保護,也是組策略限制了,然后把我的用戶和計算機都移出了組策略應用的OU,結果發現還是設置不了,這下肯定是組策略的應用上有問題了。
    搜索了半天發現有個叫rsop.msc的管理工具,可以看到某用戶在某計算機上應用的組策略,結果發現我還是應用之前的組策略,但是計算機配置和用戶配置前面都有個紅叉,右鍵-屬性-錯誤信息里面顯示:
    Title
    由于下面列出的錯誤,組策略結構 失敗。

    系統找不到指定的路徑。

    注意: 由于 GP Core 失敗,其它組策略組件沒有一個處理了它們的策略。因此,其它組件的狀態信息不可用。
    好像是有某個組策略找不到,所以不能應用的意思。
    然后想起來在域名下面有個“新建組策略”,但是沒有做過任何配置,應該是有人手賤點了一下新建按鈕加進去的,于是把它刪除,還是不行。
    重啟了一下客戶端,居然好了,時間也可以改了,屏幕保護也可以改了,一切都按計劃進行。


    莫名其妙~~
    posted @ 2014-06-23 16:11 amp@java 閱讀(1347) | 評論 (0)編輯 收藏

    現在的手機攝像頭動輒幾百萬上千萬像素,如果電腦需要用到攝像頭又沒有的話,不妨用手機的攝像頭代替。

    我是在做一個電腦二維碼識別器的時候,因為原來的攝像頭太差,從而想到用一臺淘汰的Android手機來代替。

    這類應用應該不少,我首先找到的是一個叫DraoidCam的應用,裝好之后發現免費版沒法調整分辨率,于是放棄之。

    然后又找到了一個國內做的免費軟件,叫魅色,非常簡單,支持USB和WiFi連接方式,如果是USB連接的話,打開USB調試模式之后,運行電腦的客戶端,手機上就自動裝上了App并且自動運行,可以調整分辨率,不過最高只有640*480,幀率不到10,不過已經能夠滿足我的需求了。

    然后就可以像普通PC攝像頭一樣使用了,在JMF里面也能找到,于是就可以被Java調用了。經測試,效果比原來的PC攝像頭好多了。

    軟件主頁:http://www.libfetion.org/meise/
    posted @ 2014-06-05 15:35 amp@java 閱讀(1722) | 評論 (4)編輯 收藏

         摘要: TabActivity在API 13(Android 3.2)被標記為過期,需要使用Fragment來實現,Fragment是Android 3.0引入的一個概念,主要就是為了適應各種不同的屏幕大小(手機、平板電腦)。Android 4.1發布時,google還發布了一個Android Support v4的包,用于Android 1.6以上的系統兼容新的特性,其中包括Fragment。為了在低于...  閱讀全文
    posted @ 2012-12-27 19:07 amp@java 閱讀(15645) | 評論 (0)編輯 收藏

    SQL Server 2000的導入導出功能還是不錯的,支持各種各樣的數據庫,但是卻有好多奇怪的bug,不能直接操作,幾乎每一步都要上網搜索,最后搞定了,一定要記下來:
    1、在同一臺電腦上裝好SQL Server 2000的客戶端和Oracle 10g的客戶端,并分別設置好到源數據庫(SQL Server 2000數據庫)和目標數據庫(Oracle 數據庫)的連接,兩個數據庫都有圖形界面的企業管理器,很容易設置好;
    2、在控制面板-管理工具-數據源里添加一個DSN,驅動程序選擇類似“Oracle in OraClient10g_home1”的,確定之后輸入Data Source Name(隨意),Description(隨意),TNS Service Name(在企業管理器里設置好的連接名),User ID(用戶名),然后按Test Connection測試是否連接成功,成功之后點OK;
    3、在SQL Server 2000的企業管理器里,在任意一個表上點右鍵,所有任務,導出數據,在目的里選擇“Oracle in OraClient10g_home1”,用戶/系統DSN里面就會出現剛才設置好的DSN名字,選中,然后輸入用戶名密碼,點兩次下一步就會出現選擇源表和視圖對話框
    4、這里要注意的是,勾上源中的某個表,在目的里面就會出現"用戶名"."表名"的默認選項,如果你剛才使用的Oracle用戶名是小寫的話,這里也會是小寫,一定要改成大寫,否則會提示該用戶名不存在

    目的也可以使用Microsoft OLE DB Provider for Oracle,在屬性里面設置服務器名稱為Oracle的TNS名稱,用戶名和密碼輸入Oracle用戶名和密碼,測試連接通過即可,后面的步驟都一樣。

    如果出現以下錯誤:

    OLE DB 提供程序 'MSDAORA' 報錯。

    [OLE/DB provider returned message: 未找到 Oracle 客戶端和網絡組件。這些組件是由 Oracle 公司提供的,是 Oracle 8i (或更高) 客戶軟件安裝的一部分。

     

    在安裝這些組件之前,將無法使用此提供程序。]

    OLE DB 錯誤跟蹤[OLE/DB Provider 'MSDAORA' IDBInitialize::Initialize returned 0x80004005:  


    就要修改注冊表,有人已經作出了詳細的修改說明,在這里可以看到:
    http://www.cnblogs.com/autumn/articles/splinkedserver.html

    我把那個表也貼在這里:
    Oracle Client  Microsoft Windows NT、
    Oracle Microsoft Windows 95、
    Client Windows 98 和 Windows 98 SE
    Microsoft Windows 2000/XP/2003
    7.x [HKEY_LOCAL_MACHINE\SOFTWARE
    \Microsoft\TransactionServer\Local Computer\My Computer]
    "OracleXaLib"="xa73.dll"
    "OracleSqlLib"="SQLLib18.dll"
    "OracleOciLib"="ociw32.dll

     

    [HKEY_LOCAL_MACHINE\SOFTWARE
    Microsoft\MSDTC\MTxOCI]
    "OracleXaLib"="xa73.dll"
     "OracleSqlLib"="SQLLib18.dll"
     "OracleOciLib"="ociw32.dll"
     
    8.0 [HKEY_LOCAL_MACHINE\SOFTWARE
    \Microsoft\Transaction Server
    \Local Computer\My Computer]
    "OracleXaLib"="xa80.dll"
    "OracleSqlLib"="sqllib80.dll"
    "OracleOciLib"="oci.dll"
     
    [HKEY_LOCAL_MACHINE\SOFTWARE
     \Microsoft\MSDTC\MTxOCI]
     "OracleXaLib"="xa80.dll"
     "OracleSqlLib"="sqllib80.dll"
    "OracleOciLib"="oci.dll"
    8.1 [HKEY_LOCAL_MACHINE\SOFTWARE
    \Microsoft\Transaction Server
    \Local Computer\My Computer]
    "OracleXaLib"="oraclient8.dll"
    "OracleSqlLib"="orasql8.dll"
    "OracleOciLib"="oci.dll"
     
    [HKEY_LOCAL_MACHINE\SOFTWARE
     \Microsoft\MSDTC\MTxOCI]
    "OracleXaLib"="oraclient8.dll"
    "OracleSqlLib"="orasql8.dll"
    "OracleOciLib"="oci.dll"
     
    9.0 [HKEY_LOCAL_MACHINE\SOFTWARE
    \Microsoft\Transaction Server
    \Local Computer\My Computer]
    "OracleXaLib"="oraclient9.dll"
    "OracleSqlLib"="orasql9.dll"
    "OracleOciLib"="oci.dll"
    [HKEY_LOCAL_MACHINE\SOFTWARE
     \Microsoft\MSDTC\MTxOCI]
    "OracleXaLib"="oraclient9.dll"
    "OracleSqlLib"="orasql9.dll"
    "OracleOciLib"="oci.dll"
     
    10.0 [HKEY_LOCAL_MACHINE\SOFTWARE
    \Microsoft\Transaction Server
    \Local Computer\My Computer]
    "OracleXaLib"="oraclient10.dll"
    "OracleSqlLib"="orasql10.dll"
    "OracleOciLib"="oci.dll"
    [HKEY_LOCAL_MACHINE\SOFTWARE
     \Microsoft\MSDTC\MTxOCI]
    "OracleXaLib"="oraclient10.dll"
    "OracleSqlLib"="orasql10.dll"
    "OracleOciLib"="oci.dll"
     
    posted @ 2012-04-28 10:22 amp@java 閱讀(2565) | 評論 (0)編輯 收藏

    當讀寫二進制文件,或者要把非標準長度的整數與標準長度的整數互相轉換時,就要用到大量的位操作,雖然看起來很簡單,實際上里面卻有很多細節很容易出錯。

    首先,Java有些標準跟C/C++是不同的:

    1、Java采用高字節在前的方式讀寫數據,例如要把一個4字節的int數值寫入文件時,它是按照從高字節到低字節的順序寫入的,讀取的時候也是這樣讀出來。
    而C/C++則采用平臺相關的方式,在Windows平臺采用低字節在前的方式,在Linux/Unix平臺則采用高字節在前的方式。
    如果Java要讀取C/C++創建的二進制文件,就要注意這個問題,最好先搞清楚原來的文件是采用哪種方式創建的。網絡通信也要注意。

    2、Java沒有無符號數,無論byte,short,int,long都是有符號整數,而C/C++有個unsigned關鍵字可以設置一個數值為無符號數。

    3、Java的整數基本數據類型就是byte,short,int,long這幾個,長度分別為1,2,4,8字節,C/C++可以用typedef定義各種數據類型。

    第二,Java是采用補碼來存放整數的。
    有時候覺得補碼的定義有些奇怪,實際上可以這樣理解:

    把一個整數從0一直往上加1,加到溢出就變成了負數的最小值,然后再繼續加1,最后又能回到0,實際上就是一個輪回。
    例如一個byte類型的整數,一共有8位,能表示256個數值,采用補碼的話數值范圍就是-128~127,表示方法如下:
    0        0000 0000
    1        0000 0001
    .
    .
    126    0111 1110
    127    0111 1111
    -128   1000 0000
    -127   1000 0001
    .
    .
    -1       1111 1111
    0         0000 0000

    第三、不同長度的整數轉換。
    如果是從較短的數轉成較長的數,很簡單,如果是正數就在高字節補0,如果是負數就在高字節補1。
    例如byte的127轉為short的127:
    byte:0111 1111
    short:0000 0000 0111 0111
    byte的-127轉為short的-127
    byte:1000 0001
    short:1111 1111 1000 0001
    如果是從較長的數轉成較短的數,實際上就是把高位都截斷了,所以轉出來的數值可能完全不是一回事了。
    例如short的256轉為byte:
    short:0000 0001 0000 0000
    byte: 0000 0000
    把256變成了0
    short的-255轉成byte:
    short:1111 1111 0000 0001
    byte:0000 0001
    把-255變成了1

    第四、位運算操作符及它們的優先級
    Java的位運算操作符包括:~非,|按位或,&按位與,^按位異或,<<左移,>>右移,>>>右移左側補0
    各種運算符的優先級如下表所示:
    優先級
    運算符
    結合性
    1
    () [] .
    從左到右
    2
    ! +(正) -(負) ~ ++ --
    從右向左
    3
    * / %
    從左向右
    4
    +(加) -(減)
    從左向右
    5
    << >> >>>
    從左向右
    6
    < <= > >= instanceof
    從左向右
    7
    == !=
    從左向右
    8
    &(按位與)
    從左向右
    9
    ^
    從左向右
    10
    |
    從左向右
    11
    &&
    從左向右
    12
    ||
    從左向右
    13
    ?:
    從右向左
    14
    = += -= *= /= %= &= |= ^= ~= <<= >>= >>>=
    從右向左
    根據該表可以看到,位運算操作符的優先級各有不同,分別為:
    1、~
    2、>> << >>>
    3、&
    4、^
    5、|
    另外需要特別注意的是,除了~,其他位運算操作的優先級都低于加減,所以要記得以下語句是返回32而不是7!
    1<<2+3
    還有就是&、^、|的優先級都是低于邏輯操作符的,因此下面的語句會編譯出錯,幸好Java不像C那樣對所有大于1的值都認為是真,否則下面的語句也能編譯通過,但可能與你的意圖不太一樣,可能調試半天才發現。
    if(3&1>0)
    如果記不清楚,還是按照你的意圖加上括號最保險。

    第五、字節數組與整數之間的轉換
    為了把一個整數存入文件,或者從文件中讀取一個整數,需要經常在字節數組和整數之間轉換,這個過程要用到大量的位運算。
    首先需要記住的是,在參與所有運算前,Java都會把byte、short類型的值都轉換成int,然后再對轉換后的int進行操作。例如下面的語句會編譯出錯:
    byte a=10,b=20,c;
    c=a+b;

    因為a和b在相加前都被轉成了int,最后得到的結果是個int類型的值,如果要賦給byte類型的c,必須顯式地進行類型轉換,即把第二句改為:
    c=(byte)(a+b)

    這一點很關鍵,因為對于一個最高位為1的byte類型的整數(負數),在運算之前它會被強制轉換成int類型,根據上面所說的第三點,其實就是往前面的三個高字節補上1,這樣一來,它在參與位運算的過程中,就不僅僅是它本身的8個bit參與了,實際上連前3個字節的24個bit(均為1)也參與了。例如有一個整數i=1082163328,它的二進制表示為:
    01000000 10000000 10000000 10000000
    分為4個字節存儲,除了第一個字節是正數外,其余3個字節均為負數。假如用a代表最高字節的值,用b代表其他三個字節的值,如果按照通常的理解,你可能會這樣得到i的值:
    i=(a<<24)+(b<<16)+(b<<8)+b

    如果a和b都是正數,上面的等式是成立的,但是在這個例子里,卻是錯的,因為上式中的a和b都已經被強制轉換成了int類型再參加運算,實際上
    a=00000000 00000000 00000000 01000000
    b=11111111 11111111 11111111 10000000
    i=01000000 00000000 00000000 00000000+11111111 10000000 00000000 00000000+11111111 11111111 10000000 00000000+11111111 11111111 11111111 10000000
    最后得到的結果是1065320320,不是原來的值了。
    為了不讓byte在強制轉換成int的過程加入了我們不想要的高位1,我們需要把它跟0xff進行與操作,i的值應該這樣運算:
    = ( ( a& 0xff ) << 24 ) +( ( b & 0xff ) << 16 ) + ( ( b & 0xff ) << 8 ) + ( b & 0xff )

    注意,因為&和<<的優先級都低于+,所以上面的括號是不能少的。不過由于跟0xff與操作之后,其余24位都變成了0,因此可以把+改為|操作,因為任何值與0進行或操作都得到本身:
    = ( a & 0xff ) << 24 | ( b & 0xff ) << 16 | ( b & 0xff ) << 8 | ( b & 0xff )

    由于<<的優先級高于|,所以省了一些括號。最高字節可以不與0xff進行與操作,因為它轉換成int后左邊增加的3個字節都在左移24位時被去掉了:
    = a << 24 | ( b & 0xff ) << 16 | ( b & 0xff ) << 8 | ( b & 0xff )


    把int轉為字節數組的時候比較簡單,直接右移截斷即可:
    byte[] b = new byte[4];
    b[0= (byte) (i >> 24);
    b[1= (byte) (i >> 16);
    b[2= (byte) (i >> 8);
    b[3= (byte) i;


    第六、非標準長度整數的存儲和讀取
    假如有兩個變量,他們的值可以用12個bit來表示,如果我們用16bit的short類型來表示一個變量,那么兩個變量就需要4個字節,而實際上它們只需要3個字節就能表示出來,如果存儲空間比較有限,寫入文件時可以把它們存放在3個字節里面,但是讀寫過程就需要進行轉換。
    在內存里,它們都是標準的數據類型:
    short a,b;

    寫入文件時,我們用第一個字節和第二個字節的前半部分來表示a,把第二個字節的后半部分和第三個字節來表示b,即:
    1:xxxx xxxx
    2:xxxx yyyy
    3:yyyy yyyy
    x和y都表示一個bit,分別用來存放a和b。寫入時先把a和b轉為字節數組:
    byte[] out = new byte[3];
    out[
    0= (byte) ( a >> 4 );//把a的高8位放在第一個字節
    out[1= (byte) ( a << 4 );//先把a左移四位,在右邊補上4個0,第二個字節的高4位就是a的低4位了,第二個字節的高4位已經生成,低4位還是0
    out[1|= (byte) ( b >> 8 & 0x0f );//b右移8位,并與0x0f進行與操作,實際上就只保留了b的高4位,并且是在字節的低4位上,跟第二步得到的字節進行或操作,就生成了第二個字節
    out[2= (byte) b;//把b的高4位截斷就得到了低8位
    然后再把這個字節數組寫入文件,就可以用3個字節表示兩個整數了。
    讀取:
    =(short)( (out[0& 0xff<< 4 | ( out[1& 0xf0 )>>4);
    = (short)((out[1& 0x0f<< 8 | ( out[2& 0xff));
    posted @ 2012-04-08 16:56 amp@java 閱讀(1840) | 評論 (2)編輯 收藏

    AdMob是往手機應用程序里添加廣告的最流行的方式,Android程序基本都是靠這個賺錢。看文檔似乎很簡單,但是操作起來卻不是那么回事,今天搞了一上午才弄明白怎么正確添加,網上搜索到的資料都不適合最新的SDK。

    按照AdMob的官方文檔,很簡單,只要把AdMob的開發包jar放到Build Path的Libraries里面就行了,這樣做編譯是沒問題的,但是一運行就會出錯,提示
    java.lang.NoClassDefFoundError:com.google.ads.AdView
    這是因為Google最近更新了ADT到17.0,改變了項目依賴的檢測方式,官方的說明在這里,不過看得不是很懂。有人用圖形的方式標了出來,容易理解一些,看這里。如果不求甚解,就把剛才放到Build Path里面的jar移除,直接在項目目錄下建立一個libs目錄,然后把那個jar文件放進去就行了。

    AdMob SDK也更新到了4.3.1,網上搜索到的在XML文件里面設置AdView屬性的方法也已過時,現在不需要建立attrs.xml文件,直接增加一個
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    就可以在AdView標簽里面設置ads開頭的屬性了,關于xml設置AdView屬性的官方文檔隱藏得比較深,沒有在目錄中列出來,只能在其他文檔里面的鏈接里進去,在這里
    另外,按照官方說明,要在AndroidManifest.xml里面添加一個Activity的聲明:
        <activity android:name="com.google.ads.AdActivity"
                  android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
    后面那個屬性android:configChanges的最后兩個值screenSize|smallestScreenSize是在Android 3.2后面才增加的,這兩個值必須填上去,否則運行的時候會報錯。如果你使用的SDK是3.2以下的,識別不了這兩個值,編譯也不會報錯。因此你的項目必須使用Android 3.2以上的SDK,也就是項目根目錄下的project.properties文件里面的屬性target的值必須是android-13以上,例如
    target=android-15
    但是可以在AndroidManifest.xml里面設置android:minSdkVersion和android:targetSdkVersion為比13低的值,這樣就不需要安裝Android 3.2以上的手機或平板來運行這個程序,實際上AdMob支持Android 1.5以上的系統,只是開發需要更高版本的SDK而已。


    這次折騰讓我真正體會到Android更新得實在太快了,連官方的文檔都來不及更新,開發人員只能自己摸索總結,幸好有強大的搜索工具,只要你遇到的問題不是第一個,就會有人找到解決方案。



    posted @ 2012-03-25 19:23 amp@java 閱讀(3705) | 評論 (7)編輯 收藏

    SWT里TableEditor的作用是可以在表格里面顯示一些控件,例如列表、按鈕等,有時候是根據表格的內容在控件上顯示不同內容的,如果更新了表格內容,就要同時更新控件,但是表格內容可以通過Table控件的removeAll()來清除,而表格中的控件則無法用這個方法清除,你調用Table的removeAll()方法,往表格里填入新內容后,控件還是上次的控件,但是你一操作那些控件就會出異常,提示那些控件已經disposed。

    解決方法是顯式地調用控件及TableEditor的dispose()方法,在你建立TableEditor的時候,把它的引用保存起來,把里面的控件的引用也保存起來,到整個表格需要的清除的時候,通過引用先把控件dispose掉,再把TableEditor也dispose掉,這樣整個表格的內容就真正清除了。

    例如有一個表格名為table,里面的每一行都有3列,第一列是文本,第二列是Combo,第三列是Button,繪制表格的時候是這樣的:

    TableItem ti = new TableItem(table,SWT.NONE);
    ti.setText(
    0,"some string");
    te 
    = new TableEditor(table);
    Combo combo 
    = new Combo(table,SWT.NONE);
    controls.add(combo);
    te.setEditor(combo,ti,
    1);
    Button button 
    = new Button(table,SWT.NONE);
    controls.add(button);
    te.setEditor(button,ti,
    2);

    其中te和controls都是成員變量,te的類型是TableEditor,controls的類型是ArrayList<Control>。
    當整個table要清除內容時,可以這樣:
    //刪除控件
    for(Control control:controls){
    control.dispose();
    }
    //刪除TableEditor
    te.dispose();
    //刪除文本
    table.removeAll();
    posted @ 2012-03-09 11:09 amp@java 閱讀(3850) | 評論 (0)編輯 收藏

    mars課程里關于Socket通信那一課說那些程序只能在真機上運行,模擬器模擬不了,實際上是可以的。
    Android模擬器是通過一個類似路由器的虛擬網絡層與電腦相連,可以看作模擬器是處于“內網”當中,每個模擬器都有自己的虛擬路由器,而且虛擬路由器的地址總是10.0.2.1,在模擬器看來,電腦的地址是10.0.2.2,模擬器自己的地址是10.0.2.15,無論你啟動多少個模擬器,對于模擬器來說都是這樣的地址,模擬器之間不能直接通信。
    啟動模擬器的時候,電腦會給模擬器分配兩個端口,通過這兩個端口,電腦就能操作模擬器。第一個啟動的模擬器的端口是5554和5555,第二個是5556和5557,以此類推,最多可以同時啟動32個模擬器。第一個端口(偶數端口)可以接受telnet連接,對模擬器進行設置,第二個端口(奇數端口)則接受adb連接,可以用來調試。第一個端口可以在模擬器窗口的標題欄看到,如下圖所示:

    5554表示端口號,t表示模擬器名稱。
    實際上,這些端口也是電腦監聽的端口,在電腦上通過netstat可以看到本機正在監聽這些端口,因此通過telnet localhost 5554就能連上第一臺模擬器,連上之后通過help命令可以查看操作幫助。
    為了實現電腦和模擬器上的android程序進行socket通信,需要把程序開啟的端口通過端口映射設置到電腦上,這跟家里的路由器端口映射概念是一樣的。telnet到模擬器之后,通過
    redir add tcp:1234:1234
    就能把模擬器上的1234端口映射到電腦上,第一個表示電腦端口,第二個表示模擬器程序要使用端口,這兩個數字可以相同也可以不同,要映射udp端口就把tcp改為udp即可
    redir add udp:1234:1234
    這樣一來,當模擬器的程序打開1234端口時,在電腦上也打開了對應的端口,只要通過電腦連接127.0.0.1的對應端口,就連上了模擬器的程序端口,就可以通過電腦上的client向模擬器的server發送數據,不需要通過真機運行。
    如果要讓第一個模擬器向第二個模擬器發送數據,也可以把第二個模擬器的端口映射到電腦上,然后在第一個模擬器程序中向10.0.2.2的對應端口發送數據即可。


    模擬器還有一個很有意思的功能,每個模擬器默認的電話號碼就是它的第一個端口號,例如開了兩個模擬器,第一個撥打5556,第二個就會顯示5554來電,還能接通,發短信也可以,這樣就能模擬電話和短信功能。

    詳細的信息可以看Dev Guide的模擬器部分:http://developer.android.com/guide/developing/devices/emulator.html
    posted @ 2012-02-24 10:37 amp@java 閱讀(2413) | 評論 (0)編輯 收藏

    前天是情人節,雖然結婚好多年了,但是老婆一直都喜歡驚喜的浪漫,可惜我卻是個木訥的呆子,做不出那些轟動的事情。那天下午馬上就要下班回家了,突然在微博上看到有人談到geek的情人節禮物,雖然我不是geek,但是最近在學Android,老婆的手機也是Android系統的,何不專門做個程序給她?

    想法可嘉,但是動起手來卻不是那么回事。學了那么多天,真正派上用場的還沒學到。時間只剩下不到一個小時了,我會的只是在屏幕上顯示幾個大字:XXX,我愛你!

    后來想想似乎太單調,如果能夠加上點背景音樂可能好點,但是還沒學會怎么使用,上網搜了一下,幸好很簡單,用MediaPlayer就可以了,幾條語句就能搞定。音樂文件怎么來呢?通過網絡在線播放是最簡單的,于是就到百度MP3搜了一下“情人節快樂”,我記得有一首歌里面一直在喊“情人節快樂”的,結果最后發現那首歌名字叫《沒有情人的情人節》……

    算了,管它呢,有老婆就行了,沒有情人照樣過情人節,打開發現鏈接居然是百度的,以前百度不是說它只負責搜索,不負責存放嗎,怎么現在的MP3都放在百度的服務器了?把鏈接復制下來,在模擬器上運行還是挺好的,因為它用的是電腦的寬帶,呵呵。不過過了一會提示下載失敗,把那個地址往瀏覽器一貼,果然打不開了,原來百度這種下載鏈接是有有效期的,只能讓你試聽一下,然后下載,不是長期有效的。這就麻煩了,到時候裝在手機上沒聲音豈不是很糗?

    再搜索一下,還好,可以把MP3文件放在assets里面,發布程序的時候把它包含在apk里面就行了,不用聯網了。

    現在可以在顯示大字的同時播放《沒有情人的情人節》了。看了一下效果,還是有點怪異,手機的狀態欄和程序的標題跟黑色的背景,紅色的大字似乎不太搭配,于是繼續搜索全屏代碼,哈哈,兩句搞定,這樣炫多了。

    不過一直看著那幾個字沒任何反應,似乎太單調了,于是就想讓它們不斷變色,或者動一下也好,但是無論怎么弄都搞不定,下班時間到了,要去接老婆了,就這樣吧。

    之前都是在模擬器上運行,或者接個USB在手機上運行,還不知道怎么打包成apk呢,這下居然沒搜索到,可能太簡單了,大家都沒說。于是在項目上點右鍵,果然看到導出apk的菜單,我選擇了unsigned方式導出,在手機上居然安裝不了。再搜索一下,哦,原來是要導出成signed apk才能裝的,但是我沒有證書,怎么signed呢?沒想到ADT還可以生成證書,一下就搞定了,這比Symbian那種簽名簡單多了,但是可能也是導致Android惡意軟件泛濫的原因之一。

    去接老婆的時候通過藍牙把apk發到她手機上,裝上,運行,從她表情上看出,我的努力沒有白費。不過最后還是發現了個嚴重的bug,那首歌還沒放完,另外一個聲音已經重新開始了,形成了“二重唱”的效果,而且程序退出之后還在唱,趕工造成的悲劇啊。

    下面是代碼:
    public class LoveActivity extends Activity {
        TextView text;
        
    /** Called when the activity is first created. */
        @Override
        
    public void onCreate(Bundle savedInstanceState) {
            
    super.onCreate(savedInstanceState);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,   
            WindowManager.LayoutParams.FLAG_FULLSCREEN);  
            requestWindowFeature(Window.FEATURE_NO_TITLE);  
            setContentView(R.layout.main); 
            MediaPlayer mp 
    = new MediaPlayer();
            
    try{
                AssetManager assetManager 
    = getAssets();
                AssetFileDescriptor afd 
    = assetManager.openFd("a.mp3");
                mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                mp.prepare();
                mp.start();
            }
            
    catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    main.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation
    ="vertical"
        android:layout_width
    ="fill_parent"
        android:layout_height
    ="fill_parent"
        
    >
        
    <TextView 
        
    android:id="@+id/textView1" 
        android:text
    ="@string/loveyou" 
        android:layout_width
    ="match_parent" 
        android:layout_height
    ="match_parent" 
        android:gravity
    ="center" 
        android:textColor
    ="#ff0000"
        android:textStyle
    ="bold"
        android:textSize
    ="50dip"
        
    />
        
       
    </LinearLayout>
    strings.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        
    <string name="hello">Hello World, LoveActivity!</string>
        
    <string name="app_name">Love</string>
        
    <string name="loveyou">XXX\n我愛你</string>
    </resources>
    再把那首mp3放到assets里,改名為a.mp3即可。




    希望明年能做出個更好的。
    posted @ 2012-02-16 11:06 amp@java 閱讀(2295) | 評論 (2)編輯 收藏

    僅列出標題
    共10頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
    主站蜘蛛池模板: 亚洲av中文无码乱人伦在线r▽ | 亚洲网址在线观看| 日本视频在线观看永久免费| 亚洲成AV人网址| jizz免费在线观看| 亚洲乱码国产一区三区| 免费精品久久天干天干| 图图资源网亚洲综合网站| 日韩免费高清大片在线| 亚洲最大视频网站| 最近中文字幕免费mv视频7| 亚洲国产精品无码久久久秋霞1| 免费无遮挡无码视频网站| 免费播放美女一级毛片| 亚洲日本在线观看视频| 高清一区二区三区免费视频| 久久综合亚洲色一区二区三区| 中文字幕无码视频手机免费看| 亚洲av无码一区二区三区在线播放| 国产福利免费在线观看| 一个人看www免费高清字幕| 国产成人精品日本亚洲网站| 中国xxxxx高清免费看视频| 亚洲精品无码永久在线观看男男| 国产99视频免费精品是看6| 一级黄色片免费观看| 亚洲∧v久久久无码精品| 日韩精品无码区免费专区 | 四虎永久免费网站免费观看| igao激情在线视频免费| 亚洲视频一区调教| 女人18毛片水真多免费播放| 4hu四虎免费影院www| 亚洲沟沟美女亚洲沟沟| 免费国产一级特黄久久| 在线成人精品国产区免费| 亚洲男女一区二区三区| 国产美女无遮挡免费视频| 日本道免费精品一区二区| 亚洲一级大黄大色毛片| 亚洲а∨天堂久久精品|