1. 程式人生 > >android開發——Android開發中的47個小知識

android開發——Android開發中的47個小知識

環境 底部 枚舉 目前 mount ram 啟動 creat ica

1、判斷sd卡是否存在

 boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
 

2、TextView部分文字設置顏色

 TextView tv = new TextView(this);
 //添加css樣式
 tv.setText(Html.fromHtml("<font color="#ff0000">紅色</font>其它顏色"));

3、替換數據庫某字段中某些字符的方法:

 update table set spell=replace(spell,‘ɡ‘,‘g‘)

4、單選按鈕默認選中:

mRadioGroup.check(mRadioButton_1.getId());

下拉列表默認選中:

 for(int j = 0;j < cities.length;j ++){
     if(months[j].equals("默認")){
         mSpinner_m.setSelection(j);
     }
 }

5、TextView中嵌套圖片:

 Drawable draw = getResources().getDrawable(R.drawable.ji_dot_nor);
 textView.setCompoundDrawablesWithIntrinsicBounds(
null, draw, null, null);

6、ListView去掉下拉條:

方法一:在xml屬性中設置

android:scrollbars="none"

方法二:在代碼中設置:

listView.setVerticalScrollBarEnabled(false);

7、設置Activity的風格:

 //將Activity設置成半透明的效果
 android:theme="@android:style/Theme.Translucent"  
 //將Activity設置成對話框的樣式  
 android:theme="@android:style/Theme.Dialog"  <span style="font-family: Arial, Helvetica, sans-serif; white-space: normal; ">  <wbr>  <wbr> </wbr></wbr></span>

8、創建一個背景模糊的Widow,且將對話框放在前景

Window window = dialog.getWindow();
 window.setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

9、list滾動時出現黑色底的問題:

解決方法:
方法一:
在XML中設置

android:cacheColorHint="#00000000"


方法二:
在代碼中設置

listView.setCacheColorHint(0);


10、編輯框中指定輸入的類型,設置屬性digits即可:

例:只允許輸入數字

android:digits="0123456789"  或  android:digits="integer"   或  android:digits="num"

11、利用反射機制,獲取drawable文件夾下的圖片名稱:

 Field[] fields = R.drawable.class.getDeclaredFields();
 for(Field field:fields){
     if(!"icon".equals(field.getName())){
         sb.append(field.getName() + "\t");
     }
 }
 mTextView.setText(sb.toString());

12、緩沖流播放MP3:

MediaPlayer player = new MediaPlayer();
 try {
     player.setDataSource(WebMusic.this, Uri.parse("http://stream15.a8.com/a8space/2010/12/30/2010123002225125942.mp3"));
     player.prepare();
     player.start();
 } catch (IllegalArgumentException e) {
     e.printStackTrace();
 } catch (SecurityException e) {
     e.printStackTrace();
 } catch (IllegalStateException e) {
     e.printStackTrace();
 } catch (IOException e) {
     e.printStackTrace();
 }

13、下面的代碼可以用來點亮屏幕:

 PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
 mWakelock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.SCREEN_DIM_WAKE_LOCK, "SimpleTimer");
 mWakelock.acquire();
 ...............
 mWakelock.release();

下面的代碼用來屏幕解鎖:

 KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
 KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("");
 BkeyguardLock.disableKeyguard();

使用這兩段代碼,需要在AndroidManifest文件中加入以下權限:

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

14、android 跑馬燈效果做如下設置即可:

 android:scrollHorizontally="true"    
 android:marqueeRepeatLimit="marquee_forever"    
 android:ellipsize="marquee"    
 android:focusable="true"    
 android:focusableInTouchMode="true"    
 android:singleLine="true"

15、攔截短信:
當android系統接收到短信時,會發送一個廣播BroadcastReceiver,這個廣播是以有序廣播的形式發送的。
所謂的有序廣播就是廣播發出後,接收者是按照設置的優先級一個一個接著接收,前面的接收者可以選擇是否終止這條廣播以使後面的接收者接收不到,而普遍廣播發送 後所有的接收者都能同時接到,但是不能終止這條廣播,也不能將它的處理結果傳遞給下個接收者。
sms攔截就是通過實現一個BroadcastReceiver並將其的優先級設置的比系統sms接收者高。
android:priority就是設置優先級的,設置為100即可:

  <receiver android:name="InterceptSMS">
     <intent-filter android:priority="100">
         <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
     </intent-filter>
 </receiver>

16、如果在文件夾下選擇視頻文件時,想調用自己的播放器,需要在Manifest.xml中設置過濾器,設置如下:

<intent-filter>
     <action android:name="android.intent.action.VIEW" />
     <category android:name="android.intent.category.DEFAULT"/>
     <data android:mimeType="video/*"/>
 </intent-filter>

如果想在瀏覽器中調用自己的播放器,設置如下:

<intent-filter>
     <action android:name="android.intent.action.VIEW" />
     <category android:name="android.intent.category.DEFAULT"/>
     <category android:name="android.intent.category.BROWSABLE" />
     <data android:mimeType="video/*" android:scheme="http"/>
 </intent-filter>

如果兩者都要實現的話,就必須配兩個過濾器。

17、顯示圖片時,用mImageView.setScaleType(ImageView.ScaleType.FIT_XY); 可以填充整個區域。

18、保持屏幕長開:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);


