android 零星調試筆記

adb使用:

連接不上手機

C:\Users\Administrator\.android\adb_usb.ini   增加一行內容:  0x1782

安裝第三方應用
   $ adb install apk文件名
2.安裝系統應用
$ adb remount
$ adb push apk文件名 /system/app
// apk文件名形如testme.apk

卸載應用程序

1.$ adb uninstall 包名 例如:adb uninstall lee.study

2. 在終端上找到:Home->設置->應用程序->管理應用程序->選擇某應用程序->卸載

設置屬性值

使用adb shell:   改成中文 setprop persist.sys.language zh;setprop persist.sys.country cn;stop;sleep 5;start

註解:  setprop persist.sys.language zh(MCC: mobile country code);setprop persist.sys.country cn(MNC: mobile network code);

 stop;sleep 5;start  延時5秒重啓機器

查看系統定義所有權限列表:

 adb shell pm list permissions

撥打電話: am start -a android.intent.action.CALL -d tel:10086  這裏-a表示動作,-d表述傳入的數據,還有-t表示傳入的類型

打開網頁: am start -a android.intent.action.VIEW  -d  http://www.baidu.com (這裏-d表示傳入的data)

打開音樂播放器: am start -a android.intent.action.MUSIC_PLAYER 或者 am start -n com.android.music/om.android.music.MusicBrowserActivity

啓動服務: am startservice <服務名稱> 

例: am startservice -n com.android.music/com.android.music.MediaPlaybackService (這裏-n表示組件)

               am startservice -a com.smz.myservice (這裏-a表示動作,就是你在Androidmanifest裏定義的) 

發送廣播:  am broadcast -a <廣播動作>                 am broadcast -a android.intent.action.BOOT_COMPLETED

恢復出廠設置(手機必須擁有root權限): adb shell am broadcast -a android.intent.action.MASTER_CLEAR 

模擬按鍵

adb shell input keyevent 3     :模擬home鍵  3 = KeyEvent.KEYCODE_HOME

利用adb命令查看apk文件包名

在控制檯輸入命令$adb shell pm
可以看到adb shell pm的相關用法

要看一個apk文件的相關信息最簡單實用的方法是:
aapt dump badging [app.apk]
如果只是想查看手機上應用的packageName,則輸入命令:
adb shell pm list packages
如果想知道應用對應的apk文件在手機上的安裝位置則可以在上面的命令後加-f參數
adb shell pm list packages -f
查看所有安裝的apk包名:
adb shell 'pm list packages -f' | sed -e 's/.*=//' | sort

adb server is out of date.  killing...   解決措施:

描述:adb server is out of date.  killing... 
ADB server didn't ACK
* failed to start daemon *
error: unknown host service

究其源就是adb server沒啓動 解決過程分析整理如下:
E:\>adb nodaemon server  
cannot bind 'tcp:5037'  
原來adb server 端口綁定失敗
繼續查看到底是哪個端口給佔用了
E:\>netstat -ano | findstr "5037"  
  TCP    127.0.0.1:4112         127.0.0.1:5037         CLOSE_WAIT      2960
  TCP    127.0.0.1:5037         0.0.0.0:0              LISTENING       4596
  TCP    127.0.0.1:5037         127.0.0.1:3006         ESTABLISHED     4596
  TCP    127.0.0.1:6149         127.0.0.1:5037         CLOSE_WAIT      2960
打開任務管理器kill掉4596 這個進程。ok

解決讀取權限問題

例如 使用adb push init.rc /       命令時報錯:Unable to chmod init.rc: Read-only file system

在shell命令行中輸入
adb root
切換到root用戶
然後執行如下命令:(注意,/表示的是根目錄,因此這個不僅僅是對sdcard,其他文件也可以讀寫。rw表示讀寫權限,mount重掛載文件系統)

  1. # 修改system分區爲可讀寫  
  2. mount -o remount,rw /system


代碼中安裝apk

Runtime.getRuntime().exec("pm install xxx.apk"); 
需要在manifest.xml文件中,加上INSTALL_PACKAGES的權限,可以用 Package install的receiver來處理安裝成功後的操作
或者:
  1.      /** 
  2.      * 安裝apk 
  3.      * @param url 
  4.      */  
  5.     private void installApk(){  
  6.         File apkfile = new File(saveFileName);  
  7.         if (!apkfile.exists()) {  
  8.             return;  
  9.         }      
  10.         Intent i = new Intent(Intent.ACTION_VIEW);  
  11.         i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");   
  12.         mContext.startActivity(i);  
  13. }

Andoird判斷某個APK是否已經安裝

   private boolean isAppInstalled(String uri){
    	
    	PackageManager pm = getPackageManager();
    	boolean installed =false;
    	try{
    		pm.getPackageInfo(uri,PackageManager.GET_ACTIVITIES);
    		installed =true;
    	}catch(PackageManager.NameNotFoundException e){
    		installed =false;
    	}
    	
    	return installed;
    } 

   //Just call the method by passing the package name of the application you need to check.
    if(isAppInstalled("com.yourpackage.package")){
     //app installed
    }else{
      //app not installed
    }
 

Logcat命令選項列表  選項  描述

[adb] logcat [<option>] ... [<filter-spec>] ...

options:

-b <buffer> 加載一個指定的LOG Buffer供查看,比如events 或radio。默認值是main 。具體參考查看指定的Log Buffers.
-c 清除整個 log並退出。
-d 輸出LOG到屏幕上並退出。
-f <filename> 寫LOG信息到 <filename>。默認是stdout.
-g 打印指定LOG Buffer的大小並退出。
-n <count> 設置日誌的最大數目<count>,默認值是4,需要和選項-r一起使用。
-r <kbytes> Rotates每輸出<kbytes> 寫LOG文件,默認值爲16,需要和選項-f一起使用。
-s 設置默認的過濾級別爲silent。
-v <format> Sets 設置LOG的輸出格式,默認的是brief 格式,要知道更多的支持的格式,參看控制LOG輸出格式.

舉例:

adb logcat ActivityManager:I MyApp:D *:S
只顯示那些標籤爲“ActivityManager”且優先級爲“Info”以上的和標籤爲“ MyApp”且優先級爲“ Debug”以上的信息,其他標籤的信息都不顯示
表達式最後的元素 *:S,,是設置所有標籤的優先級爲“silent”,這樣保證只有“ActivityManager”和“MyApp”的LOG纔會顯示

adb logcat -b <system,radio,events,main(default)>

main.log :     adb logcat -v time >main.log

radio.log : adb logcat -b radio -v time>radio.log

net and routerinfo :   adb shell ifconfig eth0>ifconfig.txt             adb shell busybox route -n >route_info.txt

property value: adb shell getprop> no_services_sysprop.txt

iplog: adb shell tcpdump -i any -w /data/iplog.cap&adb pull data/iplog.cap


       轉: http://www.2cto.com/kf/201401/271875.html

log文件分爲實時打印的,還有狀態信息的兩種
實時打印的主要有:logcat main,logcat radio,logcat events,tcpdump, QXDM Log
狀態信息的有:adb shell dmesg,adb shell dumpstate,adb shell dumpsys,adb bugreport
實時log:
  adb logcat -b events -v time 打印系統事件的日誌,比如觸屏事件
  tcpdump 是很有用的,對於TCP/IP協議相關的都可以使用這個來抓,
  adb shell tcpdump -s 10000 -w /sdcard/capture.pcap,
  比如抓mms下載的時候的UA profile,browser上網的時候,使用proxy的APN下載,streaming的相關內容包括UA profile等。
狀態log:
其實一個就夠了,那就是bugreport(命令adb bugreport>bugreport.log)。
裏面包含有dmesg,dumpstate和dumpsys;
dmesg(命令adb shell dmesg > ldmesg_kernel.log)是kernel的log,凡是跟kernel相關的,比如driver出了問題(相機,藍牙,usb,啓動,等等)
dumpstate是系統狀態信息,裏面比較全,包括手機當前的內存信息、cpu信息、logcat緩存,kernel緩存等等;
dumpsys這個是關於系統所有進程Process的內容都在這個裏面,adb shell dumpsys 這個命令還有更詳盡的用法,
比如adb shell dumpsys meminfo system是查看system這個process的內存信息。
dumpsys [options]
meminfo 顯示內存信息
cpuinfo 顯示CPU信息
account 顯示accounts信息
activity 顯示所有的activities的信息
window 顯示鍵盤,窗口和它們的關係
wifi 顯示wifi信息
  通過adb logcat/bugreport可以實時的查看系統的log,以及系統的狀態信息;
  如何將Log存儲下來,保存當時系統運行的情況呢?
  可以通過一些腳本或者執行可執行程序來保存log信息,以便分析問題

命令參數:

名字 功能
account 顯示accounts信息
activity 顯示所有的activities的信息
cpuinfo 顯示CPU信息
window 顯示鍵盤,窗口和它們的關係
wifi 顯示wifi信息
batteryinfo $package_name 電量信息及CPU 使用時長
package packagename 獲取安裝包信息
usagestats 每個界面啓動的時間
statusbar 顯示狀態欄相關的信息
meminfo
內存信息(meminfo $package_name or $pid 
使用程序的包名或者進程id顯示內存信息)
diskstats 磁盤相關信息
battery 電池信息
alarm 顯示Alarm信息

資源layout加載出錯:

鬱悶好久的問題:   Android Error:main cannot be resolved or is not a field 
R.layout.main總是在layout上有錯誤提示波浪線。
解決方法:
(1) 刪除"import android.R;".
(2) 勾選上Eclipse中的"Project->Build Automatically";
原因是:

添加文件,比如xml文件或者資源文件時,系統自動添加了import android.R;android.R是系統提供的資源,R是應用程序的資源。刪除"import android.R"之後工程就是從/res文件夾下自動生成的資源文件裏去解析了,否則它會從Android的資源類裏去找。

Intent.ACTION_BOOT_COMPLETED  開機完成

模擬器啓動不了

錯誤如 : Starting emulator for AVD '4.2.2' PANIC: Could not open: 4.2.2

解決:

1、把模擬器avd所在位置的.android文件夾直接複製C:\Documents and Settings\Administrator\
(模擬器avd所在位置 -- 選擇 VIRTUAL...  選擇安卓機,DETAILS...path:就是這個路徑。把.android文件夾COPY到C:\Documents and Settings\Administrator\)

2、我的電腦-屬性-高級 環境變量。
新建系統環境變量,   
名字:ANDROID_SDK_HOME
變量值:X:\
X爲android文件夾所在
(文件夾放在根目錄)
然後新建一個,就能開機了

android彩蛋代碼

DeviceInfoSettings.java ->onPreferenceTreeClick->

Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName());

startActivity(intent);

packages\apps\Crome\src\com\crome\test\PlatLogoActivity.java

取得屏幕大小:

1、在非activity類中
 WindowManager windowManager = (WindowManager)(mContext.getSystemService(Context.WINDOW_SERVICE));
 int screenWidth = windowManager.getDefaultDisplay().getWidth(); 
 int screenHeight = windowManager.getDefaultDisplay().getHeight();  
2、在activity類中
int screenWidth  = getWindowManager().getDefaultDisplay().getWidth();       // 屏幕寬(像素,如:480px)  
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();      // 屏幕高(像素,如:800px)
  
eclipse出現 Some characters cannot be mapped using "GBK" character encoding 錯誤代碼的解決辦法 
今天在使用eclipse調試騰訊空間API時,在我更改APP key後,點擊保存按鈕時,出現了Some characters cannot be mapped using "GBK" character encoding 這樣的錯誤代碼,根據提示看,應該是說一些文字無法用GBK編碼映射。應該是有些地方的文字編碼設置成了GBK造成的。

馬上google了一番,終於找到了解決的辦法,依次點擊Window->Profermance->General->Content Type->Text看目錄下面的每個文件,包括子目錄裏面 Default encoding的值是否爲utf-8,如果爲別的值或爲空,則全部改爲utf-8,每一項改完,別忘了點一下update.全部改完後推出菜單,再點一下保存,終於成功了。

獲得 LayoutInflater 實例的三種方式

1.LayoutInflater inflater = getLayoutInflater();  //調用Activity的getLayoutInflater()
2.LayoutInflater localinflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
3. LayoutInflater inflater = LayoutInflater.from(context);  
示意代碼: 
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);    
View view = inflater.inflate(R.layout.custom, (ViewGroup)findViewById(R.id.test)); 
對於上面代碼,指定了第二個參數 ViewGroup root,當然你也可以設置爲 null 值。  

ContentResolver.query(),以及 Activity.managedQuery異同:

參數、返回值相同:都返回 Cursor 對象
參數:
URI:  Content Provider 需要返回的資源索引
Projection: 用於標識有哪些columns需要包含在返回數據中。
Selection: 作爲查詢符合條件的過濾參數,類似於SQL語句中Where之後的條件判斷。
SelectionArgs: 同上。
SortOrder: 用於對返回信息進行排序。
不同:
mContext.getContentResolver().query
 ContentResolver.query(),以及 Activity.managedQuery()所以,我們看到一個是ContentResolver提供的查詢方法,位於android.content.ContextWrapper.getContentResolver(),另一個則爲Activity。   Activity.managedQuery()  方法導致活動管理 Cursor 的生命週期

