文章标签 ‘Android’
2019十一月13

2019双11入手华为全家桶 Mate 30 Pro 5G 、FreeBuds 3 、车载无线充电

谈谈使用体验:

一、手机篇

实体店现货买的翡冷翠(本来预订青山黛,但实在等不了一个月,看有现货就拿了),6899¥什么优惠都没,就送了个透明手机壳,手机壳还是满合身的,满满的安全感。考虑屏幕那么大,还是花了299¥买了碎屏险。手机出厂自带贴膜(据说第一批出厂手机没贴膜),所以这点比较好,不用纠结贴什么膜了,上手即用。

1、系统

对于做IT的来说,上手很快,摸索一圈就知道权限如何设置、通知啊、广告怎么移除等。隔空手势用了,感觉实用性不大,试想下看着抖音,用手悬停半秒,然后隔空滑动屏幕,手抬着很累的手酸了都,还没手动滑屏比较快。

发现一个bug,或也可以说设置不合理的地方,156版本系统,短信的通知关闭后不知道如何打开。设置项不在“通知”里,也不在“应用”一级菜单里,而是需要到“应用”下面的“应用管理”里面,找到“信息”,然后再点“通知管理”,对于新手来说,跟捉迷藏一样,不百度或者问客服,真不知道。

APP的打开及使用,响应速度很快,几乎和iOS系统一样,为什么说几乎呢,是因为一些功能细节上,能感觉出比iOS系统慢那么一丢丢,比如微信支付成功的通知,可能与系统的通知机制不一样造成的,不过不影响使用,几乎察觉不出来。游戏还没安装,暂时略过。

短信拦截/手机拦截等功能太好了,每天收到几十条推销短信/电话,不用单独安装拦截软件,太爽了吧。

NFC功能也很好,8P虽然带NFC但是几乎没有用武之地,华为手机的NFC可以模拟小区门禁卡,真是很方便的。

关于提子,装了v2xxxNG,正好昨天又申请新的G服务器,搭建提子可以上x网,但是没有G套件,只能通过网页访问G的服务,还不是很方便。

壁纸和锁屏界面,可以自动更新一些精美的照片,很好。

情景智能,是自动弹出来的一个功能,开通后可以绑定手机号,通过快递查询平台查询到关联的所有快递物流信息,功能还是比较贴心的。

说几点不爽之处吧:

1)Android系统里的一些官方APP内嵌广告,这个在苹果APP里很少见;

2)各种APP各种请求权限,什么存储、位置、读取设备信息等等,一般很难判断该不该禁用,有的权限禁用了APP就启动不了了,如果都赋权,那么感觉手机像裸奔。

2、屏幕

屏幕很亮眼,逛商城的时候四五个小姐姐围着手机看,有一定的误操作的几率,可能用习惯就好了吧,毕竟拿到手还没有48小时。

屏幕分辨率,刚从8p LCD切换过来的时候还不习惯,看多了也就习惯了,给眼睛一个适应过程。

3、后置摄像头

额,怎么说呢,广角拍出来效果很好,但AI有点过度,色彩失真。近距拍摄,不是那么清晰的感觉,可能每个人体验不一样吧,个人感觉摄像头数量很多,但效果不是说的那么神(不知道为啥群里的网友拍的都那么好看?我是买到了假的么……23333)。平时拍照少,也就无所谓了。

3、前置摄像头

这个要吐槽一下了,后置摄像头有AI美化,前置摄像头一点AI和美化都没有,当镜子照啊,可以非常清晰的看到脸上的斑点/粉刺/黑头,额……

4、电量

比较给力的,比之前用的ip8p持久的多了。

二、车载无线快充电

今早上班开车20来分钟,60%电量充到80%,目测一天不用手动充电,上班下班通过车载充电就够用了啊哈哈哈。买的27W功率的那款。

三、蓝牙耳机