開啟、關閉屏幕時發送的廣播:

<receiver android:name=".MyBroadcastReceiver" android:enabled="true">                 
     <intent-filter>                       
         <action android:name="android.intent.action.ACTION_SCREEN_ON"></action>                           
         <action android:name="android.intent.action.ACTION_SCREEN_OFF"></action>                 
     </intent-filter>          
 </receiver>

19、判斷一個intent是否可用:

public static boolean isIntentAvailable(Context context, String action) {
     final PackageManager packageManager = context.getPackageManager();
     final Intent intent = new Intent(action);
     List<ResolveInfo> list = packageManager.queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);
     return list.size() > 0;
 }  

上述代碼判斷action的intent是否可用
(備註,也可以得到相應intent的應用程序信息)

我們可以根據scanAvailable 來判斷是否讓用戶操作來發送該intent:

 boolean bool = isIntentAvailable(gallery.this,ACTION);
 if(bool){
     Intent intent = new Intent(ACTION);
     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     startActivity(intent);
 }
 

20、獲取所有桌面應用的圖標:

private List<Drawable> getImage(){
     PackageManager packageManager = this.getPackageManager();
     Intent intent = new Intent(Intent.ACTION_MAIN);
     intent.addCategory(Intent.CATEGORY_LAUNCHER);
     List<ResolveInfo> infos = packageManager.queryIntentActivities(intent, 0);
     for(ResolveInfo info : infos){
         ActivityInfo ai = info.activityInfo;
         Drawable icon = ai.loadIcon(packageManager);
         list.add(icon);
     }
     return list;
 }

21、Android 系統圖片數據庫:

 Uri STORAGE_URI = Images.Media.EXTERNAL_CONTENT_URI;

往改數據庫中插入數據,用到了內容提供者,大致如下:

view plaincopy
 ContentValues values = new ContentValues(11);
 values.put(Images.Media.TITLE, title);
 values.put(Images.Media.DISPLAY_NAME, filename);
 values.put(Images.Media.DATE_TAKEN, dateTaken);
 values.put(Images.Media.DATE_MODIFIED, dateTaken);
 values.put(Images.Media.DATE_ADDED, dateAdded);
 values.put(Images.Media.MIME_TYPE, "image/jpeg");
 values.put(Images.Media.ORIENTATION, degree[0]);
 values.put(Images.Media.DATA, filePath);
 values.put(Images.Media.SIZE, size);
 values.put(Images.Media.LATITUDE, latitude.floatValue());
 values.put(Images.Media.LONGITUDE, longitude.floatValue());
 
 ContentResolver contentResolver = getContentResolver();
 contentResolver.insert(STORAGE_URI, values);
 
 //插入數據後刷新一下:
 getContentResolver().notifyChange(STORAGE_URI, null);

22、獲取UI控件的寬、高:

在前面幾個周期函數中都無法獲取寬度和高度值,但在事件中或用定時器可以獲取,如下:

