[转载]Sencha Touch+PhoneGap打造超级奶爸之喂养记(一) 源码免费提供 - liongis - 博客园

mikel阅读(1160)

[转载]Sencha Touch+PhoneGap打造超级奶爸之喂养记(一) 源码免费提供 – liongis – 博客园.

起源

  非常高兴我的宝宝健康平安的出生了。对于初次做奶爸的我,喜悦过后,面临着各 中担心,担心宝宝各项指标是否正常。最初几天都是在医院待着,从出生那一天开始,护士妹妹隔一段时间就会来问宝宝的喂奶,大小便,体温等情况。我想医生们 应该也是通过这些数据来分析宝宝是否健康。宝宝刚才出生的几天,吃喝,大小便很频繁,但又不方便记录,很容易遗漏,所以想做一个APP来记录宝宝的一些数 据。最近正在学习Sencha Touch+PhoneGap,经过几天的开发,基本成型,目前我的宝宝一些数据都是用这个软件来记录的。同时也分享给大家,希望能对更多的人有用。初次 开发,还有很多不周全的地方,望各们指正。

  宝宝刚出生这一段时间主要需要记录的数据有:妈妈喂奶次数,喝牛奶多少量,大小便多少次,体温多少,睡了多长时间。APP也是围绕这几个功能进行开发。

最终效果

首页

母乳

奶瓶

尿布

体温

新增睡觉记录

 

技术点

1.使用Sencha Touch+PhoneGap开发移动端应用,结构比较完整,且功能不复杂,适合初学者学习。

2.使用SQLite做为数据存储,实现真机和PC浏览器两种模式对数据库操作。可以在PC上用浏览器上运行,方便对程序进行调试。

3.扩展时间选择控件,可以同时对日期,时间进行选择。

4.对日期选择控件进行汉化处理。

 

程序结构

本着学习和分享的精神,记录我整个程序的架构和开发过程,以方便初学者可以更快速的入门。

Sencha Touch使用的是MVC模式,有些内容是固定的,网上有很多入门文章,都是需要先装一堆东西。我用的方法很简单,直接新建目录,把需要的资源包拷贝到指定的目录。

整个程序目录结构如下:

sencha touch 2.3.1,phonegap 2.0.0

因为此程序可以在PC端支持HTML5的浏览器下运行,所以我们先讲sencha touch的开发,以后再说使用phonegap打包成手机端应用。

 

相关代码

index.html



喂养记录

<script src="cordova-2.0.0.js" charset="utf-8"></script><script src="lib/st2.3.1/sencha-touch-debug.js"></script>
<script src="app.js"></script><script src="plugin/pgsqliteplugin.js" charset="utf-8"></script>
<script src="plugin/sqlitedb.js" charset="utf-8"></script><script src="utils/dbhelper.js" charset="utf-8"></script>
<script src="utils/utils.js" charset="utf-8"></script>

&nbsp;

app.js

//数据库文件
var localFileName = "superdad.db",fgDB;
var weinaiStore, muruStore, niaobuStore, tiwenStore, shuijiaoStore;

function onBodyLoad() {
// 注册回退按钮事件监听器
document.addEventListener("backbutton", onBackKeyDown, false); // 返回键

if (Ext.os.is.Windows) {
//alert("windows");
fgDB = new sqliteDB(localFileName, 1024*1024*2);
if(0) {
initFGdb();
}
} else {
document.addEventListener("deviceready", initSystem, true);
}
}

function initFGdb() {
fgDB.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS weiyang');
tx.executeSql('CREATE TABLE IF NOT EXISTS [weiyang] (' +
'[id] INTEGER PRIMARY KEY AUTOINCREMENT, ' +
'[itemhash] VARCHAR2(16), ' +
'[stype] VARCHAR2(2), ' +
'[date] VARCHAR2(20), ' +
'[volume] VARCHAR2(4), ' +
'[remark] VARCHAR2(200), ' +
'[dateCreated] DATETIME)'
);
}, function(){
//alert('初始化表成功');
}, function (er) {
console.log('error with executeSql', er);
});
}

function initSystem() {
//compass = new Compass();
//compass.startWatch();
//alert("罗盘成功!");
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs) {
fileSystem = fs;
// isFirstLoad = false;
if (fileSystem != null) {
// alert(fileSystem.root.fullPath);
var mapFile = fileSystem.root.getDirectory("superdad/", {
create : true,
exclusive : false
}, function(parent) {
//打开数据库
openMBdb(parent.fullPath);
// alert(mapPath);
}, function(msg) {
// alert(msg);
});
} else {
alert("数据库打开失败!");
}
}, function() {
alert("数据库打开失败!");
});
}
// enable Ext autoloader
Ext.Loader.setConfig({
enabled : true
});

function openMBdb(path) {
var options = {};
options.storage = "external";
options.path = path;
fgDB = new PGSQLitePlugin(localFileName, function(dbResult, dbObject){
console.log("Database status=" + dbResult.status);
console.log("Database version=" + dbResult.version);
//fgdb = dbObject;
//alert("数据库打开成功");
if(dbResult.isNew) {
initFGdb();
}
}, function(err){
console.log("Error create database::err=" + err);
alert("数据库打开失败" + err);
},options);
}

