Android一些經常使用知識和代碼(不斷更新)

1.如何調用外部圖片選擇器,選擇圖片並返回結果javascript

                //獲取照片
                Intent in = new Intent(Intent.ACTION_GET_CONTENT);
                in.setType("image/*");
                startActivityForResult(in, 0);html

而後Activity中還要加上一個結果返回接收java

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent intent)
    {
        super.onActivityResult(requestCode, resultCode, intent);

        System.out.println(intent.getDataString());
        ImageView view = new ImageView(this);
        view.setImageURI(intent.getData());
        ((LinearLayout)findViewById(R.id.layout)).addView(view);
        
        System.out.println(requestCode);
    }android


2.如何調用Google Web Search?
其實android提供了一個很方便的調用方式,就是用Intent去調用系統的Activity,代碼以下:web

                //搜索
                Intent search = new Intent(Intent.ACTION_WEB_SEARCH);
                search.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                search.putExtra(SearchManager.QUERY, "tigertian");
                final Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
                if (appData != null) {
                    search.putExtra(SearchManager.APP_DATA, appData);
                }
                
                startActivity(search);數據庫

執行這段代碼以後,就會跳轉到google的網站並自動搜索與tigertian相關的記錄

3.爲何WebView在進行loadUrl的時候,有時候會彈出Android的自帶瀏覽器進行瀏覽?
被訪問頁面若是不帶跳轉(Redirect)是不會彈出自帶瀏覽器的。但若是帶跳轉(Redirect)的話WebView是作不到的,因此他會調用相應的瀏覽器進行跳轉訪問。

4.有按鈕的列表項爲能夠點擊嗎?
能夠,可是須要將按鈕的Focusable屬性置爲false,Checkbox等控件同理。 

5.android:layout_weight什麼時候有效果?
 <AutoCompleteTextView android:layout_height="wrap_content"  android:layout_weight="2"
   android:layout_width="wrap_content" android:completionThreshold="1"
   android:id="@+id/AutoCompleteSearchGame"></AutoCompleteTextView>
當layout_height和layout_width都未wrap_content的時候有效果。 

六、若是調用瀏覽器?
使用startActivity傳遞這個intent就能夠調用瀏覽器了new Intent(Intent.ACTION_VIEW, Uri.parse(url)) 瀏覽器

 

讀取全部電話號碼:緩存

  1、PhoneLookup.CONTENT_FILTER_URI的通常用法網絡

 Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
 resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...多線程

    API見這裏。若是直接以下使用PhoneLookup.CONTENT_FILTER_URI會報IllegalArgument Exception錯

