[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
========================================================

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。