function onConfirm(button) {
// alert('You selected button ' + button);
if (button == 1)
navigator.app.exitApp(); // 选择了确定才执行退出
}
// Show a custom confirmation dialog
//
function onBackKeyDown() {
navigator.notification.confirm('按确定退出程序!', // message
onConfirm, // callback to invoke with index of button pressed
'确定要退出程序吗?', // title
'确定,取消' // buttonLabels
);
}

//
Ext.Loader.setPath({
'Ext.ux' : 'ux',
'Ext' : 'lib/st2.3.1/src',
'WeiYang' : 'app'
});
//
Ext.application({
name : 'WeiYang', //程序名称
requires : ['Ext.MessageBox'], //引用的资源
models : ['WeiYangInfo'], //数据模型
stores : ['WeiYangStore'], //数据源
views : ['Main','Login'], //视图
controllers : ['MainController'], //控制器,
launch : function() {
// Destroy the #appLoadingIndicator element
// Ext.fly('appLoadingIndicator').destroy();
//Ext.Viewport.add(Ext.create('WeiYang.view.Login'));
Ext.Viewport.add(Ext.create('WeiYang.view.Main'));

weinaiStore = Ext.create('WeiYang.store.WeiYangStore');
muruStore = Ext.create('WeiYang.store.WeiYangStore');
niaobuStore = Ext.create('WeiYang.store.WeiYangStore');
tiwenStore = Ext.create('WeiYang.store.WeiYangStore');
shuijiaoStore = Ext.create('WeiYang.store.WeiYangStore');

Ext.Date.monthNames = [
'一月', '二月', '三月', '四月', '五月', '六月',
'七月', '八月', '九月', '十月', '十一月', '十二月'
];

Ext.Date.dayNames=["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"];
},
// html5缓存更新
onUpdated : function() {
Ext.Msg.confirm("更新", "系统已经自动更新到最新版本,是否重新加载?", function(
buttonId) {
if (buttonId === 'yes') {
window.location.reload();
}
});
}
});

今天先写到这里,宝宝醒了,得去冲牛奶了,下回继续说。
源代码免费提供

需要源码的朋友可以留下邮箱,我统一发送。

也可以先下载APK试试

超级奶爸之喂养记APK点击下载

[转载]PHP支付宝手机支付 接口 - 小窗口的浪漫 - 博客园

mikel阅读(1422)

[转载]支付宝手机支付 接口 – 小窗口的浪漫 – 博客园.

讲解:

一:取得  token

 

要取得 token 有两个 参数是 是必须

 

req_data  和 sign

req_data格式如下(这是一些必填的。如果想要更多的参数自己去下载手册):

&lt;direct_trade_create_req&gt;
&lt;notify_url&gt;{通知地址}
&lt;call_back_url&gt;{返回地址}
&lt;seller_account_name&gt;{商家支付宝账号}
&lt;out_trade_no&gt;{外部订单号}
{商品介绍}
&lt;total_fee&gt;{商品价格}

sign(签名)格式如下

$params = array(
/* 基本信息 */
'partner' =&gt; {支付宝pid},
'req_id' =&gt; md5({网站订单号}),
'service' =&gt; 'alipay.wap.trade.create.direct',
'format' =&gt; 'xml',
'v' =&gt; '2.0',
'sec_id' =&gt; 'MD5',
"_input_charset" =&gt; CHARSET
"req_data" =&gt; {以面的req_data}
);

if($sort){
/* 排序 */
ksort($params);
reset($params);
}
$sign = '';
foreach ($params AS $key =&gt; $value)
{
$sign .= "{$key}={$value}&amp;";
}

md5(substr($sign, 0, -1) . {支付宝key});

sign 要注意的地方 是 排序 md5之前一定要按手册上的排序不然会出错的

然后以post方式提交给

http://wappaygw.alipay.com/service/rest.htm?

注意 返回的 数据是 经过 urlencode 的 所心我们要用 urldecode 解码 然后还得用解析 返回的数据

/**
	 * 解析远程模拟提交后返回的信息
		 * @param $str_text 要解析的字符串
	 * @return 解析结果
	 */
	function parseResponse($str_text) {
		//以“&”字符切割字符串
		$para_split = explode('&',$str_text);
		//把切割后的字符串数组变成变量与数值组合的数组
		foreach ($para_split as $item) {
			//获得第一个=字符的位置
			$nPos = strpos($item,'=');
			//获得字符串长度
			$nLen = strlen($item);
			//获得变量名
			$key = substr($item,0,$nPos);
			//获得数值
			$value = substr($item,$nPos+1,$nLen-$nPos-1);
			//放入数组中
			$para_text[$key] = $value;
		}
		
		if( ! empty ($para_text['res_data'])) {			
			//token从res_data中解析出来(也就是说res_data中已经包含token的内容)
			$doc = new DOMDocument();
			$doc->loadXML($para_text['res_data']);
			$para_text['request_token'] = $doc->getElementsByTagName( "request_token" )->item(0)->nodeValue;
		}
		
		return $para_text;
	}

最后的 规范的支付表单数据 就是(这里是要用get)

$params = array(
            'partner'           => $this->_config['wap_alipay_partner'],
            'req_id'            =>  md5({网站订单号}),
            'service'           =>  'alipay.wap.trade.create.direct',
            'format'            =>  'xml',
            'v'                 =>  '2.0',   
            'sec_id'            =>  'MD5',
            "_input_charset"    => CHARSET
			'req_data'=>'<auth_and_execute_req><request_token>' . {token} . '</request_token></auth_and_execute_req>',
			'service'	=>	"alipay.wap.auth.authAndExecute",			
		
	);
	//这个地方也要签名的。方式和上面一样
	$params['sign']	= _get_sign($params);
	
	//get数据
	$return = array(
		'online'    =>  {联线},
		'desc'      =>  {支付说明},
		'method'    =>  'GET',
		'gateway'   =>  'http://wappaygw.alipay.com/service/rest.htm?',
		'params'    =>  $params,
	)