getContentResolver().query(PhoneLookup.CONTENT_FILTER_URI,...

 

  2、 技巧用法

        Cursor c = getContentResolver().query(Uri.withAppendedPath(
                PhoneLookup.CONTENT_FILTER_URI, "*"), new String[] {
                PhoneLookup._ID,
                PhoneLookup.NUMBER,
                PhoneLookup.DISPLAY_NAME,
                PhoneLookup.TYPE, PhoneLookup.LABEL }, null, null, sortOrder);

    關鍵是這個"*",這樣就能取到全部的號碼以及相關的聯繫人的姓名以及其餘相關字段,比經過聯繫人再查找其號碼要方便不少。

Android ListView item中有按鈕(Button)不能點擊或者條目不能點擊的問題:

增長了按鈕以後,列表條目不能點擊的緣由是:須要把Button的相關屬性設置成這樣

android:focusable="false"

不過在開發過程當中,我有個動態獲取圖片並刷新列表的機制,發現每次調用完notifyDataSetChanged()方法以後Button都不能點擊了,後來發現若是有圖片動態加載那麼每次都要從新inflate整個列表的條目,因此我乾脆重載了notifyDataSetChanged()方法。

    /**
     * Recycle bitmap resources
     */
    public void recycleBitmapRes() {
        if (mConvertViews != null && !mConvertViews.isEmpty()) {
            Collection<View> views = mConvertViews.values();
            mConvertViews.clear();
            for (View view : views) {
                ImageView icon = (ImageView) view.findViewById(R.id.imgIcon);
                if (icon != null) {
                    if (icon.getDrawable() != null && icon.getDrawable() instanceof BitmapDrawable) {
                        Bitmap bitmap = ((BitmapDrawable) icon.getDrawable()).getBitmap();
                        if (bitmap != null && !bitmap.isRecycled()) {
                            bitmap.recycle();
                        }
                    }
                }
            }
        }
    }

    @Override
    public void notifyDataSetChanged(){
        //Avoiding that buttons cannot be pressed
        Utils.LogI("GameListAdapter", "notifyDataSetChanged");
        recycleBitmapRes();
        super.notifyDataSetChanged();
    }

 

 

Android彈出撥號界面和撥打電話實現:

須要使用反射機制將ITelephony反射出來進行操做。

private void dial(String number) {
        Class<TelephonyManager> c = TelephonyManager.class;
        Method getITelephonyMethod = null;
        try {
            getITelephonyMethod = c.getDeclaredMethod("getITelephony",
                    (Class[]) null);
            getITelephonyMethod.setAccessible(true);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            TelephonyManager tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            Object iTelephony;
            iTelephony = (Object) getITelephonyMethod.invoke(tManager,(Object[]) null);
            Method dial = iTelephony.getClass().getDeclaredMethod("dial", String.class);
            dial.invoke(iTelephony, number);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    private void call(String number) {
        Class<TelephonyManager> c = TelephonyManager.class;
        Method getITelephonyMethod = null;
        try {
            getITelephonyMethod = c.getDeclaredMethod("getITelephony",
                    (Class[]) null);
            getITelephonyMethod.setAccessible(true);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            TelephonyManager tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            Object iTelephony;
            iTelephony = (Object) getITelephonyMethod.invoke(tManager,(Object[]) null);
            Method dial = iTelephony.getClass().getDeclaredMethod("call", String.class);
            dial.invoke(iTelephony, number);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 

Android中短信攔截解決方案

通過測試,Android中是能夠攔截短信的,解決方案以下:

package com.tigertian.sms;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;

public class SMSReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("SMSReceiver, isOrderedBroadcast()="
                + isOrderedBroadcast());
        
        Bundle bundle = intent.getExtras();
        Object messages[] = (Object[]) bundle.get("pdus");
        SmsMessage smsMessage[] = new SmsMessage[messages.length];
        for (int n = 0; n < messages.length; n++) {
            smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
            if(smsMessage[n].getMessageBody().contains("hahaha")){
                this.abortBroadcast();
            }
            System.out.println(smsMessage[n].getOriginatingAddress()+" "+smsMessage[n].getMessageBody()+" "+smsMessage[n].getIndexOnIcc());
        }
    }}

   <receiver android:name=".SMSReceiver">
            <intent-filter android:priority="10000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

上面的代碼是一個消息監聽,監聽接收短信的消息。咱們能夠從控制檯打印信息裏面看到,他是一個OrderedBroadcast,根據這一點咱們就能夠對短信機制進行攔截。如何攔截呢?首先要聲明一個消息監聽器,同時根據上面的配置文件須要在AndroidManifest.xml中配置好,注意它的優先級是10000,這一點很關鍵,由於OrderedBroadcast是根據優先級來傳遞消息的,優先級越高越先獲取到消息,待處理完後纔會傳遞給下一個監聽器,若是當前監聽器退出廣播,那麼後面的全部監聽器都將沒法收到消息。其次咱們須要實現onReceive方法,根據上面的代碼,咱們能夠從bundle中拿到短信內容並還原成SmsMessage,這樣咱們能夠根據特定條件來判斷哪些是須要咱們攔截而且不要讓用戶知道的,哪些是咱們能夠放行的。須要咱們攔截的短信,咱們能夠在收到後直接abortBroadcast()(上面的代碼中是判斷當短信內容包含hahaha的時候直接攔截),這樣系統收件箱將沒法接收到該條短信,繼而也就不會有notification去通知用戶。至此,應用編寫好以後,短信攔截功能就完成了,固然基於此還能夠作一些其餘功能,這方面就看需求了。注意,優先級相同,則根據包名依次傳遞廣播。想刪除收件箱中已存在的短信,請參考Android源碼SmsProvider類,能夠在你的應用中使用ContentProvider機制進行操做。

Application保存全局變量

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    
  }
}

 

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

 

 

android異步圖片加載中的圖片緩存:

讀取大文件流的問題:緩存
開多線程把圖片從網絡上蕩下來之後,首先緩存至本地文件夾 //android.content.ContextWrapper.getCacheDir() android系統提供的一個存放和獲得緩存文件夾的方法
而後對文件全路徑截取後綴以前的內容進行MD5加密並與後綴拼成一個文件名,根據這個文件名和傳入的路徑構建一個文件 寫一個緩存方法  判斷是否存在緩存文件
若是是則返回加密後文件的Uri,若是不是則從網上下載文件並返回文件的Uri.作緩存的目的是用緩存的文件,而Uri就能夠惟一標識一個文件。
public static Uri cacheFile(String path,File saveDir)throws Exception{  

  File file = new File(saveDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf('.')));
    if(file.exists()){
        return Uri.fromFile(file);    
    }else{
        FileOutputStream outStream = new FileOutputStream(file);
        HttpURLConnection conn = (HttpURLConnection)new URL(path).openConnection();
        conn.setConnectTimeout(5 * 1000);
        conn.setRequestMethod("GET");
        if(conn.getResponseCode()==200){
            InputStream inStream = conn.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while( (len = inStream.read(buffer)) !=-1 ){
                outStream.write(buffer, 0, len);
            }
            outStream.close();
            inStream.close();
            return Uri.fromFile(file);
        }else{
            throw new Exception("文件下載失敗!");
        }
    }
}