Freebuds 3 双11刚买,EMS 12号中午就送到了。耳机支持蓝牙5.1协议版本,Mate 30 Pro 5G 也是5.1协议,搭配起来很爽哦,正好坐在靠路边的窗口位置,试用了下降噪功能,开启主动降噪功能,路上的车水马龙声音真的消失了,,不过办公室里的说话声音是过滤不掉的。耳机不带调节音量功能 – -。

还有个买蓝牙耳机的重要原因,那就是Mate 30 系列打电话是屏幕发声,不开免提都能听到声音,所以为了隐私,打电话还是用蓝牙耳机比较好。

2014十月24

Android:tcpdump抓包命令

adb shell

su

chmod 777 /data/local/tcpdump

/data/local/tcpdump -p -vv -s 0 -w /sdcard/capture.pcap

2014八月28

Cordova:Toast浮动提示插件

第一步:编写插件类

package cn.xuetang.plugin;

import android.widget.Toast;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;

/**
 * Created by Wizzer on 14-8-28.
 */
public class ToastPlugin extends CordovaPlugin {
    public ToastPlugin() {

    }

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (this.cordova.getActivity().isFinishing()) return true;
        if (action.equals("show")) {
            this.show(args.getString(0));
        } else if (action.equals("showlong")) {
            this.showlong(args.getString(0));
        } else {
            return false;
        }
        callbackContext.success();
        return true;
    }

    public void show(String message) {
        Toast.makeText(this.cordova.getActivity(), Toast.LENGTH_SHORT).show();
    }

    public void showlong(String message) {
        Toast.makeText(this.cordova.getActivity(), message, Toast.LENGTH_LONG).show();
    }
}

 

第二步:配置  res/xml/config.xml

    <feature name="ToastPlugin">
        <param name="android-package" value="cn.xuetang.plugin.ToastPlugin" />
    </feature>

注:这里的 feature name ,要和↓↓面讲的的js文件里一致。

 

第三步:创建js文件 plugins/toast.js

/**
 * Created by Wizzer on 14-8-28.
 */
cordova.define("cn.xuetang.plugin.ToastPlugin", function(require, exports, module) {
    var exec = require('cordova/exec');
    module.exports = {

        /**
         * 一共5个参数
         第一个 :成功回调
         第二个 :失败回调
         第三个 :将要调用的类的配置名字(在config.xml中配置↑↑)
         第四个 :调用的方法名(一个类里可能有多个方法 靠这个参数区分)
         第五个 :传递的参数  以json的格式
         */
        show: function(message) {
            exec(null, null, "ToastPlugin", "show", [message]);
        },
        showlong: function(message) {
            exec(null, null, "ToastPlugin", "showlong", [message]);
        }
    };

});

注:js里两个方法,分别对应类中的两个方法

 

第四步:修改 cordova_plugins.js 引用 tocas.js

在 module.exports = [ ] 中追加如下代码:

    {
        "file": "plugins/toast.js",
        "id": "cn.xuetang.plugin.ToastPlugin",
        "merges": [
            "navigator.toast"
        ]
    }

 

最后:调用

       navigator.toast.show("再点击一次退出");

       navigator.toast.showlong("再点击一次退出");

 

 

 

2014八月28

Cordova:连续按两次返回键退出程序

/**
 * Created by Wizzer on 14-8-28.
 */
var num = 0;
var login = {
    initialize: function () {
        this.bindEvents();
    },
    bindEvents: function () {
        document.addEventListener('backbutton', this.eventBackButton, false);
    },
    eventBackButton: function () {
        num++;
        if (num > 1) {
            navigator.app.exitApp();
        }
        navigator.toast.show("再点击一次退出");
        // 3秒后重新计数
        var intervalID = window.setInterval(function() {
            num=0;
            window.clearInterval(intervalID);
        }, 3000);
    }
};

浮动提示插件见:
/?p=3026

2013十月8

自定义EditText实现信纸效果

自定义EditText实现信纸效果

作者:wtmdbf 

一、引言

用户在提交表单的时候,我们可能会希望展示一个美观的输入框,以提升用户体验。

二、效果

图片说明文字

三、实现细节