最后 跳转到支付宝

 

 <form action="<?php echo $return['gateway'];?>" id="payform" method="<?php echo $return['method'];?>" style="display:none">
<?php foreach ( $return['params'] $_k=>$value){?>
	<input type="hidden" name="<?php echo $_k;>" value="<?php echo $value;>" />
<?php }?>

</form>
<script type="text/javascript">
  document.getElementById('payform').submit();
</script>

[转载]Fatal error: Call to undefined function openssl_pkey_get_private() - wust_star的专栏 - 博客频道 - CSDN.NET

mikel阅读(1702)

[转载]Fatal error: Call to undefined function openssl_pkey_get_private() – wust_star的专栏 – 博客频道 – CSDN.NET.

在windows系统中IIS环境的操作方式: 

1、在php.ini中 
extension=php_openssl.dll去掉前面的注释 
2、复制php安装目录中的: 
libeay32.dll 
ssleay32.dll 
至c:\windows\system32 
3、复制php_openssl.dll至c:\windows\system32 
4、重启IIS 

---AppServ Win32如何打开openssl--------------------1.打开c:/windows,里面有一个php.ini文件(AppServ居然将php的配置文件移到这里来!),然后在里面搜索 ;extension=php_openssl.dll ,把前面的逗号去掉。

2.进入AppServ的安装目录,到php文件夹里面,分别搜索 libeay32.dll 和 ssleay32.dll ,把它们复制到 c:/windows/system32 下面

3.重新启动 Apache,就可以了,至于phpMailer的使用方法,请参考phpMailer的例子。

[转载]云图如何制作附近实体店的地图?-微信微博支付宝 - 酸奶小妹 - 博客园

mikel阅读(1262)

[转载]【云图】如何制作附近实体店的地图?-微信微博支付宝 – 酸奶小妹 – 博客园.

摘要:

附近连锁店地图与全国连锁店地图,最大的区别就是:

1、附近连锁店地图需要先定位,然后搜索附近的店铺。

2、全国连锁店地图,是先选择城市,然后检索某城市内的全部门店信息。

本文就详细讲解了如何制作附近实体店的地图,并调起高德地图进行导航,调起打电话功能。

本文还详细讲解了如何设置支付宝服务、微信公众号、微博官方账号的地图功能。

————————————————————————

 

一、支付宝设置

登录支付宝服务窗:https://fuwu.alipay.com/platform/queryMenu.htm

自定义菜单 -> 主菜单 -> 有子级菜单

填写子菜单名称,设置为跳转网页,并且放入网址。比如菜鸟物流:http://zhaoziang.com/amap/cainiao.html

最后点击发布。

 

二、微信设置

登录微信公众平台:https://mp.weixin.qq.com

功能->高级功能->编辑模式->自定义菜单-> 菜单管理->添加->设置动作

设置为跳转网页,并且放入网址。比如菜鸟物流:http://zhaoziang.com/amap/cainiao.html

最后点保存。

 

三、微博设置

登录微博:http://weibo.com/

管理中心->粉丝服务->高级功能->编辑模式->自定义菜单-> 菜单管理->添加->设置动作

设置为跳转网页,并且放入网址。比如菜鸟物流:http://zhaoziang.com/amap/cainiao.html

最后点保存。

 

四、云图设置

登录云图管理台:http://yuntu.amap.com/datamanager/index.html

新建地图

导入CSV数据。(支持UTF8和GBK 编码,数据不超过10,000 条)

 

五、代码与获取网址

将以下代码复制下来,替换key、tableID、图标,然后生成自己的网址。

获取key的地址:http://api.amap.com/key

获取tableID的地址:

进入你的云图->获取tableID

 

全部源代码:





菜鸟物流全国站点

<script src="http://webapi.amap.com/maps?v=1.2&amp;key=【您的key】" language="javascript"></script>

<div class="header clearfix"><a id="iListBtn"></a>列表模式 <a id="iMapBtn"></a>地图模式</div>

&nbsp;

&nbsp;

<div id="map" class="clearfix"></div>

&nbsp;

<div id="list" style="display: none;">正在读取数据……</div>

&nbsp;

&nbsp;