硬件滅屏功能:寫文件

"/sys/class/leds/lcd-backlight/brightness"
./devices/platform/lcd-backlight/leds/lcd-backlight/brightness
0 :滅     255 : 亮

解鎖功能

KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);    
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock(""); 
keyguardLock.disableKeyguard();
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE); 

  點亮屏幕

PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE); 
 WakeLock mWakelock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.SCREEN_DIM_WAKE_LOCK,"SimpleTimer"); 
mWakeLock.acquire();//點亮 
mWakeLock.release();//關閉  

activity全屏顯示:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);

//注意;要在setContentView(R.layout.layout)語句之前調用才行

在最新SDK中隨時可以改變改屬性,做到隨時隱藏、顯示狀態欄

    private void showStatusBar(boolean bShow) {
        android.view.Window window = mActivity.getWindow();
        android.view.WindowManager.LayoutParams lp = window.getAttributes();
        int flag;
        if(window != null && lp != null){
	        if (bShow) {
	            flag = lp.flags & ~android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
	        } else {
	            flag = lp.flags | android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
	        }
	        lp.flags = flag;
	        window.setAttributes(lp);
        }
    }


 取得build.prop中的值:
property_get()[c/c++]  、   SystemProperties_get*()[Java域]讀取這些屬性值  getBoolean、getInt、getLong、get
android 按鍵定義:
 kernal\include\linux\input.h 

設置默認動態牆紙:

在frameworks/base/core/res/res/values目錄找到Config.xml文件
<string name="default_wallpaper_component">@null</string>
將其修改爲對應的live wallpaper的啓動component即可,如要把默認壁紙設置爲2.1自帶的galaxy,這樣寫即可:<string name="default_wallpaper_component">com.android.wallpaper/com.android.wallpaper.galaxy.GalaxyWallpaper</string>
這裏的com.android.wallpaper/com.android.wallpaper.galaxy.GalaxyWallpaper 是動態壁紙的service的名字。

eclipse出現 Some characters cannot be mapped using "GBK" character encoding 錯誤代碼的解決辦法 
今天在使用eclipse調試騰訊空間API時,在我更改APP key後,點擊保存按鈕時,出現了Some characters cannot be mapped using "GBK" character encoding 這樣的錯誤代碼,根據提示看,應該是說一些文字無法用GBK編碼映射。應該是有些地方的文字編碼設置成了GBK造成的。
馬上google了一番,終於找到了解決的辦法,依次點擊Window->Profermance->General->Content Type->Text看目錄下面的每個文件,包括子目錄裏面 Default encoding的值是否爲utf-8,如果爲別的值或爲空,則全部改爲utf-8,每一項改完,別忘了點一下update.全部改完後推出菜單,再點一下保存,終於成功了。 

在Android源碼下如何對APK手動簽名呢?需要如下幾個步驟:

    1、編譯signapk JAR包:
      在Android源碼目錄下執行make signapk命令,即可在out/host/linux-x86/framework/目錄下生成signapk.jar文件。
    2、對已編譯好的普通APK進行簽名:
      java -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 xinu.apk xinu_new.apk

      以上都是在Android源碼目錄下執行,對xinu.apk進行簽名,簽名後名爲xinu_new.apk,其中pem和pk8是簽名時要用到的key文件,使用Android源碼下的key可在編譯出來系統上運行時獲取System權限等。

-----------------------------------------------------

需要先打一個未簽名的APK包,然後用系統簽名對其進行簽名。使用platform密鑰對apk進行簽名 
1.1.進入<Android_Source_Path>/build/target/product/security,找到【platform.pk8】和【platform.x509.pem】系統密鑰。 
1.2.進入<Android_Source_Path>/build/tools/signapk找到SignApk.java,運行javac編譯成SignApk.class 
1.3.執行命令java com.android.signapk.SignApk platform.x509.pem platform.pk8 input.apk output.apk 
至此,完成。 
在運行1.3的命令前,請在你當前的工作目錄下新建如下結構的文件夾:com.android.signapk,然後將第二步編譯生成的SignApk放入該目錄下。或者也可以將SignApk.java的package聲明刪除後再運行javac編譯。 
命令java com.android.signapk.SignApk platform.x509.pem platform.pk8 input.apk output.apk 
不單可以對apk文件進行重簽名,也可以對所有的zip文件進行重簽名,包括ROM文件。 
以上這方法在AndroidManifest中聲明android.permission.INSTALL_PACKAGES,有一點比較奇怪的是執行“ int result = checkCallingOrSelfPermission(Intent.ACTION_PACKAGE_INSTALL) ”,result的值爲android.content.pm.PackageManager.PERMISSION_DENIED而不是PERMISSION_GRANTED。 

取得某個文件夾下特定格式文件列表

private static final String MUSIC_PATH = new String("/sdcard/");
File file =  new File(MUSIC_PATH);
         File fileArray[] = file.listFiles(new FilenameFilter() {
             @Override
            public boolean accept(File dir, String filename) {
                // TODO Auto-generated method stub
                return (filename.endsWith(".mp3"));
            }
        });

      List<String> mMusicList = new ArrayList<String>();
        for(File item: fileArray){
            mMusicList.add(item.getName());
        }

屏常亮代碼:

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//屏常亮

自定義組合控件加載layout:

LayoutInflater.from(context).inflate(R.layout.cam_control_bar, this, true);

自定義控件不調用onDraw函數:

android默認不調用onDraw函數,在自定義view裏如需手動繪製,需要在構造函數調用this.setWillNotDraw(false);來告訴ui線程此自定義layout有需要繪製的內容 


實現序列圖切換 就是一張圖有幾張小圖組成 按時間切換 (java實現)

int currImage=0;
Handler handler=new Handler(){
		@Override
		public void handleMessage(Message msg) {
			if (msg.what==0x123) {
			currImage++;
			invalidate();
			}
		}
	};
dukeImage=new Bitmap[]{	
				BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10001),
				BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10002),
				BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10003),
				BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10004),
				BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10005),
		};
new Timer().schedule(new TimerTask(){
			@Override
			public void run() {
				handler.sendEmptyMessage(0x123);
			}
		}, 0,200);
	}
public void onDraw(Canvas canvas) {	
canvas.drawBitmap(dukeImage[currImage], 
	LEFTMART,
		screenHeight-ImageHeight-BOTTOM, 
			paint);		
		}

轉自:http://www.cnblogs.com/bastard/archive/2012/06/29/2570405.html


/**

* 簡單實現了一個方法來判斷動畫的狀態。CustomAnimDrawable是自己寫的繼承於AnimationDrawable的

* 一個類,用來根據播放第幾幀來判斷,避免了根據時間來判斷時,理論時間和實際時間不一致造成的影響。

* 用到了Java的反射機制。

*/
public class CustomAnimDrawable extends AnimationDrawable {
   private final String TAG = "xmp";
   private AnimationDrawable mOriAnim;
   private AnimationDrawable mSelf;
   private Handler mHandler;
   private boolean mStarted;
   private AnimEndListenerRunnable mEndRunnable;
   private AnimationDrawableListener mListener;

   public CustomAnimDrawable(AnimationDrawable anim) {
       mOriAnim = anim;
       initialize();
   }
   private void initialize() {
       mSelf = this;
       mStarted = false;
       mHandler = new Handler();
       mEndRunnable = new AnimEndListenerRunnable();
       for (int i = 0; i < mOriAnim.getNumberOfFrames(); i++) {
           mSelf.addFrame(mOriAnim.getFrame(i), mOriAnim.getDuration(i));
       }
   }

   @Override
   public void start() {
       mOriAnim.start();
       mStarted = true;
       mHandler.post(mEndRunnable);
       if (mListener != null) {
           mListener.onAnimationStart(mSelf);
       }
       Log.v(TAG, "------CustomAnimDrawable------>start");
   }
   
   /**
    * 循環檢測 動畫的狀態
    */
   class AnimEndListenerRunnable implements Runnable {
       @Override
       public void run() {
           // 動畫已開始
           if (!mStarted) {
               return;
           }
           // 未停止繼續監聽
           if (!isEnd()) {
// 這裏的延遲時間是跟你的每一幀動畫時間有關,基本保持一致就可以,最後一幀也會完整播放
// 上面動畫時間爲每一幀1000ms,所以這裏設爲了1000ms
               mHandler.postDelayed(mEndRunnable,1000);
               return;
           }
           Log.v(TAG, "----------->over");
           // 動畫已結束
           if (mListener != null) {
               mStarted = false;
               mListener.onAnimationEnd(mSelf);
           }
       }
   }
   /**
    * 判斷動畫是否結束 採用反射機制
    * @return
    */
   private boolean isEnd(){
       Class<AnimationDrawable> animClass = AnimationDrawable.class;
       try{  
           //利用Java反射方法判斷是否結束
           //獲得私有方法  例如
           //Method method = animClass.getDeclaredMethod("nextFrame",boolean.class);
           
           //訪問其私有變量
        Field field = animClass.getDeclaredField("mCurFrame");
           field.setAccessible(true);
           
           int currFrameNum = field.getInt(mOriAnim);
           int totalFrameNum = mOriAnim.getNumberOfFrames();
           if((currFrameNum == totalFrameNum - 1)||
              (currFrameNum == -1)){
               return true;
           }
       }
       catch (Exception e) {
           Log.v(TAG,"-------->Exception");
       }       
       return false;
   }
   public void setAnimationListener(AnimationDrawableListener listener) {
       mListener = listener;
   }   
}
public interface AnimationDrawableListener {
/**
* Notifies the start of the animation
* @param animation
*/
public void onAnimationStart(AnimationDrawable animation);
/**
* Notifies the end of the animation
* @param animation
*/
public void onAnimationEnd(AnimationDrawable animation);
}

TextView相關:

android:imeOptions="actionSearch"   調整輸入法enter鍵的顯示
android:inputType="textNoSuggestions"  限制字符(輸入格式)    InputFilter

android:focusableInTouchMode="true"  獲取焦點   <requestFocus />
mSearchEdit.setFocusable(true);
mSearchEdit.setFocusableInTouchMode(true);
mSearchEdit.requestFocus();

詳見: http://hi.baidu.com/ljlkings/item/7c8d2b0e68efe4076c9048d5

如何將TextView中的中文設置成粗體?

在xml文件中使用android:textStyle="bold" 可以將英文設置成粗體,但是不能將中文設置成粗體,將中文設置成粗體的方法是:
TextView tv = (TextView)findViewById(R.id.TextView01);
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true);

輸入法相關:

默認輸入法:1、frameworks\base\packages\SettingsProvider\res\values\defaults.xml
    <string name="default_enabled_input_methods" translatable="false">com.jb.gokeyboard/.GoKeyboard</string>      

      2、frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java 

函數private void loadSecureSettings(SQLiteDatabase db)() 中 增加語句 loadStringSetting(stmt, Settings.Secure.DEFAULT_INPUT_METHOD, com.android.internal.R.string.default_enabled_input_methods); 


4.2.2 pad中使用:


<activity android:windowSoftInputMode="stateHidden|adjustPan" . . . >   調整輸入法初始隱藏,並且不調整出口尺寸大小

詳見: http://www.cnblogs.com/snowberg/archive/2012/07/10/2618910.html  

 強制隱藏Android輸入法窗口

在IME類中我們通過 InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 實例化輸入法控制對象,通過hideSoftInputFromWindow來控制,其中第一個參數綁定的爲需要隱藏輸入法的EditText對象,比如imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

EditText editText=...

editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View arg0, boolean arg1) {
// TODO Auto-generated method stub
if(!arg1){ //失去焦點,關閉輸入界面
InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
}
});

SQL中 inner join、 left join 、right join、 outer join之間的區別

舉例說明
A表(a1,b1,c1)      B表(a2,b2)
a1   b1   c1       a2    b2
01   數學 95       01    張三
02   語文 90       02    李四
03   英語 80       04    王五
select A.*,B.* from A 
inner join B on(A.a1=B.a2)
結果是:
a1   b1   c1       a2    b2
01   數學 95       01    張三
02   語文 90       02    李四

select A.*,B.* from A 
left outer join B on(A.a1=B.a2)
結果是:
a1   b1   c1       a2    b2
01   數學 95       01    張三
02   語文 90       02    李四
03   英語 80       NULL  NULL

select A.*,B.* from A 
right outer join B on(A.a1=B.a2)
結果是:
a1   b1   c1       a2    b2
01   數學 95       01    張三
02   語文 90       02    李四
NULL NULL NULL     04    王五

select A.*,B.* from A 
full outer join B on(A.a1=B.a2)
結果是:
a1   b1   c1       a2    b2
01   數學 95       01    張三
02   語文 90       02    李四
03   英語 80       NULL  NULL
NULL NULL NULL     04    王五

如果讓包含button的item也能彈出菜單,回調click以及long click的監聽器:

設置button屬性: android:focusable="false"  另外還要設置 listview屬性:android:longClickable="true" 

PS: 如果包含的Button是ImageButton,那麼在xml中設置了android:focusable="false"屬性在當前版本是無效的,必須在代碼中,再次呼叫函數ImageButton.setFocusable(false)設置一次。 
或者: 
在父Item裏面加上android:descendantFocusability="blocksDescendants" 