視頻格式的壓縮

l  source=source.avi

l  ffmpeg -t 600 -i $source -acodec libfaac -ab 128k -ac 2 -vcodec libx264 \

l  -vpre hq -crf 22 -threads 0 tmp.mp4 && \

l  /usr/bin/MP4Box -3gp -mtu 1450 -hint tmp.mp4 -out target.mp4

插入刪除圖片MediaScanner緩存問題

插入圖片
當你打算在刪掉時 : ContentValues values = new ContentValues();  

 values.put(Images.Media.TITLE, filename);

    values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());

    values.put(Images.Media.MIME_TYPE, "image/jpeg");

    Uri uri = this.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);

File f = new File(imageURI);

    f.delete();

在gallery中就會出現佔位符 主要是由於MediaScanner有一個緩存

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

 

 

AndroidManifest.xml:

<intent-filter>

  <action android:name="android.intent.action.MEDIA_MOUNTED" />

  <data android:scheme="file" />

</intent-filter>

 

屏幕旋轉的設置:

1.   @Override  

2.       public void onConfigurationChanged(Configuration newConfig) {  

3.           super.onConfigurationChanged(newConfig);    

4.           ImageView header = (ImageView) this.findViewById(R.id.header);    

5.           if ( newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ) {  

6.                header.setImageResource(R.drawable.header480);  

7.           }  

8.           else if ( newConfig.orientation == Configuration.ORIENTATION_PORTRAIT ) {  

9.               header.setImageResource(R.drawable.header320);    

10.         }  

11.     }  

 

ListView適配器getView()優化

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);   //設置標記
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
static class ViewHolder {
TextView text;
ImageView icon;
}
android ListView幾個比較特別的屬性:

首先是stackFromBottom屬性,這隻該屬性以後你作好的列表就會顯示你列表的最下面,值爲true和false