public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
         
     text = (TextView) findViewById(R.id.text);
     btn = (Button) findViewById(R.id.btn);       
     btn.setOnClickListener(new Button.OnClickListener(){
         @Override
         public void onClick(View v) {
             int width = text.getWidth();
             int height = text.getHeight();
             Log.i("Log: ", "----------->"+width + " | " + height);
         }
     });
 }

23、判斷某一服務是否在運行:

//serviceName:即包名+服務的名稱
 //return:某一服務正在運行,返回true,否則返回false
 public  boolean isRunning(Context c,String serviceName){
     ActivityManager myAM=(ActivityManager)c.getSystemService(Context.ACTIVITY_SERVICE); 
     ArrayList<RunningServiceInfo> runningServices = (ArrayList<RunningServiceInfo>)myAM.getRunningServices(40);
     //獲取最多40個當前正在運行的服務,放進ArrList裏
     for(int i = 0 ; i<runningServices.size();i++){  //循環枚舉對比
         if(runningServices.get(i).service.getClassName().toString().equals(serviceName)){
             return true;
         }
     }
     return false;
 }


24、根據角度求正弦值:

 Math.sin(Math.PI/2)
 
  // 根據正弦值求角度:
   Math.toDegrees(Math.asin(1.0))
 
  //其他求法同上

25、畫圖時,設置畫布抗鋸齒:

 canvas.setDrawFilter(new PaintFlagsDrawFilter(0,Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));

26、讓ListView的滾動條定位到最後一行設置以下兩個屬性:

 android:stackFromBottom="true"
 android:transcriptMode="alwaysScroll"

27、獲取系統所有包的信息:

 List<PackageInfo> pkgs = AndroidDemo.this.getPackageManager().getInstalledPackages(0);
 for (int i=0; i<pkgs.size(); i++) {
     PackageInfo info = new PackageInfo();
     info = pkgs.get(i);
     label = info.applicationInfo.loadLabel(getPackageManager()).toString();
     mPackageInfoList.add(label);
     System.out.println("label----------->" + label);
 }
 

28、如何判斷一個應用是系統應用???

 private boolean isDefaultApplication(String packageName) {   
     boolean flag = false;   
     boolean isDefault = false;   
     PackageManager pckMan = mLauncher.getPackageManager();   
     List<PackageInfo> packs = pckMan.getInstalledPackages(0);   
     int count = packs.size();   
     for (int i = 0; i < count && !flag; i++) {   
         PackageInfo p = packs.get(i);   
         ApplicationInfo appInfo = p.applicationInfo;   
         if (packageName.equals(appInfo.packageName)) {   
             if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) {   
                 isDefault = true;   
             }   
             flag = true;   
         }   
     }   
     return isDefault;   
 }  
 
/*核心判斷:*/
 
 if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0){   
     //系統應用   
 }else{   
     //用戶安裝的   
 } 
 

29、卸載應用:

//包名:package + 具體包路徑
 Uri packageURI = Uri.parse("package:com.android.myapp");   
 Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);   
 startActivity(uninstallIntent);

30、檢查網絡狀態:

//return  true表示有網絡可用,dalse表示無網絡可用
 public static boolean checkNetwork(){
     // 檢查網絡連接,如果無網絡可用,就不需要進行連網操作等    
     final NetworkInfo info = mConnectivity.getActiveNetworkInfo();   
     if (info == null) {      
         return false;     
     }    
     //判斷網絡連接類型,是WIFI網絡還是3G網絡     
     final int netType = info.getType();   
     if (netType == ConnectivityManager.TYPE_WIFI) {   
         return info.isConnected();     
     } else if (netType == ConnectivityManager.TYPE_MOBILE && !mTelephony.isNetworkRoaming()) {
         return info.isConnected();     
     } else {        
         return false;     
     } 
 }

31、獲取本地apk文件的包名:

public void getApkInfo(){
     String apkPath ="/sdcard/JXT_calendar.apk";
     PackageManager pm = GetApkInfo.this.getPackageManager();
     PackageInfo info = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
     if (info != null) {
         ApplicationInfo appInfo = info.applicationInfo;
         Drawable icon = pm.getApplicationIcon(appInfo);
         image.setImageDrawable(icon);
         packageName = appInfo.packageName;
         text.setText("package: " + packageName);
     }
 }