背光亮度: /sys/class/leds/lcd-backlight/brightness

例如 echo 255 > /sys/class/leds/lcd-backlight/brightness

代碼修改亮度:

Settings.System.putInt(getContentResolver(), SCREEN_BRIGHTNESS, brightness);    //brightness 背光亮度 0~255

Settings.System.putInt(getContentResolver(),SCREEN_OFF_TIMEOUT, timeoutValues);//timeoutValues 滅屏時間 ms

FrameLayout

在FrameLayout佈局裏面android:layout_margin的各種屬性必須依賴於android:layout_gravity,也就是說,要想margin生效,必須設定view的layout_gravity屬性。

如何自定義title的高度、背景

Android程序默認的Activity標題欄只能顯示一段文字,而且不能改變它的佈局、顏色、標題欄的高度等。如果想要在標題欄加上個圖標、button、輸入框、進度條、修改標題欄顏色等,只能使用自定義的標題欄。自定義標題欄可以通過在onCreate函數中添加以下代碼來實現,需要注意的是代碼的順序必須按照下面的樣式,否則將無效。
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.mainactivity);    //Activity的佈局
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.titlebar);   //標題欄的佈局
雖然上面這樣可以在標題欄加入一些控件,但是仍然不能改變標題欄的高度、背景色,要想達到這個目的,只能使用theme(主題)。因此往project裏先添加一個style。改變背景色修改android:windowTitleBackgroundStyle的值,改變標題欄高度則修改android:windowTitleSize的值。下面是一個示例:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="fmTitleBackground">
        <item name="android:background">#778899</item>
    </style>
    <style name="fmTitlebar" parent="android:Theme">
        <item name="android:windowTitleSize">32dp</item>
        <item name="android:windowTitleBackgroundStyle">@style/fmTitleBackground</item>
    </style>
</resources>
接着再修改AndroidManifest.xml文件,找到要自定義標題欄的Activity,添加上android:theme值,比如:<activity android:name=".MainActivity" android:theme="@style/fmTitlebar">android:theme值就是上面那個style.xml文件裏定義的一個style的name值。
按照以上的步驟,修改標題欄佈局、高度、背景色的功能就實現了。

重新顯示一個已經啓動的Activity呢 不重新啓動它 只是讓它顯示到最前面  : A ->B->C->D    現在想要 從 D直接到B 

            Intent intent = new Intent(ReorderFour.this, ReorderTwo.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(intent);

Android2.1的源代碼的目錄結構,可以幫助我們研究Android的源代碼。

http://www.cnblogs.com/xilinch/archive/2013/04/07/3003670.html

判斷是否在鎖屏界面的函數

KeyguardManager: inKeyguardRestrictedInputMode();

例:        KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
                boolean keyguardexist = km.inKeyguardRestrictedInputMode();

設置activity背景透明:

1、在AndroidManifest.xml文件中相應的activity下增加屬性    android:theme="@android:style/Theme.Translucent" 
2、先在res/values下建colors.xml文件,寫入:

    <?xm version="1.0"encoding="UTF-8"?> 
  <resources> 
  <color name="transparent">#9000</color> 
  </resources>  
這個值設定了整個界面的透明度,爲了看得見效果,現在設爲透明度爲56%(9/16)左右。
再在res/values/下建styles.xml,設置程序的風格
<?xml version="1.0"encoding="utf-8"?> 
  <resources> 
  <style name="Transparent"> 
  <item name="android:windowBackground">@color/transparent</item> 
  <item name="android:windowIsTranslucent">true</item> 
  <item name="android:windowAnimationStyle">@+android:style/Animation.Translucent</item> 
  </style> 
  </resources> 
最後一步,把這個styles.xml用在相應的Activity上。即在AndroidManifest.xml中的任意<activity>標籤中添加 android:theme="@style/Transparent"
如果想設置所有的activity都使用這個風格,可以把這句標籤語句添加在<application>中。
可以把背景色#9000換成#0000,運行程序後,就全透明瞭,看得見背景下的所有東西可以卻都操作無效。

雙擊事件

class MyOnTouchListener implements View.OnTouchListener{
private long mLastTime = 0;
private long mCurTime = 0;

@Override
public boolean onTouch(View v, MotionEvent event) {
if(MotionEvent.ACTION_DOWN == event.getAction()){  
mLastTime = mCurTime; 
mCurTime = System.currentTimeMillis();
if (mCurTime - mLastTime < 1000) {
// 雙擊事件  關閉activity
FullBlackActivity.this.finish();
return true;
}
}
return false;
}
}

屏常亮(camera中的代碼)

   private void resetScreenOn() {
        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }
    private void keepScreenOnAwhile() {
        mHandler.removeMessages(CLEAR_SCREEN_DELAY);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
    }

      private static final int CLEAR_SCREEN_DELAY = 1;
    private static final int SCREEN_DELAY = 2 * 60 * 1000;
    private final Handler mHandler = new MainHandler();

  private class MainHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case CLEAR_SCREEN_DELAY: {
                    getWindow().clearFlags(
                            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                    break;
                }

            }
        }
    }

去除鎖屏、開機不鎖屏

KeyguardManager mKeyguardManager;
KeyguardManager.KeyguardLock mKeyguardLock;

mKeyguardManager=(KeyguardManager )getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock = mKeyguardManager.newKeyguardLock(this.getLocalClassName());

mKeyguardLock.disableKeyguard(); //去除鎖屏

mKeyguardLock.reenableKeyguard();//重新使能鎖屏

去除開機鎖屏的功能:frameworks/base/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
private boolean mExternallyEnabled = false;

或者也可以在函數中frameworks/base/services/java/com/android/server/wm/WindowManagerService.java private void initPolicy(Handler uiHandler)    增加代碼達到不鎖屏功能 

--- frameworks/base/services/java/com/android/server/wm/WindowManagerService.java	(revision 337)
+++ frameworks/base/services/java/com/android/server/wm/WindowManagerService.java	(working copy)
@@ -863,6 +863,11 @@
                 mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
                         * TYPE_LAYER_MULTIPLIER
                         + TYPE_LAYER_OFFSET;
+
+				 Log.v(TAG, "set mExternallyEnabled true! " );		//jimbo  set KeyguardViewMediator.mExternallyEnabled = false
+				 mPolicy.enableKeyguard(false);
             }
         }, 0);
     }

默認鎖屏時間: frameworks/base/packages/SettingsProvider/res/values/defaults.xml
<integer name="def_screen_off_timeout">-1</integer>     -1 代表不鎖屏

默認橫屏顯示

1、setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  // 進入時會先顯示一下豎屏然後再橫屏

2、在AndroidManifest.xml文件中相應的Activity增加屬性 android:screenOrientation="landscape"

取得所有需要顯示在主菜單中的程序

Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);  
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);  
List<ResolveInfo> allApps = getPackageManager().queryIntentActivities(mainIntent, 0);  

自動內存管理 ---  內存等級(剩多少內存開始關閉相應應用):

3rdparty\wifi\rda5990\special\android\system\core\rootdir\init.rc裏面的
# Define the memory thresholds at which the above process classes will
# be killed.  These numbers are in pages (4k).
    setprop ro.FOREGROUND_APP_MEM 2048     (限制後臺程序內存的)
    setprop ro.VISIBLE_APP_MEM 3072
    setprop ro.HOME_APP_MEM 3072
    setprop ro.PERCEPTIBLE_APP_MEM 4096
    setprop ro.HEAVY_WEIGHT_APP_MEM 4096
    setprop ro.SECONDARY_SERVER_MEM 15360
    setprop ro.BACKUP_APP_MEM 15360
    setprop ro.HIDDEN_APP_MEM 15360
    setprop ro.EMPTY_APP_MEM 14336
# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have combined some of
# the classes into the same memory level; the associated processes of higher
# classes will still be killed first.
    write /sys/module/lowmemorykiller/parameters/adj 0,1,2,4,7,15
write /proc/sys/vm/overcommit_memory 1
    write /proc/sys/vm/min_free_order_shift 4
    write /sys/module/lowmemorykiller/parameters/minfree 2048,3072,4096,15360,15360,14336

參考:http://bbs.hiapk.com/thread-1165395-1-1.html       http://bbs.fengbao.com/thread-869501-1-1.html