<script language="javascript">// <![CDATA[
function display(id1,id2){
    document.getElementById('map').style.display = 'none';
    document.getElementById('list').style.display = 'none';
    document.getElementById(id1).style.display = 'block';
    document.getElementById(id2).style.display = 'block';
    if (id1 === 'map' && mapObj) {
        mapObj.setFitView();
    }
}
var mapObj;
var cloudDataLayer;
var cloudSearch;
var cpoint;
//初始化地图对象,加载地图
function mapInit(){
    mapObj = new AMap.Map("map");
    mapObj.plugin('AMap.Geolocation', function () {
        geolocation = new AMap.Geolocation({
            enableHighAccuracy: true,//是否使用高精度定位,默认:true
            timeout: 10000,          //超过10秒后停止定位,默认:无穷大
            maximumAge: 0,           //定位结果缓存0毫秒,默认:0
            convert: true,           //自动偏移坐标,偏移后的坐标为高德坐标,默认:true
            showButton: true,        //显示定位按钮,默认:true
            buttonPosition: 'LB',    //定位按钮停靠位置,默认:'LB',左下角
            buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
            showMarker: true,        //定位成功后在定位到的位置显示点标记,默认:true
            showCircle: false,        //定位成功后用圆圈表示定位精度范围,默认:true
            panToLocation: true,     //定位成功后将定位到的位置作为地图中心点,默认:true
            zoomToAccuracy:true      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
        });
        mapObj.addControl(geolocation);
        geolocation.getCurrentPosition();
        AMap.event.addListener(geolocation, 'complete', onComplete); //返回定位信息-成功
        AMap.event.addListener(geolocation, 'error', function(){
            alert('哟,定位失败啦!');
        });    //返回定位信息-失败 
    });
}
function onComplete(data) {
    var lngX = data.position.getLng();
    var latY = data.position.getLat();
    cpoint = new AMap.LngLat(lngX,latY);
    //cpoint = new AMap.LngLat(116.38298,39.955543);
    myCloudList();  
}
//云图加载列表
function myCloudList(){
    //列表
    var search; 
    var searchOptions = {
            pageSize:20
        };
    mapObj.plugin(["AMap.CloudDataSearch"], function() {
        cloudSearch = new AMap.CloudDataSearch('【您的tableID】', searchOptions); //构造云数据检索类
        AMap.event.addListener(cloudSearch, "complete", cloudSearch_CallBack); //查询成功时的回调函数
        AMap.event.addListener(cloudSearch, "error", errorInfo); //查询失败时的回调函数
        cloudSearch.searchNearBy(cpoint, 10000); //周边检索 
    });
}
var markers = new Array(); 
var windowsArr = new Array();
//添加marker和infowindow     
function addmarker(i, d){  
    var lngX = d._location.getLng();  
    var latY = d._location.getLat();  
    var IconOptions = {
        image : "cainiao.png", //您的小图标33*33
        size : new AMap.Size(33,33),
        imageSize : new AMap.Size(33,33),
        imageOffset : new AMap.Pixel(-16,0)
    };
    var myIcon = new AMap.Icon(IconOptions);
    var markerOption = {  
        map:mapObj,  
        icon: myIcon,   
        offset: new AMap.Pixel(-15,-30),   
        position:new AMap.LngLat(lngX, latY)    
    };              
    var mar = new AMap.Marker(markerOption);    
    markers.push(new AMap.LngLat(lngX, latY));  
  
    var infoWindow = new AMap.InfoWindow({  
        content: "

<h3>" + d._name + "</h3>


" + "<img style=\"width:280px;height:180px;overflow:hidden;\" src='cainiao2.png' />

地址:" + d._address + "

" + "

电话:<a href=\"tel:" + d.telephone + "\">" + d.telephone + "</a>

<a href='http://mo.amap.com/?q=" + d._location.getLat() + "," + d._location.getLng() + "&name=" + d._name + "'>到这儿去</a>

",
        size:new AMap.Size(280, 0),  
        autoMove:true,  
        offset:new AMap.Pixel(0,-30),
        closeWhenClickMap: true        
    });    
    windowsArr.push(infoWindow);     
    var aa = function(){infoWindow.open(mapObj, mar.getPosition());};    
    AMap.event.addListener(mar, "click", aa);    
}
//回调函数-成功
function cloudSearch_CallBack(data) {
    clearMap();
    var resultStr="";
    var resultArr = data.datas;
    var resultNum = resultArr.length;
    for (var i = 0; i < resultNum; i++) {
        resultStr += "

<div class=\"item\">";
        resultStr += "

<h3>" + (i+1) + "、" + resultArr[i]._name + "</h3>


";
        resultStr += "

地址:" + resultArr[i]._address + "

";
        resultStr += "

电话:<a href=\"tel:" + resultArr[i].telephone + "\">" + resultArr[i].telephone + "</a>

";
        resultStr += "

地图:<a href='http://mo.amap.com/?q=" + resultArr[i]._location.getLat() + "," + resultArr[i]._location.getLng() + "&name=" + resultArr[i]._name + "'>到这里去</a>

";
        resultStr += "</div>


";
        addmarker(i, resultArr[i]); //添加大标注
    }
    if (document.getElementById('map').style.display !== 'none') {
        mapObj.setFitView();
    }
    document.getElementById("list").innerHTML = resultStr;
}
//回调函数-失败
function errorInfo(data) {
    resultStr = data.info;
    document.getElementById("list").innerHTML = resultStr;
}
//清空地图
function clearMap(){
    mapObj.clearMap();
    document.getElementById("list").innerHTML = '正在读取数据……';
}
// ]]></script>

demo网址(请用手机浏览器查看):http://zhaoziang.com/amap/cainiao.html

 

效果图:

 

六、其他云图教程

【支付宝中的全国家乐福地图】http://www.cnblogs.com/milkmap/p/3786144.html

【微信中的全国AMF海水农场地图】http://www.cnblogs.com/milkmap/p/3780417.html

【官网中的全国AMF海水农场地图】http://www.cnblogs.com/milkmap/p/3778398.html

【应用中webview形式的全国KTV地图】http://www.cnblogs.com/milkmap/p/3765925.html

 

【三甲医院】http://www.cnblogs.com/milkmap/p/3637899.html