读者可以看到就是给EditText设置一个黄色的背景,然后给每一行添加一个下划线。为了看出不同,我们这里拿android提供的notepad这个demo的效果来做下比较,下面是notepad的截图
图片说明文字

从从上可以看出,notepad的下划线是在产生新的行以后才绘制出来的,为了读者阅读的方便,我把notepad的源码贴出来如下:

public static class LinedEditText extends EditText {
        private Rect mRect;
        private Paint mPaint;

        // This constructor is used by LayoutInflater
        public LinedEditText(Context context, AttributeSet attrs) {
            super(context, attrs);

            // Creates a Rect and a Paint object, and sets the style and color of the Paint object.
            mRect = new Rect();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(0x800000FF);
        }

        /**
         * This is called to draw the LinedEditText object
         * @param canvas The canvas on which the background is drawn.
         */
        @Override
        protected void onDraw(Canvas canvas) {

            // Gets the number of lines of text in the View.
            int count = getLineCount();

            // Gets the global Rect and Paint objects
            Rect r = mRect;
            Paint paint = mPaint;

            /*
             * Draws one line in the rectangle for every line of text in the EditText
             */
            for (int i = 0; i < count; i++) {

                // Gets the baseline coordinates for the current line of text
                int baseline = getLineBounds(i, r);

                /*
                 * Draws a line in the background from the left of the rectangle to the right,
                 * at a vertical position one dip below the baseline, using the "paint" object
                 * for details.
                 */
                canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
            }

            // Finishes up by calling the parent method
            super.onDraw(canvas);
        }
    }

那是如何实现我所说的一开始就绘制好下划线的效果呢,在此之前,你需要了解如何在android中获得字体的高度,网上有很多,为了方便大家阅读特摘录如下,先看图:
图片说明文字
然后我们可以通过下面的代码获得字体大高度

Paint p = new Paint();  
p.setTextSize(50);  
p.setAntiAlias(true);  
FontMetrics fm = p.getFontMetrics();  
int textHeight = (int) (Math.ceil(fm.descent - fm.ascent) + 2);

读者了解了上面的知识点以后就可以,在看我是如何实现的。

基本思想是根据字体的高度,在view的对应位置上绘制好每条line,代码如下:

package com.example.customedittext;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.EditText;

public class CustomEditText extends EditText {

    private Paint mPaint;
    private int lines = 0;
    private float fontHeight = 0;
    private float leading = 0;

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initPaint();
    }

    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    public CustomEditText(Context context) {
        super(context);
        initPaint();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.parseColor("#CDDCD5"));
        mPaint.setAntiAlias(true);
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        int lineHeight = getLineHeight();
        int viewHeight = getHeight();
        lines = viewHeight / lineHeight;
        setGravity(Gravity.TOP);
        float textSize = getTextSize();
        Paint paint = new Paint();
        paint.setTextSize(textSize);
        FontMetrics fontMetrics = paint.getFontMetrics();
        fontHeight = fontMetrics.descent - fontMetrics.ascent;
        leading = fontMetrics.leading;// leading == 0
        setBackgroundColor(Color.parseColor("#F8F6DF"));
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int count = getLineCount();
        if (count <= lines) {
            for (int i = 1; i < lines; i++) {

                canvas.drawLine(0, fontHeight * i + leading * i, getWidth(),
                        fontHeight * i + leading * i, mPaint);
            }
        } else {
            for (int i = 1; i < count; i++) {
                canvas.drawLine(0, fontHeight * i + leading * i, getWidth(),
                        fontHeight * i + leading * i, mPaint);
            }
        }
    }

}

四、存在的问题和遗留点

虽然最主要的效果已经实现了,但还有一些问题

  • 如何定义一个只能输入固定行数的EditText?
  • 细心的朋友会发现当输入的行数过多的时候会发现字体与横线的距离会发生偏差,原因是画出来的线不精确,如果按照android notepad那样绘制出来的线是精确的,但达不到我们一开始想要的那种效果,如何让我们的绘制更加精确,**热心的朋友如果知道或者有更好的方法的话,欢迎分享**?

原文作者: wtmdbf