android:stackFromBottom="true"            

第二是transciptMode屬性,須要用ListView或者其它顯示大量Items的控件實時跟蹤或者查看信息,而且但願最新的條目能夠自動滾動到可視範圍內。經過設置的控件transcriptMode屬性能夠將Android平臺的控件(支持ScrollBar)自動滑動到最底部。

 android:transcriptMode="alwaysScroll"   

第三cacheColorHint屬性,不少人但願可以改變一下它的背景,使他可以符合總體的UI設計,改變背景背很簡單隻須要準備一張圖片而後指定屬性 android:background="@drawable/bg",不過不要高興地太早,當你這麼作之後,發現背景是變了,可是當你拖動,或者點擊list空白位置的時候發現ListItem都變成黑色的了,破壞了總體效果。

若是你只是換背景的顏色的話,能夠直接指定android:cacheColorHint爲你所要的顏色,若是你是用圖片作背景的話,那也只要將android:cacheColorHint指定爲透明(#00000000)就能夠了

第四divider屬性,該屬性做用是每一項之間須要設置一個圖片作爲間隔,或是去掉item之間的分割線

 android:divider="@drawable/list_driver"  其中  @drawable/list_driver 是一個圖片資源,若是不想顯示分割線則只要設置爲android:divider="@drawable/@null" 就能夠了

第五fadingEdge屬性,上邊和下邊有黑色的陰影

android:fadingEdge="none" 設置後沒有陰影了~

 第五scrollbars屬性,做用是隱藏listView的滾動條,

android:scrollbars="none"與setVerticalScrollBarEnabled(true);的效果是同樣的,不活動的時候隱藏,活動的時候也隱藏

第六fadeScrollbars屬性,android:fadeScrollbars="true"  配置ListView佈局的時候,設置這個屬性爲true就能夠實現滾動條的自動隱藏和顯示。

 

 

java和javascript互相調用

 mWebView = (WebView) findViewById(R.id.webview);  

        WebSettings mWebSettings = mWebView.getSettings();  

        //加上這句話才能使用javascript方法  

        mWebSettings.setJavaScriptEnabled(true);  

        //增長接口方法,讓html頁面調用  

        mWebView.addJavascriptInterface(new Object() {  

            //這裏我定義了一個撥打電話應用的方法  

            public void callPhone() {

               Uri uri= Uri.parse("tel:12345");

                Intent mIntent = new Intent(Intent.ACTION_CALL,uri);   

                startActivity(mIntent);  

            }  

        }, "demo");  

        //加載頁面  

        mWebView.loadUrl("file:///android_asset/demo.html");  

        mButton = (Button) findViewById(R.id.button);  

        //給button添加事件響應,執行JavaScript的fillContent()方法  

        mButton.setOnClickListener(new Button.OnClickListener() {  

            public void onClick(View v) {  

                mWebView.loadUrl("javascript:fillContent()");  

            }  

});  

<html>  

<head>

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

</head>

    <script> 

        function fillContent(){  

            document.getElementById("content").innerHTML =   

                 "java調用javascript哈哈,這些話是javascript搞出來的";  

        }         

</script>    

<body>  

    <p><a onClick="window.demo.callPhone()" href="">打電話</a></p>  

    <p id="content"></p>  

    <p>java和javascript相互調用</p>  

</body>  

</html>

 

 

 

1.每次啓動新的Activity的時候,輸入法老是彈出來,太煩人了。  

主要緣由就是頁面上方有個EditTexit,每次都自動獲取焦點。  

注意要求是:每次啓動新的Activity的時候,EditTexit不要獲取到焦點或者獲取到焦點也不讓輸入法彈出來,並非阻止輸入法使用。只要第一次啓動的時候別彈出來就好了,若是主動點到EditTexit的時候輸入法仍是得正常的彈出來的  

解決:  
在OnCreate方法裏面加下面這句代碼  
// 隱藏軟鍵盤  
Java代碼    收藏代碼
  1. getWindow().setSoftInputMode(  
  2.                 WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);   


2.在editText中輸入完之後,旁邊有個send 按鈕,當點擊send button 關閉軟鍵盤,再次輸入的時候再彈出來。  
解決:  
Java代碼    收藏代碼
  1. // close input method after send  
  2. final InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);       
  3. imm.hideSoftInputFromWindow(contentTextEdit.getWindowToken(), 0);   

 

