• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            xiaoguozi's Blog
            Pay it forword - 我并不覺的自豪,我所嘗試的事情都失敗了······習(xí)慣原本生活的人不容易改變,就算現(xiàn)狀很糟,他們也很難改變,在過程中,他們還是放棄了······他們一放棄,大家就都是輸家······讓愛傳出去,很困難,也無法預(yù)料,人們需要更細(xì)心的觀察別人,要隨時(shí)注意才能保護(hù)別人,因?yàn)樗麄兾幢刂雷约阂裁础ぁぁぁぁ?/span>
            android軟件破解的工具:
            smali.jar——google官方提供,主要作用是把smali文件打包成class.dex文件
            baksmali.jar——google官方提供,主要作用是把*.odex文件反編譯為smali文件
            apktool.jar——第三方提供?用于解析*.apk文件,生成smali文件和解析資源文件
            signapk.jar——apk簽名工具
            ddms——ADT中的一個(gè)調(diào)試工具


            破解工具的使用方法:
            http://sin90lzc.iteye.com/blog/1198173


            除了這些破解工具之外,還需要對(duì)smali語法有一定的了解。下面的網(wǎng)址對(duì)smali的語法有詳細(xì)的說明:
            http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html


            最后,最好對(duì)Android的應(yīng)用開發(fā)有一定的了解,至少對(duì)Android的四大組件有深刻的認(rèn)識(shí):Activity,Service,ContentProvider,BroadcastReceiver


            Android應(yīng)用程序在某些機(jī)器上不能運(yùn)行、崩潰的原因不外乎以下幾點(diǎn):
            原因一:該應(yīng)用程序需要依賴于生產(chǎn)廠商的框架(像三星,它對(duì)android的framework做過大量的修改)
            錯(cuò)誤提示:找不到field,找不到對(duì)應(yīng)的方法,找不到相應(yīng)的類
            解決途徑:
            1.在smali中嘗試屏蔽掉相應(yīng)的field,method,或類的調(diào)用,然后進(jìn)行大量測(cè)試,確保不影響正常使用
            2.反編譯framework,找到缺少的field,method,類的相應(yīng)smali文件,根據(jù)smali文件編寫java源碼。(當(dāng)smali文件比較小的時(shí)候,這個(gè)方法才可行,否則盡量避免用這種方法)
            3.實(shí)在無招的情況下,只能把第三方的framework的smali文件復(fù)制到自己的framework里面(非常槽糕的方法)。
            4.對(duì)于應(yīng)用程序需要依賴第三方低層的功能實(shí)現(xiàn)時(shí),而我們的低層卻沒有這樣的功能(比如說視頻通話等),此時(shí)可以使用上面的方法一解決,也可以參考技術(shù)四。


            原因二:資源文件不存在,像color,drawable,string等等的資源
            錯(cuò)誤提示:資源文件找不到
            解決途徑:
            在技巧一中有詳細(xì)說明。


            原因三:應(yīng)用程序需要一些函數(shù)庫的支持(在目錄/system/lib中缺少相應(yīng)的函數(shù)庫)。
            錯(cuò)誤提示:一般都會(huì)拋出UnSatisfiedException異常,后面緊跟所缺函數(shù)庫的庫名。
            解決途徑:
            1.在第三方的函數(shù)庫中找到對(duì)應(yīng)的so文件,然后復(fù)制到自己的函數(shù)庫中。
            2.如果函數(shù)庫與函數(shù)庫之間有著各種耦合的時(shí)候,方法一可能就會(huì)不適用了(看運(yùn)氣唄)。這時(shí)候就只能反編譯so文件了(這個(gè)是C/C++的反編譯的應(yīng)用了,需要再學(xué)習(xí))


            原因四:應(yīng)用程序沒有相應(yīng)的權(quán)限
            錯(cuò)誤提示:nopermission
            解決途徑:
            1.在AndroidMenifest.xml文件中添加<user-permision />添加相應(yīng)的權(quán)限


            原因五:由于應(yīng)用程序本身的一些安全機(jī)制或條件判斷影響程序的表現(xiàn)
            解決途徑:
            1.反編譯成smali文件,使用技巧三的方法跟蹤程序的運(yùn)行,耐心地分析程序的邏輯,找到可疑smali代碼,屏蔽或修改代碼。


            原因六:數(shù)據(jù)庫的結(jié)構(gòu)不一樣
            錯(cuò)誤提示:缺少某個(gè)字段或類型不匹配
            場(chǎng)情:比如android的音樂播放器與三星的音樂播放器,它們的數(shù)據(jù)庫結(jié)構(gòu)由MediaProvider.apk這個(gè)包提供。然而兩者在MediaProvider.apk中關(guān)于數(shù)據(jù)庫結(jié)構(gòu)的定義是不一樣的,三星音樂播放器需要更多的字段去保存信息。
            解決途徑:
            1.拿上面場(chǎng)情為例,反編譯MediaProvider.apk,從smali文件中找到組件ContentProvider的定義(smali文件), 在該smali文件中找到關(guān)于SQL生成表結(jié)構(gòu)的字符串(如:create table...),修改該SQL語句來適合三星音樂播放器的需要,然后重新打包回apk文件。


            原因七:應(yīng)用程序需要引用第三方提供商自定義的框架(比如,三星的/system/framework目錄下有twframework.jar、twframework-res.apk,這個(gè)就是三星的UI框架)

            錯(cuò)誤提示:
            解決途徑:
            1.屏蔽AndroidMenifest.xml文件中<uses-library android:name="sec_feature" />的代碼,一般這樣改動(dòng)是不可行的。
            2.在/system/etc/permission目錄下添加庫的聲明,如添加touchwiz.xml文件,文件內(nèi)容如下:
            <?xml version="1.0" encoding="utf-8"?>
            <permissions>
                <library name="touchwiz" file="/system/framework/twframework.jar"/>
            </permissions>
            最后,還需要把三星的twframework.jar、twframework-res.apk復(fù)制到/system/framework目錄下

            反編譯或破解的技巧總結(jié):
            一、對(duì)無應(yīng)用程序源碼的情況下,對(duì)資源文件的增刪改。
            概述:在無程序源碼,不重新編譯的情況下,刪除或修改資源文件都是非常簡(jiǎn)單的一件事情,網(wǎng)上也有很多的文章提到過。但是網(wǎng)上卻找不到在不重新編譯的情況下添加資源文件的方法。
            在不重新編譯的情況下添加資源文件的步驟:
            1.按正常的應(yīng)用程序開發(fā)添加資源。比如,要添加一個(gè)string資源,在values/strings.xml上加上:
            <string name="newstring">content</string>


            2.一個(gè)編譯后的apk會(huì)在values目錄下多生成了一個(gè)public.xml文件,這個(gè)文件記錄了每個(gè)資源的引用編號(hào)。以添加string資源為例, 在public.xml文件中找到<public type="string" ...>中最后一個(gè)元素,在這個(gè)元素后添加
            <public type="string" name="newstring" id="0x7f0700a0" /><!--此時(shí)id就是string資源newstring的引用編號(hào),注意該id應(yīng)該是public.xml文件中是唯一值-->


            3.修改smali文件,使用新增的資源
            invoke-virtual {p0}, Lcom/sini/SfsdfsActivity;->getResources()Landroid/content/res/Resources;


            move-result-object v0


            const v1, 0x7f0700a0


            invoke-virtual {v0, v1}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;


            二、編寫smali文件
            概述:自己一手一腳去寫smali文件是件超級(jí)困難的事情,如何快速地得到smali代碼呢?
            技巧:使用eclipse開發(fā)工具,新建一個(gè)Android項(xiàng)目,用正常的開發(fā)方式寫一段java代碼(這個(gè)代碼就是你想在smali中完成的東西)。使 用eclipse的run->Android Application選項(xiàng) 生成apk文件,再把a(bǔ)pk文件反編譯,找到需要的smali代碼,然后復(fù)制這段代碼到需要的地方。NOTIC:復(fù)制的時(shí)候需要注意smali的變量 v0,v1...的正確性。


            三、跟蹤程序運(yùn)行
            概述:沒源碼=寸步難行!為了能跟蹤無源碼的apk程序的運(yùn)行,只能辛苦地修改smali添加跟蹤信息了。值得慶幸的是,android本身自帶有方便的日志API(Log.i()\Log.w()...);
            技巧:按技巧二的方法得到Log.i()的smali代碼,然后把這段代碼插入到你想跟蹤信息的地方。


            四、只修改smali中影響UI的代碼,保留功能代碼(適用于必須得把smali寫回java源碼的情況)
            概述:這里最好的例子就是破解三星的通話界面。三星的通話界面程序Phone.apk中包含了視頻通話的功能,這個(gè)功能又需要依賴三星的一些低層實(shí)現(xiàn)。而 我們的系統(tǒng)中沒有視頻通話的功能,也沒有相應(yīng)的低層實(shí)現(xiàn)。但Phone.apk的主要功能是打電話,而這個(gè)功能android本身就自帶的。也就是說三星 的Phone.apk與android的Phone.apk的核心功能是一樣的,只是UI不太一樣而已。此時(shí)應(yīng)該只修改smali中的影響UI的代碼,屏 蔽掉
            smali中對(duì)視頻通話的調(diào)用。
            技巧:找到程序中影響UI的Actvity,然后根據(jù)smali文件的內(nèi)容,寫java源碼
            posted @ 2013-02-17 14:52 小果子 閱讀(3338) | 評(píng)論 (0)編輯 收藏
            原文:
            http://1622511.blog.51cto.com/1612511/581011

            如果你要定制一個(gè)Android系統(tǒng),你想用你自己的Launcher(Home)作主界面來替換Android自己的Home,而且不希望用戶安裝的Launcher來替換掉你的Launcher.
            我們可以通過修改Framework來實(shí)現(xiàn)這樣的功能。

            這里以Android2.1的源代碼為例來實(shí)際說明。

            1)首先了解一下Android的啟動(dòng)過程。
              Android系統(tǒng)的啟動(dòng)先從Zygote開始啟動(dòng),然后......(中間的過程就不說了).....一直到了SystemServer(framework)這個(gè)地方,看到這段代碼:

                  /**
                 * This method is called from Zygote to initialize the system. This will cause the native
                 * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
                 * up into init2() to start the Android services.
                 */
                native public static void init1(String[] args);

                public static void main(String[] args) {
                    if (SamplingProfilerIntegration.isEnabled()) {
                        SamplingProfilerIntegration.start();
                        timer = new Timer();
                        timer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                SamplingProfilerIntegration.writeSnapshot("system_server");
                            }
                        }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
                    }

                    // The system server has to run all of the time, so it needs to be
                    // as efficient as possible with its memory usage.
                    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

                    System.loadLibrary("android_servers");
                    init1(args);
                }

                public static final void init2() {
                    Log.i(TAG, "Entered the Android system server!");
                    Thread thr = new ServerThread();
                    thr.setName("android.server.ServerThread");
                    thr.start();
                }
            }

            從SystemServer的main函數(shù)開始啟動(dòng)各種服務(wù)。
            首先啟動(dòng)init1,然后啟動(dòng)init2.
            從上面的注釋可以看到:init1這個(gè)方法時(shí)被Zygote調(diào)用來初始化系統(tǒng)的,init1會(huì)啟動(dòng)native的服務(wù)如SurfaceFlinger,AudioFlinger等等,這些工作做完以后會(huì)回調(diào)init2來啟動(dòng)Android的service。

            這里我們主要來關(guān)注init2的過程。
            init2中啟動(dòng)ServerThread線程,
            ServerThread中啟動(dòng)了一系列的服務(wù),比如這些:

            ActivityManagerService
            EntropyService
            PowerManagerService
            TelephonyRegistry
            PackageManagerService
            AccountManagerService
            BatteryService
            HardwareService
            Watchdog
            SensorService
            BluetoothService
            StatusBarService
            ClipboardService
            InputMethodManagerService
            NetStatService
            ConnectivityService
            AccessibilityManagerService
            NotificationManagerService
            MountService
            DeviceStorageMonitorService
            LocationManagerService
            SearchManagerService
            FallbackCheckinService
            WallpaperManagerService
            AudioService
            BackupManagerService
            AppWidgetService

            這些大大小小的服務(wù)起來以后,開始
             ((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()
            在systemReady后開始開始啟動(dòng)Launcher。

            在尋找Launcher的時(shí)候是根據(jù)HOME的filter(在Manifest中定義的<category android:name="android.intent.category.HOME" />)來過濾。
            然后根據(jù)filter出來的HOME來啟動(dòng),如果只有一個(gè)HOME,則啟動(dòng)這個(gè)HOME,如果用戶自己裝了HOME,那就會(huì)彈出來一個(gè)列表供用戶選擇。

            我們現(xiàn)在希望從這里彈出我們自己定制的Launcher,同時(shí)也不希望彈出選擇HOME的界面,我們不希望用戶修改我們的home,比如我們的home上放了好多廣告,以及強(qiáng)制安裝的程序,不希望用戶把它干掉。

            我們可以通過這樣來實(shí)現(xiàn):

            2) 定義一個(gè)私有的filter選項(xiàng),然后用這個(gè)選項(xiàng)來過濾HOME.
               一般情況下我們使用Manifest中定義的<category android:name="android.intent.category.HOME"來過濾的,我們現(xiàn)在增加一個(gè)私有的HOME_FIRST過濾。

                 在Intent.java(frameworks/base/core/java/android/content/Intent.java)中添加兩行代碼

                //lixinso:添加CATEGORY_HOME_FIRST
                @SdkConstant(SdkConstantType.INTENT_CATEGORY)
                public static final String CATEGORY_HOME_FIRST = "android.intent.category.HOME_FIRST";

            3)修改和CATEGORY_HOME相關(guān)的所有的地方,都改成HOME_FIRST,主要是framework中的這幾個(gè)地方:

                frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中
                //intent.addCategory(Intent.CATEGORY_HOME);
                改成intent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso:
                //if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
                改成if (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)) { //lixinso: Intent.CATEGORY_HOME -> Intent.CATEGORY_HOME_FIRST
             
               frameworks/base/services/java/com/android/server/am/HistoryRecorder.java中
               // _intent.hasCategory(Intent.CATEGORY_HOME) &&
               改成 _intent.hasCategory(Intent.CATEGORY_HOME_FIRST) && //lixinso: Intent.CATEGORY_HOME->Intent.CATEGORY_HOME_FIRST

               frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java中
               //mHomeIntent.addCategory(Intent.CATEGORY_HOME); 
               改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso
             
              frameworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.java中
               //new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);
               改成 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso

              frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java中
               //mHomeIntent.addCategory(Intent.CATEGORY_HOME);
               改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso

              frameworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.java中
               //ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);
               改成 ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso



            4) 寫一個(gè)自己的Launcher.
               可以參考android sample中的Launcher,或者android源代碼中的 /packages/apps/Launcher 來寫。
               在Launcher中標(biāo)記其是不是Launcher的最關(guān)鍵的代碼時(shí)Manifest中的filter:android:name="android.intent.category.HOME"
               現(xiàn)在我們定義了自己的filter,那么,我們?cè)谖覀冏约簩懙腖auncher中將Manifest改為:
                <application  android:process="android.process.acore3" android:icon="@drawable/icon" android:label="@string/app_name">
                    <activity android:name=".FirstAppActivity"
                              android:label="@string/app_name">
                        <intent-filter>
                                            <action android:name="android.intent.action.MAIN" />
                            <category android:name="android.intent.category.HOME_FIRST" />
                            <category android:name="android.intent.category.DEFAULT" />
                            <category android:name="android.intent.category.MONKEY" />
                        </intent-filter>
                    </activity>
                </application>

            然后將編譯好的apk放到/out/target/product/generic/system/app目錄下。

            5)將Android自帶的Launcher刪除掉,包括源代碼(packages/apps/Launcher)和apk(/out/target/product/generic/system/app/Launcher.apk)。

            6)
            做完這些工作,就可以重新編譯Android了,我們可以編譯修改過的幾個(gè)相關(guān)的包。
            如果之前編譯過了Android源碼,可以用mmm命令來編譯部分的改動(dòng)。
            這里需要這樣編譯:

            $ . build/envsetup.sh 
            $ mmm frameworks/base
            $ mmm frameworks/base/services/java
            $ mmm frameworks/policies/base/mid
            $ mmm frameworks/policies/base/phone

            7)
            編譯完成后重新生成img文件。
            $ make snod

            8) 現(xiàn)在可以啟動(dòng)Android模擬器來看效果了。
            首先設(shè)置環(huán)境變量:
            $ export ANDROID_PRODUCT_OUT= ./out/target/product/generic
            然后切換到
            $ cd ./out/host/linux-x86/bin
            運(yùn)行
            $ ./emulator

            這樣我們啟動(dòng)的模擬器里面用的image就是我們剛才編譯好的自己定制的東西了。
            從模擬器上可以看到啟動(dòng)的Launcher是我們自己的Launcher,不會(huì)出現(xiàn)默認(rèn)的Launcher了,也不會(huì)出現(xiàn)選擇界面。

            9)我們?cè)衮?yàn)證一下,如果用戶裝上了一個(gè)其他的Launcher(Home)會(huì)怎么樣。
              從網(wǎng)上找一個(gè)一般的Launcher或者自己寫一個(gè)一般的Launcher裝上去,重新啟動(dòng),不會(huì)出現(xiàn)選擇界面。
              按HOME鍵也不會(huì)出來兩個(gè)HOME來選擇。


            這樣我們就牢牢控制了用戶的桌面。
            只有我們自己定制的HOME才能裝上。 這對(duì)于定制Android設(shè)備的廠商很有用處。
            posted @ 2013-02-17 14:51 小果子 閱讀(1506) | 評(píng)論 (0)編輯 收藏
            要移植,就要了解系統(tǒng)的結(jié)構(gòu)和打包解包:
            打包很容易,只需要制作成ZIP格式的壓縮包就行了,里面包含2個(gè)文件夾和1個(gè)boot.img文件,boot.img是內(nèi)核,沒有內(nèi)核的系統(tǒng)是不能運(yùn)行 的,另外兩個(gè)文件夾一個(gè)是system,也就是Android系統(tǒng)所在地,另一個(gè)是META-INF,這里一般存放是刷機(jī)腳本,我們移植一般需要改的就是 system文件夾里的內(nèi)容。
            解包就是解壓縮。
            首先說結(jié)構(gòu),system下有:
            App文件夾(存放內(nèi)置軟件的地方,每個(gè)軟件都有自己的名字標(biāo)注著,很容易識(shí)別,在移植上除USB.apk必須用咱們自己的版本以外,其他可以用同分辨率機(jī)型的APP直接替換)
            Bin文件夾(本文件夾一般存放的是開機(jī)運(yùn)行的腳本和一些系統(tǒng)必備代碼,一般移植出了問題不能開機(jī)就是這里的問題,一般我們用702的或者720的ROM 里的,注意除了NETD需要用701的外,其他也可以直接用702或者720ROM的,不過一般系統(tǒng)升級(jí)不會(huì)修改這里,在移植的時(shí)候,要?jiǎng)h除2nd- init以及所有.sh腳本文件,這些對(duì)701是沒有效果的,如果電池顯示?,那么可以通過替換battd文件來修複)
            Etc文件夾(本文件夾里存放著這種配置文件,包括WIFI,藍(lán)牙和基帶{\etc\motorola\bp_nvm_default}配置文件,A- GPS的文件和Hosts文件也在這里,media_profiles.xml可以控制錄像質(zhì)量,cameraCalFileDef5M.bin與 cameraCalFileDef8M.bin是照相的數(shù)據(jù)庫文件,都可以修改,子文件夾init.d文件夾下可以寫入自己的開機(jī)腳本,來實(shí)現(xiàn)一些程序或 者腳本開機(jī)啓動(dòng),如果想要執(zhí)行某模塊,可以添加一個(gè)文件,不要有后綴名,格式爲(wèi)00aaa  00是執(zhí)行序號(hào),系統(tǒng)開機(jī)時(shí)會(huì)按順序執(zhí)行,aaa是爲(wèi)了區(qū)別 每個(gè)腳本的名稱,可以隨便寫)
            Font文件夾(字體文件夾,沒什么好解釋的,你可以替換爲(wèi)你喜歡的字體)
            Framework文件夾(系統(tǒng)框架結(jié)構(gòu)文件目錄,這個(gè)目錄下是系統(tǒng)服務(wù)和系統(tǒng)界面的所在地,一般不可以單獨(dú)替換,要移植的話必須全部替換,不然會(huì)卡 M,framework-res.apk文件就是系統(tǒng)語言,界面的所在文件,修改他就可以直接修改系統(tǒng)界面,framework-res.apk必須與 app文件夾中systemui.apk配套,不然開機(jī)會(huì)出現(xiàn)狀態(tài)欄FC,不同版本不可以亂用,比如CM7.1.0.5不能用CM7.1.0.4的文件)
            Lib文件夾(本文件夾是系統(tǒng)所需要用到的驅(qū)動(dòng),庫文件的所在,如果某程序FC或者無法正常運(yùn)轉(zhuǎn),可能是這里的問題,我把我知道的一些文件的用途說一下:
            ***Lib/dsp文件夾 DSP驅(qū)動(dòng)所在,一般不需要改
            ***lib/egl 顯示芯片驅(qū)動(dòng),一般不需要改
            ***libaudio.so 話筒及音頻驅(qū)動(dòng) 必須用701的
            ***libaudioflinger.so 音頻附屬驅(qū)動(dòng) 必須用701的
            ***libbridge.so 相機(jī)方面
            ***libbattd.so  電池驅(qū)動(dòng)
            ***libcamera.so 相機(jī)驅(qū)動(dòng) 必須用701的
            ***libcameraservice.so 相機(jī)服務(wù)驅(qū)動(dòng)
            ***libfmradio.so FM驅(qū)動(dòng)
            ***libHPImgApi.so 圖片接口驅(qū)動(dòng) 必須用701的
            ***libLCML.so 未知驅(qū)動(dòng)  必須用701的
            ***liboemcamera.so 相機(jī)驅(qū)動(dòng)  必須用701的
            ***libOMX.TI.JPEG.Encoder.so 照片編碼器  必須用701的 否則照片黑
            ***libOMX.TI.AAC.decode.so  此類型的都是編碼器和解碼器驅(qū)動(dòng)(多媒體)
            除上述紅色文件必須用701外,其他文件可以直接用702或者720的。
            Media文件夾(鈴聲及開機(jī)動(dòng)畫)
            TTS文件夾(文字轉(zhuǎn)語音文件夾)
            Usr文件夾(鍵盤文件與各類數(shù)據(jù)庫)
            Xbin文件夾(系統(tǒng)工具文件夾)
            Build.prop文件(系統(tǒng)參數(shù)文件,修改這里可以調(diào)節(jié)系統(tǒng)部分參數(shù)與性能)
            如:默認(rèn)虛擬機(jī)大小,鈴聲延遲,系統(tǒng)版本等
            posted @ 2013-02-17 14:48 小果子 閱讀(440) | 評(píng)論 (0)編輯 收藏

            在項(xiàng)目中,我們經(jīng)常要實(shí)現(xiàn)以下編輯器的所見所得效果,當(dāng)然也要支持回車,在此做下記錄,對(duì)正則表達(dá)式還不是很熟練。

            將HTML換行標(biāo)簽替換為文本域換行符:
            textereaContext = divHTML.replace(/(<br>)/g, “\r\n”);

            將文本域換行符替換為HTML換行標(biāo)簽:
            divHTML =  textereaContext .replace(/\n|\r|(\r\n)|(\u0085)|(\u2028)|(\u2029)/g, “<br>”);
            posted @ 2013-02-04 15:41 小果子 閱讀(4176) | 評(píng)論 (2)編輯 收藏

            在PHP中查找中文字符,有兩種方案。

            1、中文字符是gbk(gb2312)

            有兩種解決方法

            第一種:

            將PHP保存為ASCII編碼,然后使用strpos查找,如:

            strpos($curl_res, ‘哈哈’)

            第二種:

            將PHP保存為UTF-8無BOM編碼,然后轉(zhuǎn)換字符串編碼為UTF-8,再查找,如:

            $curl_res = mb_convert_encoding($curl_res, ‘utf-8′, ‘gbk’);

            mb_strpos($curl_res, ‘哈哈’);

            2、中文字符是UTF-8

            有兩種解決方法

            第一種:

            將PHP保存為UTF-8無BOM編碼,然后使用strpos查找,如:

            strpos($curl_res, ‘哈哈’)

            第二種:

            將PHP保存為ASCII編碼,然后轉(zhuǎn)換字符串編碼為gbk,再查找,如:

            $curl_res = mb_convert_encoding($curl_res, ‘gbk’, ‘utf-8′);

            mb_strpos($curl_res, ‘哈哈’);

            應(yīng)該可以看出一些規(guī)律,就是:函數(shù)中的中文字符串參數(shù)的編碼和PHP文件保存格式的編碼一致,在使用函數(shù)時(shí)要考慮到!


                 我生成的那個(gè)html文件被EmEditor認(rèn)為UTF-8 with Signature。而好用的那個(gè)html文件被EmEditor認(rèn)為UTF-8 without Signature.
                對(duì)于這兩種UTF-8格式的轉(zhuǎn)換,我查看了網(wǎng)上信息,點(diǎn)擊記事本,EmEditor等文本編輯器的另存為,當(dāng)選擇了UTF-8的編碼格式時(shí),Add a Unicode Signature(BOM)這個(gè)選項(xiàng)被激活,只要選擇上,我的文件就可以存為UTF-8 with Signature的格式。可是,問題就在于,我用java怎么讓我的文件直接生成為 UTF-8 with Signature的格式。
                開始上google搜索UTF-8 with Signature,BOM,Add a Unicode Signature等關(guān)鍵字。
            http://www.unicode.org/unicode/faq/utf_bom.html#BOM
            我大致了解了他們兩個(gè)的區(qū)別。
            Q: What is a BOM?

            A: A byte order mark (BOM) consists of the character code U+FEFF at the beginning of a data stream, where it can be used as a signature defining the byte order and encoding form, primarily of unmarked plaintext files. Under some higher level protocols, use of a BOM may be mandatory (or prohibited) in the Unicode data stream defined in that protocol.
            http://mindprod.com/jgloss/bom.html
            BOM
            Byte Order Marks are special characters at the beginning of a Unicode file to indicate whether it is big or little endian, in other words does the high or low order byte come first. These codes also tell whether the encoding is 8, 16 or 32 bit. You can recognise Unicode files by their starting byte order marks, and by the way Unicode-16 files are half zeroes and Unicode-32 files are three-quarters zeros. Unicode Endian Markers
            Byte-order mark Description
            EF BB BF UTF-8
            FF FE UTF-16 aka UCS-2, little endian
            FE FF UTF-16 aka UCS-2, big endian
            00 00 FF FE UTF-32 aka UCS-4, little endian.
            00 00 FE FF UTF-32 aka UCS-4, big-endian.
            There are also variants of these encodings that have an implied endian marker.
            Unfortunately, often applications, even Javac.exe, choke on these byte order marks. Java Readers don't automatically filter them out. There is not much you can do but manually remove them.


            http://cache.baidu.com/c?word=java%2Cbom&url=http%3A//tgdem530%2Eblogchina%2Ecom/&b=0&a=1&user=baidu
            c、UTF的字節(jié)序和BOM
            UTF-8以字節(jié)為編碼單元,沒有字節(jié)序的問題。UTF-16以兩個(gè)字節(jié)為編碼單元,在解釋一個(gè)UTF-16文本前,首先要弄清楚每個(gè)編碼單元的字節(jié)序。 例如收到一個(gè)“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節(jié)流“594E”,那么這是 “奎”還是“乙”?

            Unicode規(guī)范中推薦的標(biāo)記字節(jié)順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個(gè)有點(diǎn)小聰明的想法:

            在UCS編碼中有一個(gè)叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。UCS規(guī)范建議我們?cè)趥鬏斪止?jié)流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。

            這樣如果接收者收到FEFF,就表明這個(gè)字節(jié)流是Big-Endian的;如果收到FFFE,就表明這個(gè)字節(jié)流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。

            UTF-8不需要BOM來表明字節(jié)順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗(yàn)證一下)。所以如果接收者收到以EF BB BF開頭的字節(jié)流,就知道這是UTF-8編碼了。

            Windows就是使用BOM來標(biāo)記文本文件的編碼方式的。


            原來BOM是在文件的開始加了幾個(gè)字節(jié)作為標(biāo)記。有了這個(gè)標(biāo)記,一些協(xié)議和系統(tǒng)才能識(shí)別。好,看看怎么加上這寫字節(jié)。
            終于在這里找到了
            http://mindprod.com/jgloss/encoding.html 
            UTF-8 
            8-bit encoded Unicode. neé UTF8. Optional marker on front of file: EF BB BF for reading. Unfortunately, OutputStreamWriter does not automatically insert the marker on writing. Notepad can't read the file without this marker. Now the question is, how do you get that marker in there? You can't just emit the bytes EF BB BF since they will be encoded and changed. However, the solution is quite simple. prw.write( '\ufeff' ); at the head of the file. This will be encoded as EF BB BF.
            DataOutputStreams have a binary length count in front of each string. Endianness does not apply to 8-bit encodings. Java DataOutputStream and ObjectOutputStream uses a slight variant of kosher UTF-8. To aid with compatibility with C in JNI, the null byte '\u0000' is encoded in 2-byte format rather than 1-byte, so that the encoded strings never have embedded nulls. Only the 1-byte, 2-byte, and 3-byte formats are used. Supplementary characters, (above 0xffff), are represented in the form of surrogate pairs (a pair of encoded 16 bit characters in a special range), rather than directly encoding the character.
             
            prw.write( '\ufeff' );就是這個(gè)。
            于是我的代碼變?yōu)椋?br /> public void htmlWrite(String charsetName) {
                    try {
                        out = new BufferedWriter(new OutputStreamWriter(
                                    new FileOutputStream(outFileName), "UTF-8"));
                        out.write('\ufeff');
                        out.write(res);
                        out.flush();

                        if (out != null) {
                            out.close();
                        }
                    } catch (Exception e) {
                        try {
                            if (out != null) {
                                out.close();
                            }
                        } catch (IOException e1) {
                            System.out.print("write errors!" + e);
                        }

                        System.out.print("write errors!" + e);
                    }
                }
            問題解決。

            posted @ 2013-02-04 15:38 小果子 閱讀(2935) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共58頁: First 2 3 4 5 6 7 8 9 10 Last 
            99久久中文字幕| 亚洲AV日韩AV永久无码久久 | 久久精品中文字幕无码绿巨人| 亚洲国产二区三区久久| 狠狠色丁香久久婷婷综| 欧美一区二区三区久久综合| 18禁黄久久久AAA片| 久久久精品久久久久影院| 香蕉久久夜色精品国产2020| 亚洲欧美一区二区三区久久| 久久精品日日躁夜夜躁欧美| 综合久久国产九一剧情麻豆| 日韩人妻无码精品久久免费一| 18岁日韩内射颜射午夜久久成人 | 久久综合给久久狠狠97色 | 久久久女人与动物群交毛片| 久久国产精品无码一区二区三区 | 久久国产热精品波多野结衣AV| 亚洲AV无码久久寂寞少妇| 麻豆亚洲AV永久无码精品久久 | 久久天天躁狠狠躁夜夜avapp| 色狠狠久久AV五月综合| 国产精品一久久香蕉产线看| 久久国产视屏| 亚洲精品乱码久久久久久蜜桃不卡 | 一本大道加勒比久久综合| 欧美成a人片免费看久久| 久久精品国产久精国产一老狼| 久久精品国产亚洲AV久| 色综合久久88色综合天天| 久久久久综合国产欧美一区二区 | 久久精品亚洲AV久久久无码| 久久久久亚洲av无码专区 | 久久婷婷国产麻豆91天堂| 中文成人久久久久影院免费观看| 婷婷五月深深久久精品| 18岁日韩内射颜射午夜久久成人| 精产国品久久一二三产区区别 | 亚洲国产精品无码久久SM | 亚洲成av人片不卡无码久久| 久久精品毛片免费观看|