原文地址: http://my.eoe.cn/readonly/archive/15757.html

2013三月8

Phonegap开发经验总结:Android与iOS应用开发的平滑移植

之前用phonegap做过Anroid项目,主要功能是人员定位、表单提交、拍照上传、通知提醒等功能,这也是最常用而基本的应用功能,最近打算出iOS版本的客户端,这里简单总结使用phonegap开发的一些经验以及探讨代码在不同手机系统的平移工作。

1、PhoneGap介绍

PhoneGap是一个用基于HTML,CSS和JavaScript的,创建移动跨平台移动应用程序的快速开发平台。这是PhoneGap最大的优点,支持jquery使其开发功能简单而强大。官方网站为 http://www.phonegap.com/ 更新速度较快,一般1个月就会发布一个新版本支持最新版本的手机系统。

既然要实现跨平台开发,大部分功能代码要做到可移植复用,在保持安全性、功能性的基础上尽量使用HTML+JS+PhoneGap API来实现业务功能,尽量避免使用手机系统的SDK开发实现。

UI层使用 Jquery Mobile ,API介绍见 http://www.jqmapi.com  ,定义了表单元素、页面和对话框等,和PhoneGap结合使用比较方便。

2、Android应用开发

2.1 数据库操作

PhoneGap API数据库操作是跨平台的,所以这里介绍后iOS段就不再赘述。

	var db ;
    document.addEventListener("deviceready", onDeviceReady, false);
    function onDeviceReady() {
        db = window.openDatabase("testdb", "1.0", "MyApp", 12000000);      
        db.transaction(creatDB,errorDB); //创建表    
		db.transaction(loginDB,errorDB); //查询表初始化表单    
    }	
    function creatDB(tx)
    { 
        tx.executeSql('CREATE TABLE IF NOT EXISTS USER (ID,LOGINNAME,PASSWORD)');  
    }
    function errorDB(err) {
       navigator.notification.alert("异常信息: "+err.code,null,"温馨提示","确定");
    }
    function loginDB(tx) {
	    tx.executeSql('SELECT * FROM USER', [], querySuccess, errorDB);  
    }
    function querySuccess(tx, results) {
        var len = results.rows.length;
        if(len>0)
        { 
            $("#loginname").val(results.rows.item(0).LOGINNAME);//LOGINNAME大写
            $("#password").val(results.rows.item(0).PASSWORD);   
        }
    }

2.2 表单提交

使用jquery+JSON解析和提交表单,常用示例:

	function getData(){
	    //{"mc":"Hello World!","list":[{"key":"0001","value":"张三"},{"key":"0002","value":"李四"}]}
		$.mobile.showPageLoadingMsg( "加载中....." ); //打开加载进度条	
		$.post(//使用jquery的POST方法  serverurl 放在公共JS里定义
				serverurl+ "/json/getdata.jsp",
				{
					"doAction":"getdata",
					"loginname":comHT.get("loginname"),//comHT 定义了从URL获取参数赋值到Hashtable中方法
					"password":hex_md5(comHT.get("password")),//hex_md5 实现对密码的加密
					"resourceid":"00100002",
					"rmd":Math.random()
				},
				function(data) {
					var jsondata = jQuery.parseJSON(data); //解析数据为JSON格式
                    $("#mc").val(jsondata.mc);//文本框赋值
					jQuery.each(jsondata.list, function(index, obj) {
						$("#czyy").append('<option value="'+obj.key+'">'+obj.value+'</option>');//下拉框架赋值  
					});
					$.mobile.hidePageLoadingMsg(); //关闭进度条

				});
	}

2.3 拍照上传

使用phonegap提供的API来使用,iOS下代码略有不同,注:此段代码phonegap 为2.0.0

原理是先把文件提交,提交成功后获得服务器真实路径,在表单提交的时候保存进数据库。