【东莞地图】http://www.cnblogs.com/milkmap/p/3657829.html

【贪官落马图】http://www.cnblogs.com/milkmap/p/3678377.html

 

七、从零开始学高德JS API系列教程

【地图展现】http://www.cnblogs.com/milkmap/p/3687855.html

【控件】http://www.cnblogs.com/milkmap/p/3707711.html

【覆盖物】http://www.cnblogs.com/milkmap/p/3727842.html

【搜索服务】http://www.cnblogs.com/milkmap/p/3745701.html

【路线规划】http://www.cnblogs.com/milkmap/p/3755257.html

【坐标转换】http://www.cnblogs.com/milkmap/p/3768379.html

 

[转载]Android: 用jni 获取MAC地址 - Braincol - 博客园

mikel阅读(1064)

[转载]Android: 用jni 获取MAC地址 – Braincol – 博客园.

最近有个需求,需要在jni层获取Android设备的mac地址,google了一圈,没看到现成的实现方法,所以就只好自己写一个了。

基本思路是,通过jni调用Android java层的api,获取wifi的mac地址。理论上,所有的java代码都可以翻译成jni代码,所以应该可以实现。

 

首先来看看mac地址获取的java实现代码:

public String getLocalMacAddress(Context context) {
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
return info.getMacAddress();
}

代码相当简单。 就两个对象:WifiManager 和 WifiInfo对象,所以这个翻译成jni代码也不会有多复杂。

先在jni获取WifiManager 对象:

/*
* 获取WifiManager 对象
* 参数: jCtxObj 为Context对象
*/
jobject getWifiManagerObj(JNIEnv *env, jclass clz, jobject jCtxObj)
{
LOGI("gotWifiMangerObj ");
//获取 Context.WIFI_SERVICE 的值
//jstring jstr_wifi_serveice = env-&gt;NewStringUTF("wifi");
jclass jCtxClz= env-&gt;FindClass("android/content/Context");
jfieldID fid_wifi_service = env-&gt;GetStaticFieldID(jCtxClz,"WIFI_SERVICE","Ljava/lang/String;");
jstring jstr_wifi_serveice = (jstring)env-&gt;GetStaticObjectField(jCtxClz,fid_wifi_service);

jclass jclz = env-&gt;GetObjectClass(jCtxObj);
jmethodID mid_getSystemService = env-&gt;GetMethodID(jclz,"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
jobject wifiManager = env-&gt;CallObjectMethod(jCtxObj,mid_getSystemService,jstr_wifi_serveice);

//因为jclass 继承自 jobject,所以需要释放;
//jfieldID、jmethodID是内存地址,这段内存也不是在我们代码中分配的,不需要我们来释放。
env-&gt;DeleteLocalRef(jCtxClz);
env-&gt;DeleteLocalRef(jclz);
env-&gt;DeleteLocalRef(jstr_wifi_serveice);

return wifiManager;
}

然后,再获取WifiInfo对象:

/*
* 获取WifiInfo 对象
* 参数: wifiMgrObj 为WifiManager对象
*/
jobject getWifiInfoObj(JNIEnv *env, jobject wifiMgrObj)
{
LOGI("getWifiInfoObj ");
if(wifiMgrObj == NULL){
return NULL;
}
jclass jclz = env-&gt;GetObjectClass(wifiMgrObj);
jmethodID mid = env-&gt;GetMethodID(jclz,"getConnectionInfo","()Landroid/net/wifi/WifiInfo;");
jobject wifiInfo = env-&gt;CallObjectMethod(wifiMgrObj,mid);

env-&gt;DeleteLocalRef(jclz);
return wifiInfo;
}

现在只差最后一步了,调用WifiInfo的getMacAddress()方法:

/*
* 获取MAC地址
* 参数:wifiInfoObj, WifiInfo的对象
*/
char* getMacAddress(JNIEnv *env, jobject wifiInfoObj)
{
LOGI("getMacAddress.... ");
if(wifiInfoObj == NULL){
return NULL;
}
jclass jclz = env-&gt;GetObjectClass(wifiInfoObj);
jmethodID mid = env-&gt;GetMethodID(jclz,"getMacAddress","()Ljava/lang/String;");
jstring jstr_mac = (jstring)env-&gt;CallObjectMethod(wifiInfoObj,mid);
if(jstr_mac == NULL){
env-&gt;DeleteLocalRef(jclz);
return NULL;
}

const char* tmp = env-&gt;GetStringUTFChars(jstr_mac, NULL);
char* mac = (char*) malloc(strlen(tmp)+1);
memcpy(mac,tmp,strlen(tmp)+1);
env-&gt;ReleaseStringUTFChars(jstr_mac, tmp);
env-&gt;DeleteLocalRef(jclz);
return mac;
}

只需要把这三个过程串起来就ok了

jobject wifiManagerObj = getWifiManagerObj(env, clz, jCtxObj);
jobject wifiInfoObj = getWifiInfoObj(env,wifiManagerObj);
char * mac = getMacAddress(env,wifiInfoObj);

完整源码为:

http://download.csdn.net/detail/niosm/4409938

[转载]Android 获取WIFI MAC地址的方法 - OPEN 开发经验库

mikel阅读(993)

[转载]Android 获取WIFI MAC地址的方法 – OPEN 开发经验库.

1. 常用方法,调用Android的API:WifiManager

 

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

 

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
return info.getMacAddress();
 

此方法需要保证WIFI在本次开机以来曾经是打开过的,否则会返回null。所以需要后台尝试先打开WIFI再获取。

 

示例代码:

 

//尝试打开wifi
private static boolean tryOpenMAC(WifiManager manager)
{
boolean softOpenWifi = false;
int state = manager.getWifiState();
if (state != WifiManager.WIFI_STATE_ENABLED && state != WifiManager.WIFI_STATE_ENABLING)
{
manager.setWifiEnabled(true);
softOpenWifi = true;
}
return softOpenWifi;
}

 

//尝试关闭MAC
private static void tryCloseMAC(WifiManager manager)
{
manager.setWifiEnabled(false);
}

 

//尝试获取MAC地址
private static String tryGetMAC(WifiManager manager)
{
WifiInfo wifiInfo = manager.getConnectionInfo();
if (wifiInfo == null || StringUtil.isNull(wifiInfo.getMacAddress()))
{
return null;
}
String mac = wifiInfo.getMacAddress().replaceAll(“:”, “”).trim().toUpperCase();
mac = formatIdentify(mac);
return mac;
}

 

//尝试读取MAC地址
private static String getMacFromDevice(int internal)
{
String mac=null;
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
mac = tryGetMAC(wifiManager);
if(!StringUtil.isNull(mac))
{
return mac;
}

//获取失败,尝试打开wifi获取
boolean isOkWifi = tryOpenMAC(wifiManager);
for(int index=0;index<internal;index++)
{
//如果第一次没有成功,第二次做100毫秒的延迟。
if(index!=0)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
mac = tryGetMAC(wifiManager);
if(!StringUtil.isNull(mac))
{
break;
}
}

 

//尝试关闭wifi
if(isOkWifi)
{
tryCloseMAC(wifiManager);
}
return mac;
}

 

 

 

==================================================================

 

2. 查询文件路径 /sys/class/net/wlan0/address

 

adb shell cat /sys/class/net/wlan0/address

 

98:6c:f5:10:96:c4

 

但是如果WIFI在本次开机期间从来没有打开过,返回的MAC地址是不同的(非实际的),如下:

 

cat /sys/class/net/wlan0/address
00:90:4c:11:22:33

 

 

 

示例代码:

 

String getMac() {
String macSerial = null;
String str = “”;
try {
Process pp = Runtime.getRuntime().exec(“cat /sys/class/net/wlan0/address”);
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
LineNumberReader input = new LineNumberReader(ir);

 

for (; null != str;) {
str = input.readLine();
if (str != null) {
macSerial = str.trim();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return macSerial;
}
==================================================================

 

3. 查询记录了MAC地址的文件“/proc/net/arp”,但是从测试结果看,返回的数据并不是想要的Wifi Mac地址:

 

比如,手机实际的WIFI Mac地址是98:6c:f5:10:96:c4,但使用adb shell cat proc/net/arp返回的是:

cat proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.0.3      0x1         0x2         00:23:89:b9:1a:fd     *        wlan0
192.168.0.1      0x1         0x2         08:00:27:7c:65:5a     *        wlan0

[转载].net程序调试一:快速定位异常 - 雨林 - 博客园

mikel阅读(1116)

[转载].net程序调试一:快速定位异常 – 雨林 – 博客园.

作为一个程序员,解BUG是我们工作中常做的工作,甚至可以说解决问题能力是一个人工作能力的重要体现。因为这体现了一个程序员的技术水平、技术深度、经验等等。

那么在我们解决BUG的过程中,定位问题是非常重要的。有句话叫”发现问题是解决问题的一半。

本文讲述就快速定位异常(专指.NET程序异常)的方法。包括在本机定位异常,在客户环境定位.net程序异常,在客户环境定位SilverLight异常。

一:定位本机异常

在我们本机定位异常很容易。假设我们都是使用的的VisualStudio,那么只需要在调试->异常菜单中将Common Langeuage Runtime Exception(CLR异常)勾选。如下图:

在上面的图片中可以发现有5种类型的异常,例如c++异常、win32异常等等。对于.NET程序来说我们只关注CLR异常。

接下来进行调试,当自己的程序代码中有异常的时候,VS就会自动定位到异常的位置。

我们可以看到异常的详细信息,并且可在调用堆栈窗口中看到 程序的堆栈信息。在堆栈信息中我们可以看到在哪个类、哪个函数中出的错,如下图:

 

调试程序有两种方式,一种是用VS直接启动程序,另一种是附加到进程。

 

附加到进程的时候,程序类型不要选错了,我使用的是.net4.0 所以程序类型选择的是 托管(4.0版)代码。

另外附加到进程有个快捷键是 Ctrl+Alt+P。

但是如果异常不是你的代码中抛出的,那么如何定位呢?

可以打开 调试 菜单下面的 选项和设置,将 启用”仅我的代码” 这一项取消勾选。那么别人代码中的异常就可以抛出了。

 

二:在客户环境定位.net程序异常:

我们的程序最后都会运行在客户的环境中,客户环境上不会有VS这样的开发工具,那么怎么办呢?

我们可以使用一个很小巧的命令行调试工具Mdbg.exe,这个工具是安装VS的时候附带安装的,仅能调试.net托管代码。

Mdbg.exe其实有很多功能,不过本文只讲它定位异常的功能,后续文章会讲使用Mdbg.exe单步调试的方法。

Mdbg.exe命令详细介绍可以 输入 h(help) 或者? 名来查看,也可以看下面的链接,

http://msdn.microsoft.com/zh-cn/ms229861(vs.80).aspx#

根据CLR版本的不用,Mdbg.exe也是有多个版本的。

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\Mdbg.exe用于调试

CLR2.0(对应net2.0,3.0,3.5)程序。

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\Mdbg.exe用于调试CLR4.0程序(对用.net4.0)。

另外Mdbg.exe有一个依赖DLL 叫做MdbgCore.dll。我们可以直接将相应版本的Mdbg.exe和MdbgCore.dll拷贝到客户机器上使用。

没有安装VS的朋友可以拷贝我自己封装的一个安装包 http://files.cnblogs.com/yuilin/U8DebugSetup.rar,这里面除了Mdbg.exe还有一些其他组件我们后面的文章会用到。

默认会安装在 C:\Program Files\U8Debug

Mdbg.exe的使用方法很加简,双击打开它,然后输入 a(attach显示附加的进程),回车,这时会列表所有可以附加的进程。

 

PID 表示进程标识,

输入a 11940 附件到 ConsoleApplication2.ex示例程序。

这时程序会中断执行,我们在这个时机可以做一些设置。让程序在遇到异常时自动中断。

输入命令 ca (catch)查看当前调试器遇到哪些事件会中断。

 

可以看到 Exception对应的是Igonre all exception ,也就是忽略所有异常,发生异常时不会中断。

输入命令 ca ex 这样调试器遇到异常时就会中断了。

再次输入ca 命令会看到 Exception对应的值已经变为Stop on all exception了。这时遇到任何异常都会中断了。

 

输入命令 g 让程序继续执行。

当遇到异常时会自动中断到调试器,如下图:

 

入命令 w(where,程序运行到哪里了) 可以查看异常堆栈信息

 

三:在客户环境定位SilverLight异常

如果客户的silverlight应用服务器部署在外网,那么我们可以直接用浏览器访问该silverlight站点,然后用VS附加到浏览器进程来调试。

 

调试方法比调试普通.net程序一样。

但是如果,客户的Silverlight服务器是部署在内网,那么你只能在客户机器上调试了。

并且Mdbg.exe也帮不了你了,它不能调试Silverlight程序。

我们还有另一个著名的调试工具Windbg。体积大概有不到20M,很容易安装到客户机,安装包大家可以到网上自己下载。windbg分为32位和64位两个版本,

调试32位的程序请使用32位windbg,反之则要使用64位的windbg,具体为什么我们不用深究,记住了就可以了。

相比Mdbg.exe的小巧实用,Windbg显然强大的多,但是使用起来也复杂一些。

Windbg其实可以调试很多种类型的程序,例如普通.NET程序,c++等。但是本文只讲解使用windbg定位异常的方法。

首先我们使用IE浏览器打开silverlight应用程序,然后打开windbg附件到IE进程来调试。附加进程的方式可以通过File菜单下的Attach to a process或者使用F6快捷键。

 

附件进程后 程序会中断到调试器,这个时候我们需要做两个设置。

一个是 设置程序发生异常时让其中断到调试器,设置方法是打开Debug菜单下的Event Filter,将CLR异常设置其为enable。

 

另外需要加载调试器扩展,使用过windbg的朋友都知道调试.net程序需要加载一个调试器扩展sos.dll。这个sos.dll也有一个Silverlight版本的。

位置在silverlight的安装目录 C:\Program Files (x86)\Microsoft Silverlight\5.1.10411.0\sos.dll。

我们再command窗口中输入 .load C:\Program Files (x86)\Microsoft Silverlight\5.1.10411.0\sos.dll 来加载它。

之后输入命令 g 来回复程序的执行。当发生异常时就会中断到调试器中。

发生异常是我们可以使用!pe(print exception) 来查看异常信息。如下图:

 

如果想查看堆栈信息的话可以输入命令 !clrstack

通过上述方法基本可以定位所有的.NET异常。至此,本文结束。

[转载]安卓模拟器bluestacks mac地址修改教程 实测可用_口袋巴士

mikel阅读(1813)

[转载]安卓模拟器bluestacks mac地址修改教程 实测可用_口袋巴士.  很多朋友都很喜欢使用bluestacks来玩安卓游戏,但是我们都知道,很多安卓网游都是需要使用到MAC地址的,所以如何找到并修改 bluestacks mac地址是很重要的,本篇教程就是教大家如何找到并修改或者更正bluestacks mac地址,有兴趣的朋友可以来学习下。
首先放出几张截图,是修改过MAC地址后的截图:

 

准备工具

 

文件名称

文件大小

下载地址
MAC地址修改器

6KB

点击下载

 

bluestacks mac地址修改教程:

1、然后正式开始教程,注意,首先确保你的安卓模拟器bluestacks已经完全关闭,如果你是老版本的模拟器,还需要在任务管理器中将模拟器进程杀掉,如果是最新版本的,直接点击“离开”就可以了;

注意:如果不完全关闭BS模拟器,会造成MAC地址修改失败。
2、然后下载并解压bluestacks mac地址修改器;

3、bluestacks mac地址修改第3步,然后找到MAC地址修改器.exe这个程序,双击运行,会出现下图这个界面;

 

  运行后会出现下图这个界面:

 

4、然后我们先点击“生成GUID”,再点击生成“IMEI”;

5、最后点击“写入注册表”即可。

这样就成功修改了bluestacks mac地址,接下来我们只需要重启模拟器就可以了。
注意:以后如果你想要修改IMEI码,都需要关闭并重启MAC地址修改器.exe这个工具才可以。此外MAC地址修改完毕后,使用RE管理器或bluestacks mac地址修改者是ES管理器都可以查看模拟器的MAC地址变动。
本篇bluestacks mac地址修改教程到这里就结束了,希望可以帮助到大家哦。

[转载]Android中使用RadioButton代替ImageButton - wavky - 博客园

mikel阅读(1199)

[转载]Android中使用RadioButton代替ImageButton – wavky – 博客园.

画外音————好久没上来发文章了,这几个月一直忙着一些跟编程不沾边的事,拖了好久,现在还在持续中,顺利的话7月份应该能解放了。。今天偶尔上来写一段番外篇性质的心得发现。


 

之前搞的Android项目,作为底部导航工具栏,一直用的是普通的ImageButton,搭配几张漂亮的图片,写写监听器就完事,效果看下面的 图,虽然简单,但是有一个不太好的缺点,那就是导航到新的页面的时候,都要手动处理这个按钮的点击状态(让它高亮底图)和其它按钮的点击状态(让之前的退 出高亮),这个处理过程既繁琐又容易遗漏出错等等等等..

 

受同事启发,使用RadioGroup和RadioButton就能自动化的解决上面的问题,因为本质上一个RadioGroup内只允许一个 RadioButton处于选择状态之下(高亮),点击了同一组的其它RadioButton,之前的RadioButton就会自动被处理掉,而且当前 RadioButton选择状态会自动保留,根本不需要再像之前的ImageButton那样一个个写处理代码,既美观又环保。

想法很不错,动手开干,但是又发现了一个新问题:RadioButton的样式在不同的系统版本表现不一样!下面拿这个超萌的猪头来说明情况。

素材图片:

RadioButton布局脚本:


其中 Android:button=”@null” 这句很重要,用来消除掉RadioButton标配的圆圈单选按钮!

而 android:drawablePadding=”-20dp” 是用来去掉标配分给RadioButton文本的空位,当图片素材画在了drawableTop上面时,对应的文本会出现在下方,如果不需要填入文本,就用这行代码去掉空位;如果选择画在drawableLeft的话,就不需要这一行。

 

具体来说分两种情况,一种是API17(4.2.2)中的表现:

另外一种是API14(4.0)以及它之下的各版本(如API8)中的表现:

   

上面API14和API8的效果是一样的,跟API17对比很明显,就是图片的左边多了一个空位!!这个位置无论怎么调padding、margin之类的参数都无法完全消除掉,很恶心。

至于API17-API14之间到底是哪个系统版本成了分水岭,这个就不得而知了,笔主这边编译环境没有安装更多的版本了,也懒得去研究。

 

上面这个问题找了好久都没找到原因,甚至于笔主都漫无目的的百度搜索有木有针对不同系统版本使用不同布局文件的方法了…

理所当然的一个但是,笔主本着不依不饶的顽强精神再次检查RadioButton布局属性参数,幸运女神终于降临了,笔主发现一个隐藏已久的陷阱:background!! 这个属性在API17的时候是空的,但是  在API14以下竟然默认配置成了 @android:drawable/btn_radio_label_background !!!既然发现了问题,笔主就二话不说直接填上伟大的 @null ,F5刷新一下屏幕..果不其然,一切又回归自然了!

(左右那俩二货没有弄background,所以还是那副鸟样)

 

处理后的RadioButton布局代码是:


RadioGroup开始的整体代码是:(上面的RadioButton参数被我放到了style文件里面)


&nbsp;

&nbsp;

开头所说的选择的时候高亮状态,需要设置相应的selector处理图片素材,这里就不详细说明了。

至此,RadioButton已经能够透明的代替ImageButton了,向下兼容至API8,并带入自动标记高亮单项选择功能,做导航的话应该比单纯的ImageButton更具优势吧,呵呵。

 

ps. 因为需要动态增减RadioButton等原因,在代码中设置新RadioButton对象的属性可参考以下博文:

Android中代码设置RadioButton的高端技巧

[转载]自己动手搞定支付宝手机网站支付接口 FOR ECShop - x3d - 博客园

mikel阅读(834)

[转载]自己动手搞定支付宝手机网站支付接口 FOR ECShop – x3d – 博客园.

支付宝WAP网站版本的支付接口网上整合的比较少,看到很多网站在卖,顿觉无语。

主要是得自己查看支付宝官方提供的SDK中的开发文档。

支付宝sdk下载地址:http://club.alipay.com/read-htm-tid-9976972.html

 

1. 要使用支付宝手机网站支付接口,除了要配置基本的帐号外,还必须配置openssl密钥文件。关于key的生成,一定要看文档,在此不详述。文档上演示的在线上传key的界面地址为:https://mobiless.alipay.com/home/index.htm ,key一定要存在,而且地址要正确,不然支付宝那边不能返回有效的界面

2.以独立的支付接口形式提供,便于用户根据自己的需求再做定制;

3. 附件提供的代码是简单的集成,仅起一个演示作用,没有考虑代码的复用性之类

 

ecshop支付宝手机网站支付接口下载地址: http://files.cnblogs.com/x3d/ecshop_payment_alipay_wap.zip

本文来源:http://www.cnblogs.com/x3d/,转载请注明。