[Android] 開發一款軟件我學到了些什麼?

子曰:學而時習之,不亦說乎

是啊,學習了要經常溫習才行;尤記得大一大二的時候自己愛上了編程;那時的我在地攤上買了一本ASP動態網站編程,還記得花了5塊錢。
而後的日子我把那本書翻的幾乎成了一張張的樣子;然後結合老師講的HTML語法;自己就慢慢的搗鼓了一個班級網站出來;想想心裏還是挺激動的。
這麼久過去了,VBScript 的知識忘得差不多了;以後找個機會再看看。這次寫這個是爲了記錄下我最近接手的一個項目中遇到的一些第一次遇到的問題或者疑惑吧。
由於項目還沒有完,所以持續更新...
========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41849241
========================================================

讀取瀏覽器歷史記錄

<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
{	
    String string = null;
    ContentResolver contentResolver = getContentResolver();
    Cursor cursor = contentResolver.query(Uri.parse("content://browser/bookmarks"), new String[]{"url"}, null, null, null);
    while (cursor != null && cursor.moveToNext()) {
    string = cursor.getString(cursor.getColumnIndex("url"));
        Log.d("debug", string == null ? "null":string);
}

模擬返回鍵功能

1.java.lang.Runtime
Runtime runtime = Runtime.getRuntime();
runtime.exec("input keyevent " + KeyEvent.KEYCODE_BACK);
2.android.app.Instrumentation
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

監聽開機啓動廣播

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            do...
        }
    }
}
<receiver android:name=".BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

判斷移動網絡類型

    /**
     * 判斷移動網絡類型
     *
     * @param networkType telephonyManager.getNetworkType()
     * @return 網絡類型
     */
    static int getMobileNetworkType(int networkType) {
        /*
        GPRS       2G(2.5) General Packet Radia Service 114kbps
        EDGE       2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
        UMTS      3G WCDMA 聯通3G Universal Mobile Telecommunication System 完整的3G移動通信技術標準
        CDMA     2G 電信 Code Division Multiple Access 碼分多址
        EVDO_0   3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 屬於3G
        EVDO_A  3G 1.8mbps - 3.1mbps 屬於3G過渡,3.5G
        1xRTT      2G CDMA2000 1xRTT (RTT - 無線電傳輸技術) 144kbps 2G的過渡,
                HSDPA    3.5G 高速下行分組接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
        HSUPA    3.5G High Speed Uplink Packet Access 高速上行鏈路分組接入 1.4 - 5.8 mbps
        HSPA      3G (分HSDPA,HSUPA) High Speed Packet Access
        IDEN      2G Integrated Dispatch Enhanced Networks 集成數字增強型網絡 (屬於2G,來自維基百科)
        EVDO_B 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
        LTE        4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G過渡,升級版 LTE Advanced 纔是4G
        EHRPD  3G CDMA2000向LTE 4G的中間產物 Evolved High Rate Packet Data HRPD的升級
        HSPAP  3G HSPAP 比 HSDPA 快些
        */
        switch (networkType) {
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_CDMA:
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:
                return Note.NETWORK_TYPE_2G;
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                return Note.NETWORK_TYPE_3G;
            case TelephonyManager.NETWORK_TYPE_LTE:
                return Note.NETWORK_TYPE_4G;
            default:
                return Note.NETWORK_TYPE_UNKNOWN;
        }
    }

讀取通話記錄

final Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, new String[] {
CallLog.Calls.NUMBER, CallLog.Calls.CACHED_NAME,
CallLog.Calls.TYPE, CallLog.Calls.DATE }, null, null,
CallLog.Calls.DEFAULT_SORT_ORDER);
final Cursor cursor = cr.query(數據庫表名,取得的數據數組(裏邊包含字段名稱),條件,參數組,排序等信息) //這就相當於一條SQL語句//取得所有通話信息  這裏邊稍微有點複雜
for (int i = 0; i < cursor.getCount(); i++) {
    cursor.moveToPosition(i);
    str = cursor.getString(0);
    type = cursor.getInt(2);
    if (type == 3) {
    tel = str;
    break;
    }
} //取得值
final Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, new String[] {
CallLog.Calls.NUMBER }, "type=3", null,
"date desc limit 1");
//這個就是取得最近的一次未接來電的電話號碼。
if(cursor.moveToFirst()){
    tel = cursor.getString(0);
}
這個取值之後和最上邊的值是一樣的。
CallLog.Calls.CONTENT_URI (通話記錄數據庫)
CallLog.Calls.NUMBER (通話號碼)
CallLog.Calls.CACHED_NAME (通話人姓名)
CallLog.Calls.TYPE (通話類型)
呼叫記錄有三種類型:
       來電:CallLog.Calls.INCOMING_TYPE (常量值:1)
       已撥:CallLog.Calls.OUTGOING_TYPE(常量值:2)
       未接:CallLog.Calls.MISSED_TYPE(常量值:3)
       其實還有一種類型-拒接 系統未給出常量。但經測試後得出結論爲4.