1.FOREGROUND_APP:前臺程序
This is the process running the current foreground app.  We'd really rather not kill it!
用戶正在使用的程序. 這個設的太高,用戶看到得就會是一個正在使用的程序莫名其妙的消失了,然後自動回到桌面..(因爲它被系統kill了..) 所以最好別動它..
目前正在屏幕上顯示的進程和一些系統進程。舉例來說,Dialer Storage,Google Search等系統進程就是前臺進程;再舉例來說,當你運行一個程序,如瀏覽器,當瀏覽器界面在前臺顯示時,瀏覽器屬於前臺進程(foreground),但一旦你按home回到主界面,瀏覽器就變成了後臺程序(background)。我們最不希望終止的進程就是前臺進程
2.. VISIBLE_APP: 可見程序
This is a process only hosting activities that are visible to the user, so we'd prefer they don't disappear.
跟FOREGROUND_APP類似,用戶正在使用/看得到. 它們的區別就是VISIBLE_APP可能不是用戶預期需要的程序,但是用戶看得到. 所以可以適當的比FOREGROUND_APP高一點.
可見進程是一些不再前臺,但用戶依然可見的進程,舉個例來說:widget、輸入法等,都屬於visible。這部分進程雖然不在前臺,但與我們的使用也密切相關,我們也不希望它們被終止(你肯定不希望時鐘、天氣,新聞等widget被終止,那它們將無法同步,你也不希望輸入法被終止,否則你每次輸入時都需要重新啓動輸入法)
3. SECONDARY_SERVER:次要服務
This is a process holding a secondary server -- killing it will not have much of an impact as far as the user is concerned.
所有應用的service. 系統級的service比如PhoneService不屬於這類,它們是絕不會被Android結束掉的. 所以這個可以適當的設高一點點~ 注意, HOME(SenseUI)也包括在這裏 因此還是別設的太高. 要不每次返回桌面都得等它重新load,特別是widget多的..
目前正在運行的一些服務(主要服務,如撥號等,是不可能被進程管理終止的,故這裏只談次要服務),舉例來說:谷歌企業套件,Gmail內部存儲,聯繫人內部存儲等。這部分服務雖然屬於次要服務,但很一些系統功能依然息息相關,我們時常需要用到它們,所以也太希望他們被終止
4.BACKUP APP MEMORY :(背景數據程序內存)
這個ANDROID系統裏是合併到上面的3.次要服務裏的,這個應該是後臺谷歌同步數據(日曆,聯繫人,地圖)
5.HOME-app-memory (桌面程序內存)
這個同樣ANDROID是合併到上面的3.次要服務裏的,其實應該是桌面LUNCHER類應用程序(ADW LP)
6.HIDDEN_APP:(隱藏程序)
This is a process only hosting activities that are not visible, so it can be killed without any disruption.
本來屬於1.前臺程序或者2.可見程序 的程序, 在用戶按了"back返回鍵"或者"home房子鍵"後,程序本身看不到了,但是其實還在運行的程序,它們就屬於HIDDEN_APP了. 幹掉沒什麼影響.. 不過要了解並不是所有屬於這一類的就應該馬上結束掉,像push mail,locale,鬧鐘,等都屬於這一類. 因此還是別設的過高. 真正"應該"一點返回鍵就退出的程序(真正沒用的程序)-空程序在下面.
雖然作者用了hidden這個詞,但實際即是後臺進程(background),就是我們通常意義上理解的啓動後被切換到後臺的進程,如瀏覽器,閱讀器等。當程序顯示在屏幕上時,他所運行的進程即爲前臺進程(foreground),一旦我們按home返回主界面(注意是按home,不是按back),程序就駐留在後臺,成爲後臺進程
(background)。後臺進程的管理策略有多種:有較爲積極的方式,一旦程序到達後臺立即終止,這種方式會提高程序的運行速度,但無法加速程序的再次啓動;也有較消極的方式,儘可能多的保留後臺程序,雖然可能會影響到單個程序的運行速度,但在再次啓動已啓動的程序時,速度會有所提升。這裏就需要用戶根據自己的使用習慣找到一個平衡點
7.CONTENT_PROVIDER:(內容/節點供應)
This is a process with a content provider that does not have any clients attached to it.  If it did have any clients, its adjustment would be the one for the highest-priority of those processes.
這個也是用處不大,但是還是比下面的EMPTY_APP(空程序)稍微有點用.. 所以高點沒關係,(大魚評論:有時候我開了大程序遊戲,返回桌面的時候,我的JORTE 日曆桌面插件顯示會縮小成一小塊,應該就是內容/節點供應達到閥值開始釋放內存有關。
沒有程序實體,進提供內容供別的程序去用的,比如日曆供應節點,郵件供應節點等。在終止進程時,這類程序應該有較高的優先權
8.EMPTY_APP:(空程序)
This is a process without anything currently running in it.  Definitely the first to go! This value is initalized in the constructor, careful when refering to this static variable externally.
完全沒用,殺了它只有好處沒壞處,第一個幹它!大魚評論:基本上大家運行的一些正常的第三方程序按返回退出後都變成了空程序!
有任何東西在內運行的進程,有些程序,比如BTE,在程序退出後,依然會在進程中駐留一個空進程,這個進程裏沒有任何數據在運行,作用往往是提高該程序下次的啓動速度或者記錄程序的一些歷史信息。這部分進程無疑是應該最先終止的。

OOM-ADJ等級:
(可根據“oom_adj”值的範圍來決定進程管理策略,比如可以設定“當內存小於X時,結束“oom_adj”大於Y的進程”)
0代表降低進程的優先級且駐留內存;這意味着它不會被系統終止,一旦它不可訪問後,會獲得個更高的“oom_adj”
1代表駐留內存;
4代表緩存較多的內存;
15代表儘量緩存內存。
也就是說內存緩存器是按照ADJ從大到小來進行緩存的。

一個經典用例:

ro.FOREGROUND_APP_ADJ=0 前臺程序駐留內存(不緩存)
ro.VISIBLE_APP_ADJ=1 可見的程序駐留內存(不緩存)
ro.PERCEPTIBLE_APP_ADJ=2 緩存的RAM多一些
ro.HOME_APP_ADJ=3 桌面程序,緩存的RAM稍多一些
ro.HEAVY_WEIGHT_APP_ADJ=4 緩存的RAM再多一些
ro.SECONDARY_SERVER_ADJ=5 緩存的RAM再再多一些
ro.BACKUP_APP_ADJ=6 緩存的RAM再再再多一些
ro.HIDDEN_APP_MIN_ADJ=7 隱藏的程序,根據程序的類型進行內存管理,最低爲緩存的RAM再再再再多一些,最高就是直接緩存內存。
ro.EMPTY_APP_ADJ=15 已經退出的程序,直接緩存內存

VSS – Virtual Set Size 虛擬耗用內存(包含共享庫佔用的內存)
RSS – Resident Set Size 實際使用物理內存(包含共享庫佔用的內存)
PSS – Proportional Set Size 實際使用的物理內存(比例分配共享庫佔用的內存)
USS – Unique Set Size 進程獨自佔用的物理內存(不包含共享庫佔用的內存)
可以使用procrank查看Android系統的各進程的VSS/RSS/PSS/USS的值。


free命令:


 totoal(1018216KB)是總內存數量,used(992664KB)表示已經使用的數量, free(25552KB)表示空閒數量。其中,total(1018216KB)=used(992664KB)+free(25552KB)。後面的buffers(9700)表示往磁盤空間裏“寫”的緩衝區大小,cached表示“讀”的數據的緩存,它們屬於used的一部分。二者可以快速變爲可用內存,使用它們出於改善系統IO性能的目的。當不把二者計入時,系統uesd和free的統計值就是下面的一行(-/+ buffers)因此:uesd:749728=992664-9700-233236,free:25552+9700+233236=268488
最下面的一行表示交換到磁盤空間的內存。

顯示當前正在運行的activity

class ShowCurrentActivityThd extends Thread{  
   @Override  
   public void run() {  
       // TODO Auto-generated method stub  
   super.run();  
   while(true){  
         ActivityManager mActivityManager = (ActivityManager) MainActivity.this.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName componentName = mActivityManager.getRunningTasks(1).get(0).topActivity;    
       String packageName = componentName.getPackageName();  
           String className = componentName.getClassName();  
               Log.d("TOP_ACTIVITY","package = " + packageName + ", class = " + className);
       try {  
           Thread.sleep(1500);  
           } catch (InterruptedException e) {  
           // TODO Auto-generated catch block  
       e.printStackTrace();  
       }  
   }  
   }  
}  

使用方法: new ShowCurrentActivityThd().start();  然後就會不停的打印當前activity的包名、類名

獲取音樂的內置圖片

轉自 http://blog.csdn.net/tao_zi7890/article/details/8851512

public class ArtworkUtils {  
    private static final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");  
    private static final BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options();  
  
    public static Bitmap getArtwork(Context context, String title, long song_id, long album_id,  
            boolean allowdefault) {  
        if (album_id < 0) {  
            if (song_id >= 0) {  
                Bitmap bm = getArtworkFromFile(context, song_id, -1);  
                if (bm != null) {  
                    return bm;  
                }  
            }  
            if (allowdefault) {  
                return getDefaultArtwork(context);  
            }  
            return null;  
        }  
        ContentResolver res = context.getContentResolver();  
        Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);  
        if (uri != null) {  
            InputStream in = null;  
            try {  
                in = res.openInputStream(uri);  
                Bitmap bmp = BitmapFactory.decodeStream(in, null, sBitmapOptions);  
                if (bmp == null) {  
                    bmp = getDefaultArtwork(context);  
                }  
                return bmp;  
            } catch (FileNotFoundException ex) {  
                Bitmap bm = getArtworkFromFile(context, song_id, album_id);  
                if (bm != null) {  
                    if (bm.getConfig() == null) {  
                        bm = bm.copy(Bitmap.Config.RGB_565, false);  
                        if (bm == null && allowdefault) {  
                            return getDefaultArtwork(context);  
                        }  
                    }  
                } else if (allowdefault) {  
                    bm = getDefaultArtwork(context);  
                }  
                return bm;  
            } finally {  
                try {  
                    if (in != null) {  
                        in.close();  
                    }  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
        return null;  
    }    
    private static Bitmap getArtworkFromFile(Context context, long songid, long albumid) {  
        Bitmap bm = null;  
        if (albumid < 0 && songid < 0) {  
            throw new IllegalArgumentException("Must specify an album or a song id");  
        }  
        try {  
            if (albumid < 0) {  
                Uri uri = Uri.parse("content://media/external/audio/media/" + songid + "/albumart");  
                ParcelFileDescriptor pfd = context.getContentResolver()  
                        .openFileDescriptor(uri, "r");  
                if (pfd != null) {  
                    FileDescriptor fd = pfd.getFileDescriptor();  
                    bm = BitmapFactory.decodeFileDescriptor(fd);  
                }  
            } else {  
                Uri uri = ContentUris.withAppendedId(sArtworkUri, albumid);  
                ParcelFileDescriptor pfd = context.getContentResolver()  
                        .openFileDescriptor(uri, "r");  
                if (pfd != null) {  
                    FileDescriptor fd = pfd.getFileDescriptor();  
                    bm = BitmapFactory.decodeFileDescriptor(fd);  
                }  
            }  
        } catch (FileNotFoundException ex) {  
        }  
        return bm;  
    }    
    private static Bitmap getDefaultArtwork(Context context) {  
        BitmapFactory.Options opts = new BitmapFactory.Options();  
        opts.inPreferredConfig = Bitmap.Config.RGB_565;  
        return BitmapFactory.decodeStream(  
                context.getResources().openRawResource(R.drawable.music_icon), null,  
                opts);  
    }  

創建阻塞式模態對話框的方法

轉自:http://blog.csdn.net/winux/article/details/6269687  和 http://www.eoeandroid.com/thread-272252-1-1.html

import android.app.Activity;
import android.app.Dialog;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.method.PasswordTransformationMethod;
import android.text.method.TransformationMethod;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
public class PasswordDialog extends Dialog
{
int dialogResult;
Handler mHandler ;

public PasswordDialog(Activity context, String mailName, boolean retry)
{

super(context);
setOwnerActivity(context);
onCreate();
TextView promptLbl = (TextView) findViewById(R.id.promptLbl);
promptLbl.setText("請輸入密碼/n" + mailName);
}
public int getDialogResult()
{
return dialogResult;
}
public void setDialogResult(int dialogResult)
{
this.dialogResult = dialogResult;
}
/** Called when the activity is first created. */

public void onCreate() {
setContentView(R.layout.password_dialog);
findViewById(R.id.cancelBtn).setOnClickListener(new android.view.View.OnClickListener() {

@Override
public void onClick(View paramView)
{
endDialog(DialogResult.CANCEL);
}
});
findViewById(R.id.okBtn).setOnClickListener(new android.view.View.OnClickListener() {

@Override
public void onClick(View paramView)
{
endDialog(DialogResult.OK);
}
});
}

public void endDialog(int result)
{
dismiss();
setDialogResult(result);
Message m = mHandler.obtainMessage();
mHandler.sendMessage(m);
}

public int showDialog()
{
mHandler = new Handler() {
@Override
              public void handleMessage(Message mesg) {
                  // process incoming messages here
//super.handleMessage(msg);
throw new RuntimeException();
              }
          };
super.show();
try {
Looper.getMainLooper().loop();
}
catch(RuntimeException e2)
{
}
return dialogResult;
}

}

網絡連接相關

轉自:http://blog.csdn.net/tao_zi7890/article/details/9278955

/**
    * 獲取當前的網絡狀態  -1:沒有網絡  1:WIFI網絡2:wap網絡3:net網絡
    */ 
   public int getAPNType(Context context){ 
    int CMNET = 3, CMWAP=2, WIFI=1;
       int netType = -1;  
       ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
       android.net.NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); 
       if(networkInfo==null){ 
           return netType; 
       } 
       int nType = networkInfo.getType();  // 取得類型
       if(nType==ConnectivityManager.TYPE_MOBILE){ 
           log("networkInfo.getExtraInfo()"+ " networkInfo.getExtraInfo() is "+networkInfo.getExtraInfo()); 
           if(networkInfo.getExtraInfo().toLowerCase().equals("cmnet")){ 
               netType = CMNET; 
           } 
           else{ 
               netType = CMWAP; 
           } 
       } 
       else if(nType==ConnectivityManager.TYPE_WIFI){ 
           netType = WIFI; 
       } 
       return netType; 
   } 

//判斷是否連接到網絡

android.net.NetworkInfo[] networkInfo = connectivity.getAllNetworkInfo();   
             if (networkInfo != null) {   
                 for (int i = 0; i < networkInfo .length; i++) {   
                     if (networkInfo [i].getState() == android.net.NetworkInfo.State.CONNECTED) {   
                         log("netWorkNameis:"+networkInfo [i].getTypeName()+"  subTypeName="+inetworkInfo fo[i].getSubtypeName()+"  NetWorkState is:"+ "Availabel");   
                         return true;   
                     }   
                 }   
             }   

或者:

android.net.NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();  
        if (networkInfo != null) {  
            return networkInfo.isAvailable();  
        }  

網絡類型:

connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);     //0

connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);//1

TYPE_MOBILE_MMS  //2    、        .....TYPE_BLUETOOTH //7

打開/關閉wifi

private void setWifi(boolean on) {
		// TODO Auto-generated method stub
		if (mWifiManager == null) {
			// mWifiManager = (WifiManager)this.getSystemService(Context.WIFI_SERVICE);
			return;
		}

		Log.d("jimbo", "wifi====" + mWifiManager.isWifiEnabled()+ "  is going to  state:"+on);
		if (on) {// 開啓wifi
			if (!mWifiManager.isWifiEnabled()) {
				mWifiManager.setWifiEnabled(true);

			}
		} else {
			// 關閉 wifi
			if (mWifiManager.isWifiEnabled()) {
				mWifiManager.setWifiEnabled(false);
			}
		}
	}

打開/關閉藍牙 bt

private void setBT(boolean enable) {
		// TODO Auto-generated method stub
		
		if (btAdapter == null) {
			//btadapter = BluetoothAdapter.getDefaultAdapter();
			Log.d("jimbo", "not support bluetooth");
		} else {
			if (enable) {
				btAdapter.enable();
			} else {
				btAdapter.disable();
			}
			IntentFilter intentFilterBt = new IntentFilter();
			intentFilterBt.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
			intentFilterBt.addAction(BluetoothDevice.ACTION_FOUND);
			intentFilterBt.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
			intentFilterBt.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
			intentFilterBt.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
			registerReceiver(mBtStateReceiver , intentFilterBt);
			
			btAdapter.startDiscovery();
			
		}
	}

Intent的使用

1、顯示使用Explicit 當你有一個消息需要傳遞,如果你明確知道你需要哪個Activity 或者其他Class 來響
應的話,你可以指定這個類來接受該消息,這被稱爲顯性發送。你需要將Intent 的class 屬性設置成目標。
用setClass或setComponent來設置 Intent的發起方與接收方

2、隱式使用Implicit 不需要用setClass或setComponent來指定事件處理 器,利用AndroidMenifest.xml中的配置由平臺定位事件的消費者

intent要定位事件的目的地,無外乎需要以下幾個信息:
1).種類(category),比如我們常見的 LAUNCHER_CATEGORY 就是表示這是一類應用程序。
2).類型(type),在前面的例子中沒用過,表示數據的類型,這是隱性Intent定位目標的重要依據。
3).組件(component),前面的例子中用的是setClass,不過也可以用setComponent來設置intent跳轉的前後兩個類實例。
4).附加數據(extras),在ContentURI之外還可以附加一些信息,它是Bundle類型的對象。

舉例:

增加一個類:HelloThreeProvider,它必須實現於ConentProvider接口,然後,在AndroidMenifest.xml中我們將上面這個HelloThreeProvider類加入應用程序 <provider class="HelloThreeProvider" android:authorities="cn.sharetop.android.hello" />

隱式使用  Intent intent = new Intent();

//使用在AndroidMenifest.xml中定義的android:authorities 的標籤  content://+authorities+
  intent.setData(new ContentURI("content://cn.sharetop.android.hello/one"));
  intent.setAction(intent.VIEW_ACTION);
  startActivity(intent);