32、捕獲Home鍵,重寫onAttachedToWindow()方法,在方法裏面setType 即可,去掉之後就無法捕獲Home鍵:

 @Override
 public void onAttachedToWindow() {
     // TODO Auto-generated method stub
     this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
     super.onAttachedToWindow();
 }
 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
     // TODO Auto-generated method stub
     if(keyCode == KeyEvent.KEYCODE_HOME) {
         //不做任何操作
     }
     return false;
 }


33、Notification通知如何點擊後自動消失:

代碼中加上notification.flags |= Notification.FLAG_AUTO_CANCEL 即可
Notification通知無清楚按鈕,如音樂播放時的狀態:
代碼中加上notification.flags |= Notification.FLAG_NO_CLEAR 即可

34、橫豎屏切換時候activity的生命周期android:configChanges
不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次
設置Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次
設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命周期,只會執行onConfigurationChanged方法
35、獲取默認的應用圖標:

private PackageManager mPackageManager;
 mPackageManager = getPackageManager();
 Drawable d = mPackageManager.getDefaultActivityIcon();
 Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1),Math.max(d.getIntrinsicHeight(), 1),Bitmap.Config.ARGB_8888);
 

36、優化Dalvik虛擬機的堆內存分配:

對於Android平臺來說,其托管層使用的Dalvik Java VM從目前的表現來看還有很多地方可以優化處理,比如我們在開發一些大型遊戲或耗資源的應用中可能考慮手動幹涉GC處理,
使用dalvik.system.VMRuntime類提供的setTargetHeapUtilization方法可以增強程序堆內存的處理效率。當然具體原理我們可以參考開源工程,這裏我們僅說下使用方法:

 view plaincopy
 private final static float TARGET_HEAP_UTILIZATION = 0.75f; 

在程序onCreate時調用一下代碼即可:

 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 

Android堆內存也可自己定義大小:

 //設置最小heap內存為6MB大小。當然對於內存吃緊來說還可以通過手動幹涉GC去處理
 VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); 
 // 查看剩余的內存容量。
 Runtime.getRuntime().freeMemory();

37、PopupWindow 的使用:
顯示PopupWindow 的代碼如下:

public void showPopupWindow(){
     //獲取上下文環境
     Context context = PopupWindowCalendar.this;
     //獲取系統服務
     LayoutInflater fliter = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
     //加載自定義的布局文件date_layout.xml
     View calendarWindow = fliter.inflate(R.layout.date_popup, null);
     //new 一個PopupWindow ,參數一:將加載的布局放在PopupWindow中顯示;參數二:設置寬度;參數三:設置高度;參數四:獲取焦點
     final PopupWindow popupWindow = new PopupWindow(calendarWindow, LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
     //設置背景(此處設置是當點擊PopupWindow之外的區域或按back鍵時隱藏該PopupWindow)
     ColorDrawable dw = new ColorDrawable(-00000);
     popupWindow.setBackgroundDrawable(dw);
     //顯示PopupWindow的位置,參數一:父親的view,即底層Activity根布局的id;參數二:顯示的位置,如左上角;參數三:在參數二的基礎上x、y坐標的偏移
     popupWindow.showAtLocation(findViewById(R.id.main), Gravity.LEFT|Gravity.TOP, 150, 200);
 }
 
//隱藏PopupWindow 的代碼:
 
 popupWindow.dismiss();

38、Android ListView的美化方法:

listview在拖動的時候背景圖片消失變成黑色背景。等到拖動完畢我們自己的背景圖片才顯示出來
代碼結解決

android:scrollingCache=”false”

listview的上邊和下邊有黑色的陰影
代碼解決

android:fadingEdge=”none”

listview的每一項之間需要設置一個圖片做為間隔
代碼解決:

android:divider=”@drawable/list_driver”

其中 @drawable/list_driver 是一個圖片資源
自定義listview的時候,會出現下面選中一個空間黑色底色的情況,破壞整體美觀度
代碼解決:

android:cacheColorHint=“#00000000”

默認顯示選中的item為橙黃底色,有時候我們需要去掉這種效果
代碼解決:android:listSelector屬性.
39、
在AndroidManifest.xml文件中設置android:launchMode="singleInstance" ,可以保證棧中每個Activity只有一個實例,防止重復界面的不斷加載。
單純的跳轉頁面時是可以處理的,但是跳轉界面需要傳值時就會出問題,這樣處理只會將後臺的Activity啟動,傳遞的值是無法獲取並重新加載的,
如:ActivityA ——> ActivityB ——(搜索關鍵字)——> ActivityA (當我從ActivityB傳遞關鍵字到ActivityA時,只是將棧底的ActivityA放在了棧頂,並不會做其他操作)
如果既要保證每個Activity只有一個實例,又可以傳遞數據,可以在跳轉界面的代碼處加上下面一句話:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
這樣處理,就是在跳轉的時候將堆棧中該Activity前面的所有Activity都清除,並重新發intent將此Activity啟動,因此就可以獲取傳遞過來的數據進行相關處理。
40、線程問題:

The content of the adapter has changed but ListView did not receive a notification.
Make sure the content of your adapter is not modified from a background thread, but only from the UI thread。
解決問題的方法:

這個錯誤經常出現在Activity休眠起來之後,主要還是使用adapter不太小心造成的,有時候我們獲取數據都使用後臺線程操作,
當Activity休眠時,後臺線程還在運行,喚醒Activity時再次操作該數據就會報這個錯,原因就是數據在後臺改變了但界面沒有刷新。
Activity從休眠狀態被喚醒時會調用onResume()方法,我們可以在onResume()方法中進行數據的刷新notifyDataSetChanged,如下操作

@Override
 protected void onResume() {
     super.onResume();
     Log.e("onResume", "------------>onResume");
     //這個錯誤經常出現在Activity休眠起來之後,休眠起來時會調用onResume(),調notifyDataSetChanged可以解決改問題
     if(securitiesAdapter != null){
         securitiesAdapter.notifyDataSetChanged();
     }
 }
 

41、保留小數點後兩位:

 DecimalFormat formater = new DecimalFormat("#0.##");
 System.out.println(formater.format(123456.7897456));
 

42、判斷耳機狀態:

 public class ServiceReceiver extends BroadcastReceiver {
     public void onReceive(Context context, Intent intent) {
         if (Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) {
             try {
                 if (intent.getIntExtra("state", 0) == 0) {
                     Log.e("caculate broadcast", "headset off");
                     bHeadsetOn = false;
                 } else if (intent.getIntExtra("state", 0) == 1) {
                     Log.e("headset", "headset on");
                     bHeadsetOn = true;
                 }
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }
 }

43、異步任務調用時,先判斷是否在運行,如果正在運行,則先取消該任務,然後再開啟

if(searchTask.getStatus() == AsyncTask.Status.RUNNING){
     searchTask.cancel(true);
 }
 searchTask = new SearchTask();
 searchByKey(sSearchKey);
 

44、黑屏後音頻播放會有停頓的問題:

PowerManager mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);
 PowerManager.WakeLock mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "media");
 //播放時:
 
 if (!mWakeLock.isHeld()){
     mWakeLock.acquire();
 }
// 停止時:
 
 if (mWakeLock.isHeld()){
     mWakeLock.release();
 }
 

權限:

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

45、當ViewFlipper 與touch 事件沖突時,ViewFlipper的滑屏事件會被touch 事件攔截,解決方法如下:

 public boolean onTouchEvent(MotionEvent event) {
     // 執行touch 事件
     super.onTouchEvent(event);
     return this.detector.onTouchEvent(event);
 }
 //這個方法會先執行,當返回為true時,才執行onTouchEvent 方法
 public boolean dispatchTouchEvent(MotionEvent ev){
     //先執行滑屏事件
     detector.onTouchEvent(ev);
     super.dispatchTouchEvent(ev);
     return true;
 }

46、
查詢圖片,Uri地址為:MediaStore.Images.Media.EXTERNAL_CONTENT_URI

查詢音樂,Uri地址為:MediaStore.Audio.Media.EXTERNAL_CONTENT_URI

47、
TextView底部加橫線:

 mTextView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG|Paint.ANTI_ALIAS_FLAG);
 //TextView中間加橫線:
 
 mTextView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG|Paint.ANTI_ALIAS_FLAG);

android開發——Android開發中的47個小知識