CallLog.Calls.DATE (通話時間)

 CallLog.Calls.CONTENT_URI : 等價於:Uri.parse("content://call_log/calls");
            //過濾未接電話
            //通話時長0~11秒
            //時間爲:開始響鈴~結束時間
            String whereStr = CallLog.Calls.TYPE + "!=3 AND " + CallLog.Calls.DURATION + ">0 AND " + CallLog.Calls.DURATION + "<11 AND " + CallLog.Calls.DATE + ">" + startTime + " AND " + CallLog.Calls.DATE + "<" + endTime;
            //倒敘並查詢
            Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, new String[]{CallLog.Calls.NUMBER}, whereStr, null, null);
            bFlag = cursor.getCount() > 0;
            cursor.close();
需要聲明的權限 在AndroidManifest.xml中加入
        <uses-permission android:name="android.permission.READ_CONTACTS" /> 讀記錄
        <uses-permission android:name="android.permission.WRITE_CONTACTS" /> 寫記錄
這兩條是和<application>節點同級的 如果想加入呼叫權限,還要加上
     <uses-permission android:name="android.permission.CALL_PHONE" />
還有發送短信權限
     <uses-permission android:name="android.permission.SEND_SMS" />
還有連接互聯網權限
     <uses-permission android:name="android.permission.INTERNET" />

再次點擊返回鍵退出程序

    // 複寫返回事件
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if ((System.currentTimeMillis() - mExitTime) > 2000) {
                Toast.makeText(this, R.string.label_press_main, Toast.LENGTH_SHORT).show();
                mExitTime = System.currentTimeMillis();
            } else {
                finish();
            }
            return true;
        } else
            return super.onKeyDown(keyCode, event);
    }

ActiveAndroid 與 Gson 衝突

問題描述:ActiveAndroid  Model 中無法通過 Gson 進行實例化,原因是 ActiveAndroid  Model 中含有無法通過 Gson 轉換的字段;

解決方案:在 ActiveAndroid  Model 中對指定的類進行過濾:
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
/**
 * Created by QiuJu
 * on 2014/9/16.
 */
public class SpecificClassExclusionStrategy implements ExclusionStrategy {
    private final Class<?> excludedThisClass;
    private final Class<?> excludedThisClassFields;
    /**
     * 過濾器初始化
     *
     * @param excludedThisClass       該類和繼承自該類的對象實例將被忽略
     * @param excludedThisClassFields 該類的屬性將不被序列化
     */
    public SpecificClassExclusionStrategy(Class<?> excludedThisClass, Class<?> excludedThisClassFields) {
        this.excludedThisClass = excludedThisClass;
        this.excludedThisClassFields = excludedThisClassFields;
    }
    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return clazz != null && (clazz.equals(excludedThisClass) || shouldSkipClass(clazz.getSuperclass()));
    }
    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getDeclaringClass().equals(excludedThisClassFields);
    }
}
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setExclusionStrategies(new SpecificClassExclusionStrategy(null, Model.class));
        gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Gson gson = gsonBuilder.create();
        NotePutModel model = new NotePutModel();
        model.setPhoneId(Settings.getPhoneId());
        model.setPhoneMark(Settings.getPhoneMark());
        model.setNotes(Note.getAll(false));
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(gson.toJson(model));
        } catch (JSONException e) {
            e.printStackTrace();
        }