現在我們的setData裏的東西可與以前不一樣的,是吧?注意到它的格式了嗎?content://是個協議頭,固定這樣寫就行了。然後就是那個authorities中定義的串了,再後面就是我們自定義的東西了,我這裏很簡單的寫個one,其它還可以更長一點,如one/101之類的。它負責去關聯上那個provider類。另外,增加了setAction的調用設置操作爲VIEW_ACTION,與Menifest中的<action>又掛上了。Android平臺負責根據Intent的Data信息中的authorities,找到ContentProvider,然後getType,用type和intent中的Action兩個信息,再找到可以處理這個intent的消費者。

轉自:http://www.sf.org.cn/Android/lumen/20979.html

判斷Bitmap 是否是.9圖片

//private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {  // BitmapFactory.java  

        byte[] np = bm.getNinePatchChunk();
        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);

拍照並保存到SD卡代碼:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, SystemCapture);

    public void takePicture()  
    {  
        if(m_camera != null)  
            m_camera.takePicture(shutterCallback, rawCallback, jpegCallback);  
    }  
    public void open()  
    {  
        if(m_camera == null)  
            m_camera = Camera.open();  
    }  
    public void release()  
    {  
        if(m_camera != null)  
        {  
            m_camera.release();  
            m_camera = null;  
        }  
    }  
    ShutterCallback shutterCallback = new ShutterCallback() {  
        public void onShutter() {  
            Log.d(TAG, "onShutter'd");  
        }  
    };  
  
    /** Handles data for raw picture */  
    PictureCallback rawCallback = new PictureCallback() {  
        public void onPictureTaken(byte[] data, Camera camera) {  
            Log.d(TAG, "onPictureTaken - raw");  
        }  
    };  
    /** Handles data for jpeg picture */  
    PictureCallback jpegCallback = new PictureCallback() {  
        public void onPictureTaken(byte[] data, Camera camera) {  
            try  
            {  
                Bitmap bitmapPicture = BitmapFactory.decodeByteArray(data, 0, data.length);  
                String path = Environment.getExternalStorageDirectory().toString();  
                String filename;  
                Date date = new Date(0);  
                SimpleDateFormat sdf = new SimpleDateFormat ("yyyyMMddHHmmss");  
                filename =  sdf.format(date);  
                OutputStream fOut = null;  
                //File file = new File(path, "/DCIM/"+filename+".jpg");  
                File file = new File(path, "/"+filename+".jpg");  
                fOut = new FileOutputStream(file);  
                //FileOutputStream out = new FileOutputStream(String.format("/sdcard/DCIM/Signatures/%d.jpg", System.currentTimeMillis()));  
                bitmapPicture.compress(Bitmap.CompressFormat.JPEG, 0, fOut);  
                fOut.flush();  
                fOut.close();  
  
                MediaStore.Images.Media.insertImage(m_contentResolver,file.getAbsolutePath(),file.getName(),file.getName());  
            }  
            catch(Exception ex)  
            {  
                ex.printStackTrace();  
            }  
            finally  
            {  
                camera.startPreview();  
            }  
            Log.d(TAG, "onPictureTaken - jpeg");  
        }  
    };  

實現錄像功能

Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, SystemVideoRecord);

取得前、後攝像頭

private int getFrontCameraId(){
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();  
        cameraCount = Camera.getNumberOfCameras(); // get cameras number  
                
        if(cameraCount == 0){
        mCameraId = -1 ;
        Toast.makeText(this, "no camera devices avalible! finish this acitivty", Toast.LENGTH_LONG).show();
        finish();
        }else if(cameraCount == 1) {
mCameraId = 0;
}else{
for(int camIdx = 0; camIdx < cameraCount; camIdx++ ) {  
Camera.getCameraInfo(camIdx, cameraInfo ); // get camerainfo  
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT ) {   
// 代表攝像頭的方位,目前有定義值兩個分別爲CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK後置  
mCameraId = camIdx;  
break;
}  
}
}
        return mCameraId;
}

 回到待機界面

Intent home = new Intent(Intent.ACTION_MAIN);  
home.addCategory(Intent.CATEGORY_HOME);  
this.startActivity(home); 

鎖屏可以根據GSensor旋轉

在代碼:KeyguardUtils.java (main\frameworks\base\packages\keyguard\src\com\mediatek\keyguard\utils)
    public static boolean shouldEnableScreenRotation(Context context) {
        ///M: when is alarm boot,disable rotation @{
        if (PowerOffAlarmManager.isAlarmBoot()) {
            return false;
        } 
        ///@}
        return SystemProperties.getBoolean("lockscreen.rot_override",false)
                || context.getResources().getBoolean(R.bool.config_enableLockScreenRotation);
    }

所以可以i修改
Config.xml (main\frameworks\base\core\res\res\values):    <bool name="config_enableLockScreenRotation">false</bool>
或增加屬性
lockscreen.rot_override=true
都可以實現鎖屏界面的旋轉
</pre></div><h3>設置(Settings)<span style="background-color:#ff9632">默認</span>值</h3><p>frameworks/base/packages/SettingsProvider/src/com/Android/providers/settings/DatabaseHelper.java</p><p>loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT, R.integer.def_screen_off_timeout);</p><p>R.integer.def_screen_off_timeout來初始化。我們爲了讓系統永不鎖屏,只需要把資源 R.integer.def_screen_off_timeout設爲-1即可。查看文件</p><p>frameworks\base\packages\SettingsProvider\res\values\defaults.xml  設置裏面的<span style="background-color:#ffd700">默認</span>值  例:def_screen_off_timeout  <span style="background-color:#ffd700">默認</span>鎖屏時間frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java  函數loadSystemSettings(SQLiteDatabase db) 加載各個<span style="background-color:#ffd700">默認</span>值SoundSettings.java mDtmfToneDefaultValue<span style="background-color:#ffd700">默認</span>按鍵音</p><p>開機<span style="background-color:#ffd700">默認</span>鎖屏 :</p><p>frameworks/policies/base/phone/com/Android/internal/policy/impl/KeyguardViewMediator.java該文件中有一個變量定義如下:    /**     * External apps (like the phone app) can tell us to disable the keygaurd.     */    private boolean mExternallyEnabled = true;mExternallyEnabled是用來管理是否開啓屏幕鎖的關鍵。<span style="background-color:#ffd700">默認</span>值是打開屏鎖       </p><p>默認時間格式: </p><p>DateFormat.java  is24HourFormat()</p><p>android源碼是根據地區自適應選擇是24小時還是12小時</p><p>代碼:</p><pre code_snippet_id="76283" snippet_file_name="blog_20131121_3_7535774" class="java" name="code"> if (value == null) {
     Locale locale = context.getResources().getConfiguration().locale;
     ……
     java.text.DateFormat natural =
                java.text.DateFormat.getTimeInstance(
                    java.text.DateFormat.LONG, locale);
      ……
}


如果要去掉自適應,可以修改

java.text.DateFormat.LONG, locale); ->java.text.DateFormat.LONG, Locale.UK);    //24小時格式

java.text.DateFormat.LONG, locale); ->java.text.DateFormat.LONG, Locale.US.);    //12小時格式

修改默認時間

mtk中默認時間設置:

\alps\mediatek\custom\[project]\preloader\ inc\cust_rtc.h
\alps\mediatek\custom\[project]\kernel\rtc\rtc\rtc-mt65XX.h
 
#define RTC_DEFAULT_YEA         2010
#define RTC_DEFAULT_MTH        1
#define RTC_DEFAULT_DOM        1

也可以在kernel中使用代碼設置時間

(在android中,Linux內核中、rtc時鐘,默認的起始日期都是1970年1月1日,那麼如何把默認日期指到2012-01-01呢?筆者在實踐中發現,在RTC驅動中可以很容易實現。在RTC驅動加載的時候,一般都有個probe函數需要先執行,因此在probe函數裏下手最直接有效。RTC從1970-01-01開始,那當然很容易把默認值設置到2012-01-01,所需要設置的seconds也就是從1970-01-01所差的秒數,以秒爲單位。因此,一旦讀出來的RTC值小於我們預想的值比如2012-01-01(1325402913)小,我們就把它設置到這個時間點。)

seconds = rtc_read_time();  
printk("init PMU/RTC time to  %ld \n", seconds);  
  
if(seconds <= 1325402913) {  
    seconds = 1325402913;/*2012-01-01*/  
    ret = rtc_set_time(seconds);  
    RTC_DBG("Init Set time: %ld, ret =0x%x\n", seconds, ret);  
}

java 24小時格式顯示轉換

在使用SimpleDateFormat時格式化時間的 yyyy.MM.dd 爲年月日而如果希望格式化時間爲12小時制的,則使用hh:mm:ss 如果希望格式化時間爲24小時制的,則使用HH:mm:ss 

Date d = new Date();  
SimpleDateFormat ss = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//12小時制   
System.out.println(ss.format(d));  
  
Date date = new Date();  
SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//24小時制   
String LgTime = sdformat.format(date);  
System.out.println(LgTime);  

xml 字符串中特殊字符& 、<、>、 '、" 的處理

& 使用&amp; 代替                  ' 使用\' 代替'

 &lt; < 小於號
&gt; > 大於號
&amp; & 和
&apos; ' 單引號
&quot; " 雙引號

<b></b>加粗字體 
<i></i> 斜體字體 
<u></u> 給字體加下劃線 
\n 換行 
\u0020表示空格 
\u2026表示省略號 
使用&lt;b>和&lt;b>來打印出<b></b> 這樣的文字;“&lt;”表示“<”的意思; 
使用textView.setText(Html.fromHtml("Hello <b>World</b>,<font size=\"3\" color=\"red\">AnalysisXmlActivty!</font>"));設置類似於html那樣的效果 
如果你需要使用 String.format(String, Object...) 來格式化你的字符串,你可以把格式化參數放在你的字符串中,參見下面的例子: 
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string> 
在這個例子中,這個格式化的字符串有2個參數, %1$s是個字符串 %2$d 是個浮點數,你可以在你的程序中按照下面的方法來根據參數來格式化字符串: 
Resources res = getResources(); 
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount); 
那麼根據例子上說的我需要把%s換成%1$s才行了,修改後編譯通過,程序成功啓動。 
問題補充:如何在<string></string>中使用%號 
有兩個辦法可供選擇 
1.用%%來表示1個%,和轉意符號 \ 的用法相同 
2.如果你的字符串不需要格式化,可以在你的<string 標籤上增加一個屬性:formatted="false"例如 <string name="test" formatted="false">% test %</string> 即可 


開機後特定的時間內自動發送短信 

StartCromeSendMsgReceiver.java

public class StartCromeSendMsgReceiver extends BroadcastReceiver {
    private TelephonyManager mTelephonyManager;
    private Context mContext = null;
private String mImeiStr = null;
   private static final int SEND_SMS_MESSAGE_WHAT = 0x100; 
private final Timer mSendSmsTimer = new Timer();
private TimerTask mSendSmsTask = null;
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
mContext = arg0;
if(arg1.getAction().equals( Intent.ACTION_BOOT_COMPLETED )) {
                   //延時時間 1小時start
mSendSmsTask = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
if(!isSendSmsFlagExist()){
Message message = mSendSmsHandler.obtainMessage();
message.what = SEND_SMS_MESSAGE_WHAT;
mSendSmsHandler.sendMessage(message);
}
}
};

// start timer
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub

long delayTimer = 60*1000; //60*60*1000;  //延時時間 1小時
mSendSmsTimer.schedule(mSendSmsTask, delayTimer, delayTimer);
}
}).start();
                   //延時時間 1小時end

                   //獲取IMEI 號   start
StringBuffer imeiBuffer = new StringBuffer();
int phoneCnt = TelephonyManager.getPhoneCount();

for (int i = 0; i < phoneCnt; i++) {
if(phoneCnt<2)
{
   imeiBuffer.append("IMEI:");
}
else
{
   imeiBuffer.append("IMEI");
   imeiBuffer.append((i + 1));
   imeiBuffer.append(":");
}

imeiBuffer.append(((TelephonyManager) arg0.getSystemService(PhoneFactory
.getServiceName(Context.TELEPHONY_SERVICE, i))).getDeviceId());

if(i < (phoneCnt-1))
{
   imeiBuffer.append("-");
}
}

mImeiStr = imeiBuffer.toString();
Log.d("StartCromeSendMsgReceiver", "+++++zhangyong[imeiStr]++++++ " + mImeiStr);
                   //獲取IMEI 號   end
}
else if (SEND_SMS.equals(arg1.getAction())) {
log(SEND_SMS);
//createSendSmsFlag();
}else if(DELIVERY_SMS.equals(arg1.getAction())) {
log(DELIVERY_SMS);
if(createSendSmsFlag()){
mSendSmsTimer.cancel();
}
}
}
private void log(String msg) {
// TODO Auto-generated method stub
Log.d("StartCromeSendMsgReceiver", "--"+msg+"--");
}
private Handler mSendSmsHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
       // TODO Auto-generated method stub
       // send sms
    switch (msg.what) {
case SEND_SMS_MESSAGE_WHAT:
sendImeiSms();
break;
default:
break;
}
   }
};
    
    private static final String DELIVERY_SMS = "delivery_sms_ok"; 
    private static final String SEND_SMS = "send_sms_ok"; 
    private static final String SEND_SMS_KEY = "has_send_sms"; 
  