Android應用如何實現換主題功能:   

假設一個簡單的場景:有2套主題,一套綠色,一套黑色的。應用界面就一個按鈕,每點擊一下,按鈕和背景都切換爲不一樣的主題,如當前爲黑色主題,下一次就爲綠色主題,再下一次爲黑色,以此類推。

打開Eclipse,新建三個Android工程項目,名字分別爲BlackSkin、GreenSkin和MainSkin。BlackSkin和GreenSkin分別對應黑色、綠色主題資源,MainSkin爲主應用。

BlackSkin
該工程下沒有任何代碼,只是在res\drawable目錄下放置2張圖片,一張黑色的背景,一張黑色的按鈕圖片。接着修改AndroidManifest.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="net.toeach.blackskin"
android:sharedUserId="net.toeach.MainSkin">

<uses-sdk android:minSdkVersion="3" />

</manifest>













GreenSkin
與BlackSkin項目同樣,該工程下也沒有任何代碼,只是在res\drawable目錄下放置2張圖片,一張綠色的背景,一張綠色的按鈕圖片。接着修改AndroidManifest.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="net.toeach.greenskin"
android:sharedUserId="net.toeach.mainskin">

<uses-sdk android:minSdkVersion="3" />

</manifest>















咱們知道Android給每一個APK進程分配一個單獨的用戶空間,其manifest中的userid就是對應一個Linux用戶的(Android 系統是基於Linux)。因此不一樣APK(用戶)間互相訪問數據默認是禁止的,可是它也提供了2種APK間共享數據的形式:
1. Share Preference. / Content Provider
APK能夠指定接口和數據給任何其餘APK讀取,須要本身實現接口和Share的數據.

2. Shared User id
經過Shared User id,擁有同一個User id的多個APK能夠配置成運行在同一個進程中。因此默認就是能夠互相訪問任意數據。也能夠配置成運行成不一樣的進程,同時能夠訪問其餘APK的數據目錄下的數據庫和文件。就像訪問本程序的數據同樣。本文中的換主題功能就是經過這種方式來實現的。

MainSkin
該工程爲主應用,咱們新創建一個Activity類,叫MainActivity.java。代碼以下:

public class MainActivity extends Activity {
private LinearLayout showBg;
private Button btn;
private Context greenSkinContext = null;
private Context blackSkinContext = null;
int flag = 0;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
greenSkinContext = this.createPackageContext("net.toeach.greenskin", Context.CONTEXT_IGNORE_SECURITY);
blackSkinContext = this.createPackageContext("net.toeach.blackskin", Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
e.printStackTrace();
}

showBg = (LinearLayout) findViewById(R.id.linear_layout_1);
btn = (Button) findViewById(R.id.btn_change_skin);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (flag == 0) {
//訪問GreenSkin下的資源
showBg.setBackgroundDrawable(greenSkinContext.getResources().getDrawable(R.drawable.bg));
btn.setBackgroundDrawable(greenSkinContext.getResources().getDrawable(R.drawable.btn_normal));
flag = 1;
} else if (flag == 1) {
//訪問BlackSkin下的資源
showBg.setBackgroundDrawable(blackSkinContext.getResources().getDrawable(R.drawable.bg)); btn.setBackgroundDrawable(blackSkinContext.getResources().getDrawable(R.drawable.btn_normal)); flag = 0; }//end of if }); }//end of method }//end of class

相關文章
相關標籤/搜索