獲取基站信息

    public static String getCellPos(TelephonyManager mTelephonyManager) {
        String result = null;
        try {
            // 返回值MCC + MNC
            String operator = mTelephonyManager.getNetworkOperator();
            if (operator != null && operator.length() > 0) {
                int mcc = Integer.parseInt(operator.substring(0, 3));
                int mnc = Integer.parseInt(operator.substring(3));
                // 中國移動和中國聯通獲取LAC、CID的方式
                GsmCellLocation location = (GsmCellLocation) mTelephonyManager.getCellLocation();
                int lac = location.getLac();
                int cellId = location.getCid();
                result = " MCC = " + mcc + "\t MNC = " + mnc + "\t LAC = " + lac + "\t CID = " + cellId;
                // 中國電信獲取LAC、CID的方式
                /*CdmaCellLocation location1 = (CdmaCellLocation) mTelephonyManager.getCellLocation();
                lac = location1.getNetworkId();
                cellId = location1.getBaseStationId();
                cellId /= 16;*/
                // 獲取鄰區基站信息
                List<NeighboringCellInfo> infos = mTelephonyManager.getNeighboringCellInfo();
                StringBuilder sb = new StringBuilder("Size: " + infos.size() + "\n");
                for (NeighboringCellInfo info1 : infos) { // 根據鄰區總數進行循環
                    sb.append(" LAC : ").append(info1.getLac()); // 取出當前鄰區的LAC
                    sb.append(" CID : ").append(info1.getCid()); // 取出當前鄰區的CID
                    sb.append(" BSSS : ").append(-113 + 2 * info1.getRssi()).append("\n"); // 獲取鄰區基站信號強度
                }
                result += " Neighbor:" + sb.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

Java Android Date Gson Json 解析字符串String時間中含有 T 報錯的問題:

問題描述:時間字符串中含有“T”字符,無法進行對應的格式化。出現:ParseException: unparseable date 
界面方案:設置格式串: “yyyy-MM-dd'T'HH:mm:ss“


   public static Gson getNoteReplyGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setExclusionStrategies(new SpecificClassExclusionStrategy(null, Model.class));
        gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        return gsonBuilder.create();
    }

百度定位問題

問題描述:在使用百度定位的時候出現,調用 LocationClient.start() 後返回 False 且,不回調回調函數;但是在有一部手機上能正常使用。
解決辦法:將默認的 JNI(armeabi) 文件,拷貝爲全平臺。

附上獲取百度地圖的一個封裝類:
class LocationBuilder implements BDLocationListener {
    CountDownLatch mLatch;
    LocationClient mClient;
    Location mLocation;
    public LocationBuilder(final Context context) {
        this.mLatch = new CountDownLatch(1);
        this.mLocation = new Location();
        ToolKit.runOnMainThreadSync(new Runnable() {
            @Override
            public void run() {
                mClient = buildLocation(context);
                mClient.registerLocationListener(LocationBuilder.this);
                mClient.start();
            }
        });
        try {
            this.mLatch.await(15, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
            this.stop();
        }
    }
    public Location getLocation() {
        Location location = mLocation;
        mLocation = null;
        return location;
    }
    private void stop() {
        try {
            mClient.unRegisterLocationListener(this);
            mClient.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private LocationClient buildLocation(Context context) {
        LocationClient locationClient = new LocationClient(context);     //聲明LocationClient類
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//設置定位模式
        option.setCoorType("bd09ll");//返回的定位結果是百度經緯度,默認值gcj02
        option.setScanSpan(1000);//設置發起定位請求的間隔時間爲1000ms
        option.setIsNeedAddress(true);
        locationClient.setLocOption(option);
        return locationClient;
    }
    @Override
    public void onReceiveLocation(BDLocation location) {
        this.stop();
        try {
            if (mLatch != null) {
                int[] codes = new int[]{61, 65, 66, 68, 161};
                if (Arrays.binarySearch(codes, location.getLocType()) >= 0) {
                    mLocation.setLongitude(location.getLongitude());
                    mLocation.setLatitude(location.getLatitude());
                    mLocation.setRadius(location.getRadius());
                    mLocation.setAddress(location.getAddrStr());
                    mLocation.setAltitude(location.getAltitude());
                }
                mLatch.countDown();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

IIS 服務器下載apk文件報404錯

文件路徑什麼都對,可就是提示404錯誤,最後問題出在了IIS的MIME上,按照下面的辦法即可解決。
  1. 在 IIS 管理器中,右鍵單擊要爲其添加 MIME 類型的網站或網站目錄,單擊"屬性"。
  2. 單擊"HTTP 頭"選項卡。
  3. 單擊"MIME 類型"。
  4. 單擊"新建"。
  5. 在"擴展名"框中,鍵入文件擴展名:.apk
  6. 在"MIME 類型"框中,鍵入application/octet-stream
  7. 單擊"確定"。

========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41849241
========================================================

發佈了82 篇原創文章 · 獲贊 709 · 訪問量 66萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章