private boolean createSendSmsFlag(){
boolean ret = false;
SharedPreferences preferences = mContext.getSharedPreferences("SEND_SMS_FLAG", Context.MODE_PRIVATE);

Editor editor = preferences.edit();
editor.putBoolean(SEND_SMS_KEY, true);
ret = editor.commit();

return ret;
}
private boolean isSendSmsFlagExist(){
boolean ret = false;
SharedPreferences preferences = mContext.getSharedPreferences("SEND_SMS_FLAG",Context.MODE_PRIVATE);
ret = preferences.getBoolean(SEND_SMS_KEY, false);
if(ret){
mSendSmsTimer.cancel();
}
return ret;
}
private void sendImeiSms(){
if(isSendSmsFlagExist()){
return;
}

//String sendingTextString = "測試文本!";
SmsManager sm = SmsManager.getDefault();
PendingIntent sendIntent = PendingIntent.getBroadcast(
mContext, 0,
new Intent(SEND_SMS),0);
PendingIntent deliveryIntent = PendingIntent.getBroadcast(
mContext, 0,
                new Intent(DELIVERY_SMS),0);
// new Intent(this, FullBlackActivity.class),0);

// 如果短信沒有超過限制長度,則返回一個長度的List。
List<String> texts = sm.divideMessage(mImeiStr);
for (String text : texts) {
//sms.sendTextMessage(“這裏是接收者電話號碼”,  “這裏是發送者電話號碼”,  “這裏是短信內容”,  null, null);
sm.sendTextMessage("15988888888", "", text, null, deliveryIntent);
//log(text);
}
}
}

然後在 AndroidManifest.xml文件中 增加

<receiver android:name=".StartCromeSendMsgReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>

<action android:name="send_sms_ok"/>

<action android:name="delivery_sms_ok"/>
</intent-filter>
</receiver>

撥號:

直接在adb中 撥號: am start -a android.intent.action.CALL -d tel:10086

Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "112")); 

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);  


定時器相關

一、採用Handler與線程的sleep(long)方法
二、採用Handler的postDelayed(Runnable, long)方法
三、採用Handler與timer及TimerTask結合的方法
四、鬧鐘定時
下面逐一介紹:
一、採用Handle與線程的sleep(long)方法
Handler主要用來處理接受到的消息。這只是最主要的方法,當然Handler裏還有其他的方法供實現,有興趣的可以去查API,這裏不過多解釋。
1. 定義一個Handler類,用於處理接受到的Message。
Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        // 要做的事情
        super.handleMessage(msg);
    }
};
2. 新建一個實現Runnable接口的線程類,如下:
public class MyThread implements Runnable {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            try {
                Thread.sleep(10000);// 線程暫停10秒,單位毫秒
                Message message = new Message();
                message.what = 1;
                handler.sendMessage(message);// 發送消息
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
3. 在需要啓動線程的地方加入下面語句:
new Thread(new MyThread()).start();
4. 啓動線程後,線程每10s發送一次消息。
二、採用Handler的postDelayed(Runnable, long)方法
這個實現比較簡單一些。
1. 定義一個Handler類
Handler handler=new Handler();
Runnable runnable=new Runnable() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        //要做的事情
        handler.postDelayed(this, 2000);
    }
};
2. 啓動計時器
handler.postDelayed(runnable, 2000);//每兩秒執行一次runnable.
3. 停止計時器
handler.removeCallbacks(runnable);
三、採用Handler與timer及TimerTask結合的方法
1. 定義定時器、定時器任務及Handler句柄
private final Timer timer = new Timer();
private TimerTask task;
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        // 要做的事情
        super.handleMessage(msg);
    }
};
2. 初始化計時器任務
task = new TimerTask() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        Message message = new Message();
        message.what = 1;
        handler.sendMessage(message);
    }
};
3. 啓動定時器
timer.schedule(task, 2000, 2000);
簡要說一下上面三步提到的一些內容:
1. 定時器任務(TimerTask)顧名思義,就是說當定時器到達指定的時間時要做的工作,這裏是想Handler發送一個消息,由Handler類進行處理。
2. java.util.Timer.schedule(TimerTask task, long delay):這個方法是說,dalay/1000秒後執行task.只執行一次。
java.util.Timer.schedule(TimerTask task, long delay, long period):這個方法是說,delay/1000秒後執行task,然後進過period/1000秒再次執行task,這個用於循環任務,執行無數次,當然,你可以用timer.cancel();取消計時器的執行。
四、鬧鐘定時
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(SEND_SMS_BEGIN), 0);
am.set(AlarmManager.RTC_WAKEUP, 60*1000, pendingIntent);

android.mk 編譯選項

definitions.mk    定義各類函數 例: define my-dir   define all-makefiles-under     define all-subdir-makefiles   define all-java-files-under
build/core/config.mk  各類變量的定義   例: BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk   BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk  BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk

耳機狀態

private static final String HEADSET_STATE_PATH = "/sys/class/switch/h2w/state";    保存狀態文件位置

private boolean isHeadsetExists(){       //判斷耳機是否插入的函數    FM源碼 FMplayService.java  
        char[] buffer = new char[1024];
        int newState = 0;
        try {
            FileReader file = new FileReader(HEADSET_STATE_PATH);
            int len = file.read(buffer, 0, 1024);
            newState = Integer.valueOf((new String(buffer, 0, len)).trim());
        } catch (FileNotFoundException e) {
            Log.e(LOGTAG, "This kernel does not have wired headset support");
        } catch (Exception e) {
            Log.e(LOGTAG, "" , e);
        }
        return newState != 0;
   }

未插入耳機:

# cat /sys/class/switch/h2w/state
cat /sys/class/switch/h2w/state
0

插入耳機:
# cat /sys/class/switch/h2w/state
cat /sys/class/switch/h2w/state
1

sd卡和sim卡狀態判斷

//sdcard是否可讀寫 

public boolean IsCanUseSdCard() { 
    try { 
        return Environment.getExternalStorageState().equals( 
                Environment.MEDIA_MOUNTED); 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
    return false; 

//sim卡是否可讀 

public boolean isCanUseSim() { 
    try { 
        TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
         return TelephonyManager.SIM_STATE_READY == mgr.getSimState(); 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
    return false; 

開機啓動,檢查sim卡是否發生變更

(1)註冊receiver,設置意圖過濾器
<receiver android:name=".receiver.BootCompleteReceiver" >
    <intent-filter android:priority="1000" >
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
(2)接受開機廣播,並判斷sim卡時候發生更改
public class BootCompleteReceiver extends BroadcastReceiver {
    private static final String TAG = "BootCompleteReceiver";
    private SharedPreferences sp;
    private TelephonyManager tm;
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG,"手機重啓了");
        sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
        boolean protecting = sp.getBoolean("protecting", false);
        //如果防盜保護開啓
        if(protecting){
                //判斷sim卡是否發生了變化
        tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            String currentSim = tm.getSimSerialNumber();
            String savedSim= sp.getString("sim", "");
            if(savedSim.equals(currentSim)){
                    // sim卡爲發生變化, do nothint
            }else{
                //sim卡發生了變化
                //發送報警短信 給安全號碼
                SmsManager smsManager = SmsManager.getDefault();
                String destinationAddretss = sp.getString("safenumber", "");
                smsManager.sendTextMessage(destinationAddretss, null, "sim change !!!", null, null);
            }
        }
    }
}

判斷SIM卡屬於哪個移動運營商

第一種方法:
獲取手機的IMSI碼,並判斷是中國移動\中國聯通\中國電信  
TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
/** 獲取SIM卡的IMSI碼
* SIM卡唯一標識:IMSI 國際移動用戶識別碼(IMSI:International Mobile Subscriber Identification Number)是區別移動用戶的標誌,
* 儲存在SIM卡中,可用於區別移動用戶的有效信息。IMSI由MCC、MNC、MSIN組成,其中MCC爲移動國家號碼,由3位數字組成,
* 唯一地識別移動客戶所屬的國家,我國爲460;MNC爲網絡id,由2位數字組成,
* 用於識別移動客戶所歸屬的移動網絡,中國移動爲00,中國聯通爲01,中國電信爲03;MSIN爲移動客戶識別碼,採用等長11位數字構成。
* 唯一地識別國內GSM移動通信網中移動客戶。所以要區分是移動還是聯通,只需取得SIM卡中的MNC字段即可  
*/ 
String imsi = telManager.getSubscriberId();
if(imsi!=null){  
if(imsi.startsWith("46000") || imsi.startsWith("46002")){
//因爲移動網絡編號46000下的IMSI已經用完,所以虛擬了一個46002編號,134/159號段使用了此編號  
//中國移動  
}else if(imsi.startsWith("46001")){  
//中國聯通  
}else if(imsi.startsWith("46003")){ 
//中國電信 
}  
}
第二種方法
TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
String operator = telManager.getSimOperator();
if(operator!=null){  
if(operator.equals("46000") || operator.equals("46002")){  
//中國移動  
}else if(operator.equals("46001")){  
//中國聯通  
}else if(operator.equals("46003")){  
//中國電信 
}  
}  
在文件 AndroidManifest.xml中添加權限 

<uses-permission  android:name="android.permission.READ_PHONE_STATE"/> 

取得sim卡的網絡類型

  public String getNetworkTypeName() {
        switch (getNetworkType()) {
            case NETWORK_TYPE_GPRS:
                return "GPRS";
            case NETWORK_TYPE_EDGE:
                return "EDGE";
            case NETWORK_TYPE_UMTS:
                return "UMTS";
            case NETWORK_TYPE_HSDPA:
                return "HSDPA";
            case NETWORK_TYPE_HSUPA:
                return "HSUPA";
            case NETWORK_TYPE_HSPA:
                return "HSPA";
            case NETWORK_TYPE_CDMA:
                return "CDMA";
            case NETWORK_TYPE_EVDO_0:
                return "CDMA - EvDo rev. 0";
            case NETWORK_TYPE_EVDO_A:
                return "CDMA - EvDo rev. A";
            case NETWORK_TYPE_EVDO_B:
                return "CDMA - EvDo rev. B";
            case NETWORK_TYPE_1xRTT:
                return "CDMA - 1xRTT";
            default:
                return "UNKNOWN";
        }
    }

手機卡種類:

private String getSimType() {
        // 獲得SIMType   
        String simType = "";
        // 獲得系統服務,從而取得sim數據   
        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
        int type = tm.getNetworkType();
        System.out.println(Contants.DEBUG+" NetWorkType:"+type);
        //Test1:聯通USIM卡,在這兒取出來的值爲10-------NETWORK_TYPE_HSPA
        //Test2:中國移動 神州行OTA 2-----NETWORK_TYPE_EDGE
        //Test3:中國移動 動感地帶OTA 2-----NETWORK_TYPE_EDGE
        //...
 
        switch (type) {
            case TelephonyManager.NETWORK_TYPE_UNKNOWN://0
                simType= "UNKOWN";
                break;
            case TelephonyManager.NETWORK_TYPE_GPRS://1
                simType= "SIM";
                break;
            case TelephonyManager.NETWORK_TYPE_EDGE://2
                simType= "SIM";
                break;
            case TelephonyManager.NETWORK_TYPE_UMTS://3
                simType= "USIM";
                break;
            case TelephonyManager.NETWORK_TYPE_CDMA://4
                simType= "Either IS95A or IS95B Card";
                break;
            case TelephonyManager.NETWORK_TYPE_EVDO_0://5
                simType= "EVDO revision 0 Card";
                break;
            case TelephonyManager.NETWORK_TYPE_EVDO_A://6
                simType= "EVDO revision A Card";
                break;
            case TelephonyManager.NETWORK_TYPE_1xRTT://7
                simType= "1xRTT Card";
                break;
            case TelephonyManager.NETWORK_TYPE_HSDPA://8
                simType= "HSDPA Card";
                break;
            case TelephonyManager.NETWORK_TYPE_HSUPA://9
                simType= "HSUPA Card";
                break;
            case TelephonyManager.NETWORK_TYPE_HSPA://10
                simType= "USIM";
                break;
             
        }
        System.out.println(Contants.DEBUG+" sim type :"+simType);
        return simType;
    }
各種手機卡知識:http://bbs.csdn.net/topics/390199890

單態模式實例

一:public class Singleton {
  private Singleton(){}  //注意這是private 只供內部調用
  private static Singleton instance = new Singleton();  //這裏提供了一個供外部訪問本class的靜態方法,可以直接訪問  
  public static Singleton getInstance() {
    return instance;   
  } 
}
二:public class Singleton {
  private static Singleton instance = null;
  public static synchronized Singleton getInstance() {//注意一定要加上關鍵字 synchronized  否則有可能得到多個Singleton實例
  if (instance==null){
    instance=new Singleton();
}
  return instance;
  }
}

修改 特殊字符的命令(工程命令,如展訊*#*#83789#*#*)

TwelveKeyDialer.java afterTextChanged->

SpecialCharSequenceMgr.java ->handleChars ->handleSecretCode

/**
     * Handles secret codes to launch arbitrary activities in the form of *#*#<code>#*#*.
     * If a secret code is encountered an Intent is started with the android_secret_code://<code>
     * URI.
     *
     * @param context the context to use
     * @param input the text to check for a secret code in
     * @return true if a secret code was encountered
     */
    static boolean handleSecretCode(Context context, String input) {
        // Secret codes are in the form *#*#<code>#*#*
        int len = input.length();
        if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
            Intent intent = new Intent(Intents.SECRET_CODE_ACTION,
                    Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
            context.sendBroadcast(intent);
            return true;
        }
        return false;
    }

makefile詳解

http://blog.csdn.net/zirconsdu/article/details/8005415

默認字體大小

frameworks/base/core/java/android/content/res/Configuration.java裏面,有個fontScale=1

screen 默認拉伸大小  

settings->screen->Screen Scale

默認大小: DEFALUT_SCREEN_SCALE      手機存放路徑: /sys/class/graphics/fb0/scale 或 /sys/class/graphics/fb2/scale

ScreenScaleManager.cpp

#define MAIN_DISPLAY_SCALE_FILE "/sys/class/graphics/fb0/scale"
#define AUX_DISPLAY_SCALE_FILE "/sys/class/graphics/fb2/scale"

獲得圓角圖片的方法

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {

Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);

final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);

paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);

return output;
}