<img style="width:120px;height:120px;" id="zpzp1" src="../image/zpsc.png" onclick="pz(this,1)" /> 
<input type="hidden" id="zp1" value="">
    function pz(obj,v_zdz) {
		zdz=v_zdz;
		zpobj = obj;
		navigator.camera.getPicture(onSuccess, onFail, {
			quality : 25,
			destinationType : Camera.DestinationType.FILE_URI
		}); 
	}
 	// 采集操作成功完成后的回调函数
	function onSuccess(imageURI) {
		zpobj.src = imageURI;
		uploadFile(imageURI);
	}
	// 采集操作出错后的回调函数
	function onFail(error) {
	}
	// 上传文件到服务器
	function uploadFile(path) {
		    var ft = new FileTransfer();
		    var loginname=comHT.get("loginname");
            var options = new FileUploadOptions();
            var fn=loginname+"-"+path.substr(path.lastIndexOf('/')+1);
            options.fileKey="file";
            options.fileName=path.substr(path.lastIndexOf('/')+1);
            options.mimeType="image/jpeg";
            options.chunkedMode = false; 
		    ft.upload(
				 path, 
				 serverurl+"/json/upload.jsp?fn="+fn,
			     function(result) {
					 var jsondata = jQuery.parseJSON(result.response);
					 $("#zp"+zdz).val(jsondata.path);
					 navigator.notification.alert("照片"+zdz+" "+decodeURI(jsondata.res),null,"温馨提示","确定");
		         }, 
		         function(error) {
		        	 navigator.notification.alert("照片"+zdz+" 上传失败!"+ error.code,null,"温馨提示","确定"); 
		         }, 
		         options
		    );
	}

2.4 人员定位

采用百度定位SDK,从用户表中读取用户标识,详细的开发过程过繁琐不写了(好吧,下班了。。),下载和查看百度定位SDK请访问

http://developer.baidu.com/map/geosdk-android-download.htm

2.5 通知提醒

使用androidpn来实现android下消息推送功能,嗯,这个网上教程比较多,大家搜一下吧。

 

3、iOS应用开发

首先搭建iOS开发环境,详见本站教程 /?p=2438 ,目前phonegap 2.5.0支持iOS6.0以下版本,iOS6.1暂时不支持要等phonegap新版咯。

拍照功能需要真机测试,而真机测试需要证书,这大大的头疼,还好找到了方法,就是找到了一篇《Xcode 4.5.2 + iOS 6.0免证书(iDP)开发+真机调试+生成IPA全攻略》文章,哇哈哈,iOS6.1也适应。文章地址 http://www.cnblogs.com/yuanxiaoping_21cn_com/archive/2012/11/15/2772388.html

 

3.1 数据库操作

同android,略。

3.2 表单提交

同android,略。

3.3 拍照上传

在研究,以后更新。

3.4 人员定位

在研究,以后更新。

3.5 通知提醒

在研究,以后更新。

2012十二月27

jquerymobile 实现提示框

引入JS和CSS文件:

<link rel="stylesheet" href="../css/jquery.mobile-1.0.1.min.css" />
<link rel="stylesheet" href="../css/jquery.mobile.simpledialog.min.css" /> 
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/jquery.mobile-1.0.1.min.js"></script>
<script type="text/javascript" src="../js/jquery.mobile.simpledialog2.min.js"></script>

JS代码:

$('<div>').simpledialog2({
				mode: 'button',
				headerText: '提示',
				headerClose: true,
				buttonPrompt: '请选择商品',
				buttons : {
					'确定': {
						click: function () { 
							//$('#outputbutton1').text('OK');
						}
					}
				}
			});

 

2012六月20

Android:扫描获取AP信息

增加权限:

<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />
<uses-permission android:name=”android.permission.CHANGE_WIFI_STATE” />

WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
			   WifiInfo wifiInfo = wifiManager.getConnectionInfo();
			  showMsg(wifiInfo.toString());//自己的显示方法

			  wifiManager.startScan();
			  List mWifiList = wifiManager.getScanResults();
			  for(int i=0;i<mWifiList.size();i++)
				  logger.d(mWifiList.get(i).toString());//自己重构的日志方法
2011十月31

里程碑2 MIUI简单演示

2011十月15

里程碑2 ME722 CM7简单演示