網絡下載

private Runnable mdownApkRunnable = new Runnable() {      
        @Override  
        public void run() {  
            try {  
                URL url = new URL(apkUrl);  
              
                HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
                conn.connect();  
                int length = conn.getContentLength();  
                InputStream is = conn.getInputStream();  
                  
                File file = new File(savePath);  
                if(!file.exists()){  
                    file.mkdir();  
                }  
                String apkFile = saveFileName;  
                File ApkFile = new File(apkFile);  
                FileOutputStream fos = new FileOutputStream(ApkFile);  
                  
                int count = 0;  
                byte buf[] = new byte[1024];  
                  
                do{                   
                    int numread = is.read(buf);  
                    count += numread;  
                    progress =(int)(((float)count / length) * 100);  
                    //更新進度  
                    mHandler.sendEmptyMessage(DOWN_UPDATE);  
                    if(numread <= 0){      
                        //下載完成通知<span style="BACKGROUND-COLOR: #ffd700">安裝</span>  
                        mHandler.sendEmptyMessage(DOWN_OVER);  
                        break;  
                    }  
                    fos.write(buf,0,numread);  
                }while(!interceptFlag);//點擊取消就停止下載.  
                  
                fos.close();  
                is.close();  
            } catch (MalformedURLException e) {  
                e.printStackTrace();  
            } catch(IOException e){  
                e.printStackTrace();  
            }  
              
        }  
    };  
      
     /** 
     * 下載apk 
     * @param url 
     */  
      
    private void downloadApk(){  
        downLoadThread = new Thread(mdownApkRunnable);  
        downLoadThread.start();  
    }  

一個彈出AlertDialog實例、機器重啓(reboot)實例

new AlertDialog.Builder(EthernetStaticIP.this)
<span style="WHITE-SPACE: pre">	</span>.setTitle(R.string.str_about)
<span style="WHITE-SPACE: pre">	</span>.setMessage(R.string.str_reboot)
<span style="WHITE-SPACE: pre">	</span>.setPositiveButton(R.string.str_ok, 
<span style="WHITE-SPACE: pre">		</span> new DialogInterface.OnClickListener()
<span style="WHITE-SPACE: pre">		</span> {
<span style="WHITE-SPACE: pre">		</span>    public void onClick(DialogInterface dialoginterfacd,int i)
<span style="WHITE-SPACE: pre">		</span>    {
<span style="WHITE-SPACE: pre">		</span>    <span style="WHITE-SPACE: pre">	</span>//reboot
<span style="WHITE-SPACE: pre">		</span>    /*final static */String SYSTEMUI_REBOOT_ACTION = "com.android.systemui.reboot";
                Intent intent = new Intent();
                intent.setAction(SYSTEMUI_REBOOT_ACTION);
                EthernetStaticIP.this.sendBroadcast(intent);
<span style="WHITE-SPACE: pre">		</span>    }
<span style="WHITE-SPACE: pre">		</span> } 
<span style="WHITE-SPACE: pre">	</span>)
<span style="WHITE-SPACE: pre">	</span>.setNegativeButton(R.string.str_cancel,
<span style="WHITE-SPACE: pre">		</span> new DialogInterface.OnClickListener()
<span style="WHITE-SPACE: pre">	</span> {
<span style="WHITE-SPACE: pre">			</span>public void onClick(DialogInterface dialoginterfacd,int i)
<span style="WHITE-SPACE: pre">			</span>{
<span style="WHITE-SPACE: pre">				</span>finish();
<span style="WHITE-SPACE: pre">			</span>}
<span style="WHITE-SPACE: pre">	</span> }  <span style="WHITE-SPACE: pre">		</span>
<span style="WHITE-SPACE: pre">	</span>)
<span style="WHITE-SPACE: pre">	</span>.show();
reboot代碼:

frameworks\base\services\java\com\android\server\wm\WindowManagerService.java   增加代碼 

    final static String SYSTEMUI_POWEROFF_ACTION = "com.android.systemui.poweroff";
    final static String SYSTEMUI_REBOOT_ACTION = "com.android.systemui.reboot";
    final BroadcastReceiver mAdditionalReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(SYSTEMUI_POWEROFF_ACTION.equals(intent.getAction())){
                Log.d(TAG,"wms calling shutdown dlg from broadcast..");
                shutdown();//ShutdownThread.shutdown(context,true);
            }else if(SYSTEMUI_REBOOT_ACTION.equals(intent.getAction())){	
                Log.d(TAG,"wms calling shutdown dlg from broadcast..");
                reboot();
            }
        }
    };
    public void shutdown() {
        ShutdownThread.shutdown(mContext, true);
    }	
    public void reboot() {
        ShutdownThread.reboot(mContext, null, false);
    }
及註冊廣播接收

        IntentFilter f = new IntentFilter();
        f.addAction(SYSTEMUI_POWEROFF_ACTION);
        f.addAction(SYSTEMUI_REBOOT_ACTION);	
        mContext.registerReceiver(mAdditionalReceiver, f);

獲得內存信息,cpu信息、頻率等

通過讀取文件/proc/cpuinfo系統CPU的類型等多種信息。
讀取/proc/stat 所有CPU活動的信息來計算CPU使用率 ,   "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" 存儲最大頻率的文件的路徑, cpuinfo_min_freq最低頻率,scaling_cur_freq當前頻率

通過讀取文件/proc/meminfo的信息獲取Memory的總量。
ActivityManager. getMemoryInfo(ActivityManager.MemoryInfo)獲取當前的可用Memory量

LOCAL_REQUIRED_MODULES

mms Android.mk 中 含有:LOCAL_REQUIRED_MODULES := SoundRecorder

LOCAL_REQUIRED_MODULES的作用當編譯整個android源碼時,如果mms模塊在編譯路徑中(即可以編譯打包到system.img下),
則會自動編譯SoundRecorder,並且打包到system.img,如果不是編譯整個源碼,只是mm。則不會編譯SoundRecorderl生成相應的apk文件。

<xliff:g>標籤介紹

定義可變的字符串:
當一個字符串中只包含一個可變的數
例如這樣: <string name="tedst"> %d首歌曲。</string>這樣正確的
當一個字符串中只包含多個可變的數 
例如: <string name="tedst">%d張專輯 %d首歌曲。</string>,這樣是錯誤的
當你字符串中包含多個 %d,需要用xliff:g來格式化字符串

<string name="appwidget_text_format"><xliff:g id="prefix">%1$s</xliff:g>: <xliff:g id="time">%2$s</xliff:g></string>
這個主要用於程序中,動態的插入內容時候使用,例如,
<string name="time">當前時間:<xliff:g id="prefix">%1$s</xliff:g>時 <xliff:g id="time">%2$s</xliff:g>分</string>
然後通過程序,context.getString(R.string.time,"10","05");
將會輸出——當前時間:10時05分

屬性id可以隨便命名
屬性example表示舉例說明,可以省略
%n$ms:代表輸出的是字符串,n代表是第幾個參數,設置m的值可以在輸出之前放置空格
%n$md:代表輸出的是整數,n代表是第幾個參數,設置m的值可以在輸出之前放置空格,也可以設爲0m,在輸出之前放置m個0
%n$mf:代表輸出的是浮點數,n代表是第幾個參數,設置m的值可以控制小數位數,如m=2.2時,輸出格式爲00.00

注意:一定要增加命名空間 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">  否則會編譯不過Error parsing XML: unbound prefix 

android kernel log圖片 生成工具 

log_make.sh   logo_linux_clut224.ppm

#!/bin/sh 

echo "make logo_linux_clut224.ppm start"
cd ./1/
echo "--make linuxlogo.pnm"
pngtopnm ../linuxlogo.png > linuxlogo.pnm
echo "--make linuxlogo224.pnm"
pnmquant 224 linuxlogo.pnm > linuxlogo224.pnm 
echo "--make logo_linux_clut224.pnm"
pnmtoplainpnm linuxlogo224.pnm > logo_linux_clut224.ppm

cd ..
echo "make logo_linux_clut224.ppm end"

android定位代碼

定位出現問題的代碼:
12-26 14:29:47.801 I/DEBUG ( 100): backtrace:
12-26 14:29:47.801 I/DEBUG ( 100): #00 pc 00016ce0 /system/lib/libc.so (strcmp+32)
12-26 14:29:47.801 I/DEBUG ( 100): #01 pc 000035bb /system/bin/vold
12-26 14:29:47.801 I/DEBUG ( 100): #02 pc 00003521 /system/bin/vold
12-26 14:29:47.801 I/DEBUG ( 100): #03 pc 00002b57 /system/lib/libsysutils.so (NetlinkListener::onDataAvailable(SocketClient*)+166)
12-26 14:29:47.801 I/DEBUG ( 100): #04 pc 000025cf /system/lib/libsysutils.so (SocketListener::runListener()+490)
在工程的根目錄下的shell端輸入:addr2line -e out/target/product/rk31sdk/symbols/system/bin/vold 00003521
其中,00003521爲出現問題的pc指針 
結果爲:system/vold/MiscManager.cpp:85
addr2line -e out/target/product/rk31sdk/symbols/system/bin/vold 000035bb 
system/vold/G3Dev.cpp:63

android ril的加載

在init.rc文件中進行加載Android RIL模塊
service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttyS0
也可以手動加載:
/system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttyS0

這兩種方式,都將啓動rild守護進程,然後通過-l參數將libreference-ril.so共享庫鏈入,libreference-ril.so的參數-d是指加載一個串口設備,/dev/ttyS0則是這個串口設備的具體設備文件,除了參數-d外,還有-s代表加載類型爲socket的設備,-p代表迴環接口

監控電話狀態: 來電、通話中、空閒

獲取電話服務: 在啓動Activity時間獲取電話服務

	TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
        MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener();
        // 手動註冊對PhoneStateListener中的listen_call_state狀態進行監聽通話
        telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
MyPhoneStateListener類
/**
 * 繼承PhoneStateListener類,我們可以重新其內部的各種監聽方法
 * 然後通過手機狀態改變時,系統自動觸發這些方法來實現我們想要的功能
 */
public class MyPhoneStateListener extends PhoneStateListener {
    /**
     * @param state 通話狀態
     * @param incomingNumber   手機號碼
     */
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                Log.e("---------", "掛掉");
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                Log.e("---------", "有來電,號碼是:" + incomingNumber);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.e("---------", "通話中");
            default:
                break;
        }
        super.onCallStateChanged(state, incomingNumber);
    }
}

相關權限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

NetworkOnMainThreadException錯誤解決:在主線程中訪問了網絡數據

E/AndroidRuntime(1562): android.os.NetworkOnMainThreadException

E/AndroidRuntime(1562): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)

查看Ubuntu版本、位數

1.cat /etc/issue
2.cat /etc/lsb-release
3.uname -a

位數:getconf LONG_BIT

 java工具 javah和javap的使用(獲取、生成java native函數signature工具)

javah的使用: 生成jni C函數聲明  在工程目錄\bin\classes目錄下執行 javah -o 生成的頭文件.h -jni java包名.類名 
     例:javah -o android_hardware_miscdevice.h -jni com.odm.misc.MiscDevice

javap的使用:獲得java文件的native函數簽名    在工程目錄\bin\classes目錄下執行 javap -s packagename.classname

            例: D:\workspace\TtyTester\bin\classes>javap -s com.odm.tty.ttyutil
Compiled from "TtyUtil.java"
public class com.odm.tty.TtyUtil extends java.lang.Object{
public static final java.lang.String A4_RFID_RDM_TTY_DEV;
。。。
  Signature: Ljava/lang/String;
public static final java.lang.String UE966_TTY_DEV;
  Signature: Ljava/lang/String;
public com.odm.tty.TtyUtil();
  Signature: ()V
}

ubuntu samba可視化共享

sudo apt-get install samba
sudo apt-get install smbfs
sudo apt-get install system-config-samba
sudo /etc/init.d/samba start
sudo system-config-samba 

遠程桌面登陸ubuntu後無法使用鍵盤輸入小寫s和m

在xp上所有程序->附件->遠程桌面連接  連接上Ubuntu後,發現輸入字母s或m後,分別彈出logout菜單和message菜單

百度搜索結果中列出了文章的部分信息,一個關鍵的url:https://bugs.launchpad.net/ubuntu/+source/indicator-applet/+bug/568401
 打開後,發現原來是indicator applet引起的bug具體修復步驟如下:
1.sudo apt-get install apt-show-versions  (安裝用於查看Ubuntu軟件包版本的應用)
2.sudo apt-show-versions | grep indicator-applet (查看安裝的indicator applet版本)發現安裝的版本正是0.3.6,存在bug的那個版本

3.sudo apt-get install indicator-applet   (更新至最新版本 0.3.7)
4.重啓機器後ok

使用adb 調試串口

Android手機上很多外設是串口連接到AP的,如modem,gps。爲了調試這些串口,通常需要將它們飛線接出來,用pc的串口連接調試。這樣比較麻煩。
在adb  shell裏是可以直接調試串口的,就不用飛線了,還可以驗證Android串口配置是否正確。
用usb連接Android設備調試後,在pc端輸入 adb shell,連接成功後,先停止一些可能佔用端口的服務,如:
stop ril-daemon停掉ril後臺
然後:
busybox microcom -t 15000 -s 115200 /dev/ttyS0
-t 單位毫秒,無操作自動退出時間。
-s 單位bps,串口波特率。
ttyS0 要操作的串口。
然後打開另一個命令行窗口,輸入:
adb shell cat /dev/ttyS0
然後可以在第一個窗口輸入命令,在第二個窗口可以看到命令和響應。
如果沒有響應,請檢查Android串口配置是否正確,串口號是否對,波特率是否正確。
microcom的-t設置要合理,太短,輸入命令可能輸入不完就退出了,太長要等很久才退出。
必須先執行第一個窗口,再執行第二個窗口,因爲不設置波特率,第二個窗口顯示會有問題。
第一個窗口microcom退出後,也可以用以下方法發送命令到串口:
echo -e "AT\r\n">/dev/ttyS0

啓動另外一個進程中的acitivity

Intent i = new Intent();
ComponentName cpName = new ComponentName("lee.magniwill.testserial", "lee.magniwill.testserial.MainActivity");
i.setComponent(cpName);
i.setAction("android.intent.action.MAIN");

啓動同一個進程中的acitivity

Intent intent = new Intent("lee.magniwill.testserial.MainActivity");
startActivity(intent);

通過字符串來使用R下面資源的ID 值 

方法一:      

Resources resources=getResources(); 
String resStr = "weather_"+iconToday[0];
int resID = resources.getIdentifier(resStr, "drawable", getPackageName());
log("image to show: "+resStr + " id="+resID);
log結果:04-13 12:17:46.509: D/WeatherForecast(2173): --- image to show: weather_7 id=2130837534 ---
方法二
try{ 
	Field field=R.drawable.class.getField(resStr); 
	int <span style="font-family: Arial, Helvetica, sans-serif;">resID </span>= field.getInt(new R.drawable()); 
	log("image to show: "+resStr + " id="+resID);
}catch(Exception e){ 
	log(resStr,e.toString()); 
}

攔截HOME鍵、power鍵

修改文件:frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java 

函數 interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {

...

if (keyCode == KeyEvent.KEYCODE_HOME) {

mContext.sendBroadcast(intetn);發送一個broatcast廣播, 然後在需要攔截home鍵的apk中接收改廣播並做相應處理即可

}

...

}

power鍵

    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {

       case KeyEvent.KEYCODE_POWER: {
                result &= ~ACTION_PASS_TO_USER;

// add begin app端可以接收 KEYCODE_POWER消息
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
try{
String calssName = activityManager.getRunningTasks(1).get(0).topActivity.getClassName();//得到當前的activity名稱
if ("com.xhw.fuctions.TakePicActivity".equals(calssName)){
//Please reset the special package name.
result |= ACTION_PASS_TO_USER;
Log.d(TAG,"detect power key in special package, pass to user!");
break;
}
}catch(NullPointerException e){
Log.d(TAG,"ingore a NullPointerException ..");
}
//add end

}

禁止系統安裝其他任何apk

修改文件: /frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java

註釋掉 runInstall();的調用處即可

C語言文件的讀寫、java語言文件的讀寫

	FILE*  fp =    fopen("/storage/sdcard1/medias/config.txt","rt");
	// int fread(void *ptr, int size, int nitems, FILE *stream);
	//返回值 int 代表真的讀取了多少次  size的長度
	//*ptr  數據讀到哪個內存空間裏面
	// size 一次讀取的數據的長度是多個字節
	// nitmes讀取多少次數據
	// stream 從哪個文件裏面讀
	int read = fread(mPoliceCode, sizeof(char)*6, 1, fp);
	ALOGE("!!!    !!! mPoliceCode  read =%d", read); 
	char recordLen[2] = {0};

	//int fseek(FILE *stream, long offset, int fromwhere);
	fseek(fp, 6 +1, SEEK_SET);	//警號是6位,加1位換行符
	read = fread(recordLen, sizeof(char)*1, 1, fp);
	ALOGE("!!!   !!! recordLen  read =%d", read); 
	mRecordlength = atoi(recordLen);
	ALOGE("!!!    mPoliceCode: %s, recordLen: %s, mRecordlength: %d read=", mPoliceCode, recordLen, mRecordlength, read); 
	
	fclose(fp);//關閉流
private void saveConfigs() {
		String configFileNameString = "config.txt";
		
		File settingsFile = new File(FileUtil.getDefStoragePath() + File.separator + "medias"+File.separator+ configFileNameString);
		// 如果文件不存在則創建之
		log("saveConfigs  = "+settingsFile.getAbsolutePath());
		if (!settingsFile.exists()) {
			try {
				boolean ret = settingsFile.createNewFile();
				log("saveConfigs  "+settingsFile.getAbsolutePath()+" isn't exist! create it success?=" + ret);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				log("saveConfigs create "+settingsFile.getAbsolutePath()+" error! " + e.getMessage());
			}
		}
		
		OutputStreamWriter osw = null;
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(settingsFile);
			osw = new OutputStreamWriter(fos, "gb2312");
			
			//寫入警號
			osw.write(MyApplication.policeCodeString);
			osw.write("\n");
			//寫入分段時間
			osw.write(MyApplication.recordlength+"");
			log("saveConfigs  code ="+MyApplication.policeCodeString +" recordlength=" + MyApplication.recordlength);
			
			osw.flush();
			osw.close();
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				if(osw != null) osw.close();
				if(fos != null) fos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

如何對手機內存中的文件數據進行讀寫呢?
    Context提供了領個方法來打開該應用程序的數據文件夾中的文件I/O流,具體如下:
    FileInputStream openFileInput(String name)打開應用程序的數據文件夾下的name文件對應的數據流
    FileOutputSream openFileOutput(String name, int mode)打開應用程序數據文件夾下的name文件對應的輸出流,mode指定文件打開的模式,該模式主要有一下4種:
    ①MODE_PRIVATE(該文件只能被當前應用程序讀寫)
    ②MODE_APPEND(以追加方式打開,可以在文件中追加內容)
    ③MODE_WORLD_READABLE(該文件內容可以被其他應用程序讀取)
    ④MODE_WORLD_WRITEABLE(該文件內容可以被其他應用程序度,寫)
    讀取文件:
    假設name爲要打開的文件名字
    FileInputStream f = openFileInput(name);
    byte[] buf = new byte[1024];
    int hasRead = 0;
    StringBuilder sb = new StringBuilder("");
    while((hasRead = f.read(buf)>0))
    {
      sb.append(new String(buf, 0 , hasRead));
     }
    f.close();
    獲取文件內容字符串:sb.toString();
    寫文件:
    假設要寫入的字符串爲content
    FileOutputStream f = openFileOutput(name, MODE_APPEND);
    PrintStream temp = new PrintStream(f);
    temp.println(content);
    temp.close();
注:應用程序的數據文件默認保存在/data/datea<package name>/files目錄下,使用openFileInput和openFileOutput方法來打開文件輸入流,輸出流時,打開的都是應用程序的數據文件夾裏的文件,也就是說是在手機內存中的文件,而不是SD卡中的文件。

eclipse導入andriod源碼jar包路徑:

現在我需要導入Setting源碼到eclipse ,導入之後會有很多地方報錯,未能找到相關類,需要我們導入相應jar包,現在我們如何知道需要導入哪些jar包?
路徑:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/下編譯的classes.jar

android:protectionLevel 的修改  例如修改串口權限

一些需要system級別的權限,例如android.permission.SERIAL_PORT  apk必須需要android:sharedUserId="android.uid.system"  的signature纔可以安裝,不然會報錯:  INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,   此時可以修改文件 frameworks/base/core/res/AndroidManifest.xml  把     -        android:protectionLevel="signature|system" /> 修改爲   +        android:protectionLevel="normal" />   然後其他需要SERIAL_PORT權限的apk 就可以直接安裝了

通過包名獲取其他包的Context實例

Context有個createPackageContext方法,可以創建另外一個包的上下文,這個實例不同於它本身的Context實例,但是功能是一樣的。這個方法有兩個參數:
1。packageName  包名,要得到Context的包名
2。flags  標誌位,有CONTEXT_INCLUDE_CODE和CONTEXT_IGNORE_SECURITY兩個選項。CONTEXT_INCLUDE_CODE的意思是包括代碼,也就是說可以執行這個包裏面的代碼。CONTEXT_IGNORE_SECURITY的意思是忽略安全警告,如果不加這個標誌的話,有些功能是用不了的,會出現安全警告。

判斷是否是在漫遊

    private boolean isRoaming() {
        Boolean isRoaming = false;
	  if(mContext == null) return isRoaming;
		
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        isRoaming = (networkInfo != null
                && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE 
                && networkInfo.isRoaming());
        Log.d(TAG, "jimbo---KeyguardStatusView isRoaming " + isRoaming);
        return isRoaming;
    }

android:layout_weight使用

只有在Linearlayout中,該屬性纔有效。之所以Android:layout_weight會引起爭議,是因爲在設置該屬性的同時,設置android:layout_width爲wrap_content和match_parent會造成兩種截然相反的效果

android:layout_weight的真實含義是:一旦View設置了該屬性(假設有效的情況下),那麼該 View的寬度等於原有寬度(android:layout_width)加上剩餘空間的佔比!

設屏幕寬度爲L,在兩個view的寬度都爲match_parent的情況下,原有寬度爲L,兩個的View的寬度都爲L,那麼剩餘寬度爲L-(L+L) = -L, 左邊的View佔比三分之一,所以總寬度是L+(-L)*1/3 = (2/3)L.事實上默認的View的weight這個值爲0,一旦設置了這個值,那麼所在view在繪製的時候執行onMeasure兩次的原因就在這。

Google官方推薦,當使用weight屬性時,將width設爲0dip即可,效果跟設成wrap_content是一樣的。這樣weight就可以理解爲佔比了!

最合理的使用方式:當使用weight屬性時,將width設爲0dip

Android 獲取控件的寬和高/ 如何獲取控件的大小

在onCreate()裏面獲取控件的高度是0,
//------------------------------------------------方法一   自己測量 
int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);  
int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);  
imageView.measure(w, h);  
int height =imageView.getMeasuredHeight();  
int width =imageView.getMeasuredWidth();  
textView.append("\n"+height+","+width);  
  
  
  
  
<div style="text-indent: 28px;"><span style="font-family: Arial, Helvetica, sans-serif;">//-----------------------------------------------方法二 </span><span style="font-family:宋體;color:#333333;"><span style="font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);">  註冊一個ViewTreeObserver的監聽回調,這個監聽回調,就是專門監聽繪圖的,既然是監聽繪圖,那麼我們自然可以獲取測量值了,同時,我們在每次監聽前remove前一次的監聽,避免重複監聽。 </span></span></div>ViewTreeObserver vto = imageView.getViewTreeObserver();  
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {  
    public boolean onPreDraw() {  
<code class="java plain" style="line-height: 15.3999996185303px; font-size: 14px; white-space: pre; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; min-height: inherit !important; background: none !important;"><span style="white-space:pre">	</span>vto.removeOnPreDrawListener(</code><code class="java keyword" style="line-height: 15.3999996185303px; font-size: 14px; white-space: pre; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; font-weight: bold !important; min-height: inherit !important; color: rgb(0, 102, 153) !important; background: none !important;">this</code><code class="java plain" style="line-height: 15.3999996185303px; font-size: 14px; white-space: pre; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; min-height: inherit !important; background: none !important;">);</code>
        int height = imageView.getMeasuredHeight();  
        int width = imageView.getMeasuredWidth();  
        textView.append("\n"+height+","+width);  
        return true;  
    }  
});  
//-----------------------------------------------方法三       <span style="color: rgb(51, 51, 51); font-family: 宋體; font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);">第2個方法基本相同,但他是全局的佈局改變監聽器,所以是最推薦使用的</span>
ViewTreeObserver vto2 = imageView.getViewTreeObserver();    
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {  
    @Override    
    public void onGlobalLayout() {  
        imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);    
        textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth());  
    }    
});    












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章