androidify(androidify是什么)
一、android开发支付宝付款实时通知是怎么实现的
到支付宝官网,下载支付宝集成开发包,看懂里面的关键代码
由于android设备一般用的都是无线支付,所有我们申请的就是支付宝无线快捷支付接口。
如果链接失效,你可以到支付宝官网商家服务模块中找到快捷支付(无线)这个服务。
下载集成开发包,解压发现里面有客户端的demo即说明文档,在客户端的demo中找到Android_SDK,这个就是你要用到的支付宝接口及demo。
把demo(alipay_sdk_demo)和(alipay_lib)导入到你的eclipse里面,然后你可以试着运行一遍demo(alipay_sdk_demo),只要把这个demo搞懂了,你就会调用这个支付宝接口了。至于到时候如何集成到你的项目里面,文档上说明很详细,按着文档上一步一步来就行了。我的建议是先把这个demo弄懂再设计你的项目,看看调用接口时需要哪些数据,这样也有利于你一开始设计数据。
下面来简单的介绍下接口demo里面的结构。
你打开项目会发现里面有5个类。
其中,Base64.java、Result.java、Rsa.java这3个类不需要动,需要用到的,到时候直接放到你项目里面就行了,如果你想了解下它们你也可以看看。重点就是ExternalPartner.java和Keys.java这两个类。先来说说Keys.java类吧。
Key.java这个类等你申请支付宝签约成功后再配置,先放在这不用管,如何配置我注释里面已经的很明白了。
然后是ExternalPartner.java这个类。这个类其实也很简单,你运行这个demo会发现就是一个listview里面加载的很多商品信息,点击一款商品就调用会支付宝接口(因为Key.java未配置,所以你现在估计调用不成功)。我们找到listview的点击事件的方法就找到调用支付宝的入口了
kagecom.alipay.android.msp.demo;
importjava.io.IOException;
........
........
importcom.alipay.android.app.sdk.AliPay;
publicclassExternalPartnerextendsActivityimplementsOnItemClickListener,
OnClickListener{
publicstaticfinalStringTAG="alipay-sdk";
privatestaticfinalintRQF_PAY=1;
privatestaticfinalintRQF_LOGIN=2;
privateEditTextmUserId;
privateButtonmLogon;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.external_partner);
initProducts();
initListView();
}
/*
*(non-Javadoc)
*
*@seeandroid.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
publicbooleanonCreateOptionsMenu(Menumenu){
menu.add(Menu.NONE,Menu.FIRST,1,"快速登录");
returntrue;
}
/*
*(non-Javadoc)
*
*@seeandroid.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
switch(item.getItemId()){
caseMenu.FIRST:
setContentView(R.layout.trustlogin);
mUserId=(EditText)findViewById(R.id.user_id);
mLogon=(Button)findViewById(R.id.get_token);
mLogon.setOnClickListener(this);
break;
}
returnfalse;
}
privatevoidinitProducts(){
if(sProducts!=null)
return;
XmlResourceParserparser=getResources().getXml(R.xml.products);
ArrayList<Product>products=newArrayList<Product>();
Productproduct=null;
try{
inteventType=parser.getEventType();
while(eventType!=XmlPullParser.END_DOCUMENT){
if(eventType==XmlPullParser.START_TAG
&&parser.getName().equalsIgnoreCase("product")){
product=newProduct();
product.subject=parser.getAttributeValue(0);
product.body=parser.getAttributeValue(1);
product.price=parser.getAttributeValue(2);
products.add(product);
}
eventType=parser.next();
}
sProducts=newProduct[products.size()];
products.toArray(sProducts);
}catch(XmlPullParserExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
//listview点击事件,里面调用的支付宝接口
@Override
publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intposition,
longarg3){
try{
Log.i("ExternalPartner","onItemClick");
Stringinfo=getNewOrderInfo(position);//这个是订单信息
Stringsign=Rsa.sign(info,Keys.PRIVATE);//签名加密订单信息什么的
sign=URLEncoder.encode(sign);
info+="&sign=\""+sign+"\"&"+getSignType();
Log.i("ExternalPartner","startpay");
//startthepay.
Log.i(TAG,"info="+info);
finalStringorderInfo=info;
newThread(){
publicvoidrun(){
AliPayalipay=newAliPay(ExternalPartner.this,mHandler);//这个应该就是支付宝接口了,哈哈,支付宝现在把很多功能都封装了,所以省了很多代码
//设置为沙箱模式,不设置默认为线上环境
//alipay.setSandBox(true);
Stringresult=alipay.pay(orderInfo);//这个是返回的结果,你到时候可以根据这个结果加以操作你想操作的,然后基本就完了,其他的你想附加的功能你看着写吧,现在Key.java配置好就能调用快捷支付了
//后面的这些代码可以改成你自己的,也可以在它们的基础上改
Log.i(TAG,"result="+result);
Messagemsg=newMessage();
msg.what=RQF_PAY;
msg.obj=result;
mHandler.sendMessage(msg);
}
}.start();
}catch(Exceptionex){
ex.printStackTrace();
Toast.makeText(ExternalPartner.this,R.string.remote_call_failed,
Toast.LENGTH_SHORT).show();
}
}
//获得订单信息的方法
privateStringgetNewOrderInfo(intposition){
StringBuildersb=newStringBuilder();
sb.append("partner=\"");
sb.append(Keys.DEFAULT_PARTNER);//合作身份者id
sb.append("\"&out_trade_no=\"");
sb.append(getOutTradeNo());//这个是订单编号
sb.append("\"&subject=\"");
sb.append(sProducts[position].subject);//这个应该是商品名称
sb.append("\"&body=\"");
sb.append(sProducts[position].body);//这个应该是商品的描述,具体你可以参考demo
sb.append("\"&total_fee=\"");
sb.append(sProducts[position].price.replace("一口价:",""));//这个是要付款的金额,到时候你调用的时候改下就行了
sb.append("\"¬ify_url=\"");
//网址需要做URL编码
sb.append(URLEncoder.encode(""));//服务器异步通知页面,完成交易后通知商家服务器的页面,以post的形式将商品订单信息发送到指定页面,手机客户端不需要可以先放在这不管。
是不是,这个类很简单看懂吧,就一listview。调用支付宝接口的方法就在onItemClick()方法里面,如果你是一个按钮的话换成按钮点击事件就行了,主要的细节我注释已写。现在你要想的是,需要哪些数据,提供给onItemClick()方法里面的Stringinfo。demo里面的数据是getNewOrderInfo(intposition)这个方法提供的,你可以自己提供或者在上面修改下。
现在,你已经知道代码是如何调用支付宝接口了。接下来,是如何把这些集成到你的项目中去。
二、android 是怎么通过在XML中配置的控件属性得到具体的view对象
我可能表达的不是很清楚,那就拿个具体的例子来说明吧
比如说,在Activity中我们需要用到一个ProgressBar控件,我们一般先在layout下的main.xml中进行配置
Xml代码
<ProgressBar
android:id="@+id/pb1"
android:layout_width="fill_parent"
android:layout_height="20dip"
<span style="color:#ff0000;"> android:indeterminateOnly="false"</span>
android:layout_gravity="center_vertical"
android:progressDrawable="@android:drawable/progress_horizontal"
android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal"
android:minHeight="20dip"
android:maxHeight="20dip"
/>
我们看 android:indeterminateOnly="false"这行代码的
一般我们如果要将在代码中创建一个ProgressBar,但是不通过配置文件得到。
代码如下:
Java代码
ProgressBar mProgressBar=new ProgressBar(context);
<span style="color:#ff0000;">mProgressBar.setIndeterminate(false);</span>
mProgressBar.setProgressDrawable(getResources().getDrawable
(android.R.drawable.progress_horizontal));
mProgressBar.setIndeterminateDrawable(getResources().getDrawable
(android.R.drawable.progress_indeterminate_horizontal));
本来我们是希望创建一个普通的能显示进度的横条ProgressBar
但是我们发现progressBar中的进度无法更新。
我们来看进度更新的源代码setProgress():
Java代码
@android.view.RemotableViewMethod
synchronized void setProgress(int progress, boolean fromUser){
<span style="color:#ff0000;"> if(mIndeterminate){
return;
}</span>
if(progress< 0){
progress= 0;
}
if(progress> mMax){
progress= mMax;
}
if(progress!= mProgress){
mProgress= progress;
refreshProgress(R.id.progress, mProgress, fromUser);
}
}
关键是: if(mIndeterminate){ return;}
原来mIndeterminate的值为true的话,函数直接返回了,也就是我们不能设置progressBar的进度(mProgress)
现在我们的任务是将mIndeterminate属性设置为false
但是我们发现 mProgressBar.setIndeterminate(false);这行代码并没有设置mIndeterminate属性为false
我们看ProgressBar中的源代码:
Java代码
@android.view.RemotableViewMethod
public synchronized void setIndeterminate(boolean indeterminate){
<span style="color:#ff0000;"> if((!mOnlyIndeterminate||!mIndeterminate)&& indeterminate!= mIndeterminate){</span>
mIndeterminate= indeterminate;
if(indeterminate){
// swap between indeterminate and regular backgrounds
mCurrentDrawable= mIndeterminateDrawable;
startAnimation();
} else{
mCurrentDrawable= mProgressDrawable;
stopAnimation();
}
}
}
看这行代码: if((!mOnlyIndeterminate||!mIndeterminate)&& indeterminate!= mIndeterminate){
我们发现当mOnlyIndeterminate和mIndeterminate之前都为true时,我们并不能将mIndeterminate从true改变为false
google后,有人通过反射机制将ProgressBar中的mOnlyIndeterminate设置为false(具体请看:关于使用代码来创建ProgressBar)
我现在我就在想既然 ProgressBar中的mOnlyIndeterminate和mIndeterminate属性都是private,而且都不能通过get和set方法来对其进行操作,那么 android通过在XML中配置的控件属性,是怎么被转换成真正的java类呢?
求大神解惑!
问题补充
over140写道
你应该看一下他源码里关于这个的构造函数部分的代码,注意父类里面可能也有代码,他并不是转换成java类,只是读取从XML属性读取想要的参数。
你指的是ProgressBar类中的构造函数吗?我之前就仔细看了这些东西
ProgressBar中构造函数源码:
Java代码
/**
* Create a new progress bar with range 0...100 and initial progress of 0.
*@param context the application environment
*/
public ProgressBar(Context context){
this(context, null);
}
public ProgressBar(Context context, AttributeSet attrs){
this(context, attrs, com.android.internal.R.attr.progressBarStyle);
}
public ProgressBar(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
mUiThreadId= Thread.currentThread().getId();
initProgressBar();
TypedArray a=
context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyle, 0);
mNoInvalidate= true;
Drawable drawable= a.getDrawable(R.styleable.ProgressBar_progressDrawable);
if(drawable!= null){
drawable= tileify(drawable, false);
setProgressDrawable(drawable);
}
mDuration= a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);
mMinWidth= a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
mMaxWidth= a.getDimensionPixelSize(R.styleable.ProgressBar_maxWidth, mMaxWidth);
mMinHeight= a.getDimensionPixelSize(R.styleable.ProgressBar_minHeight, mMinHeight);
mMaxHeight= a.getDimensionPixelSize(R.styleable.ProgressBar_maxHeight, mMaxHeight);
mBehavior= a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);
final int resID= a.getResourceId(
com.android.internal.R.styleable.ProgressBar_interpolator,
android.R.anim.linear_interpolator);// default to linear interpolator
if(resID> 0){
setInterpolator(context, resID);
}
setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
setSecondaryProgress(
a.getInt(R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
drawable= a.getDrawable(R.styleable.ProgressBar_indeterminateDrawable);
if(drawable!= null){
drawable= tileifyIndeterminate(drawable);
setIndeterminateDrawable(drawable);
}
mOnlyIndeterminate= a.getBoolean(
R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);
mNoInvalidate= false;
setIndeterminate(mOnlyIndeterminate|| a.getBoolean(
R.styleable.ProgressBar_indeterminate, mIndeterminate));
a.recycle();
}
看以上代码,发现ProgressBar类并没有使用其父类的构造方法,它的三个构造方法最终都需要进入到第三个构造方法内,
再看这一句
Java代码
initProgressBar();
其中具体源码如下:
Java代码
private void initProgressBar(){
mMax= 100;
mProgress= 0;
mSecondaryProgress= 0;
mIndeterminate= false;
mOnlyIndeterminate= false;
mDuration= 4000;
mBehavior= AlphaAnimation.RESTART;
mMinWidth= 24;
mMaxWidth= 48;
mMinHeight= 24;
mMaxHeight= 48;
}
看这两句:
Java代码
mIndeterminate= false;
mOnlyIndeterminate= false;
奇怪在这个初始化ProgressBar的过程中,明明将mIndeterminate和mOnlyIndeterminate属性设置为false
但是我们初始化后的进度条,显示后同样是不会进度的(图如下)
也就是说 mIndeterminate属性依然是true(具体请看ProgressBar中的setProgress()方法)
继续看构造方法中的其他内容时,发现关键所在:
Java代码
mOnlyIndeterminate= a.getBoolean(
R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);
mNoInvalidate= false;
setIndeterminate(mOnlyIndeterminate|| a.getBoolean(
R.styleable.ProgressBar_indeterminate, mIndeterminate));
这两句将mOnlydeterminate和mIndeterminate属性都设置为true,
看到这里,发现这两句都用到 a这个对象,a具体是什么呢?
Java代码
TypedArray a=
context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyle, 0);
那我们能不能通过改变传入构造函数的参数来使 a发生相应的变化,进而使mOnlyIndeterminate和mIndeterminate属性设置为 true呢?
再往下深入,发现看的我那是一头雾水,完全找不到方向,所以只得放弃这个猜想。
到最后,我发现如果要通过正常的java访问机制(当然排除使用反射机制),来操作mOnlyIndeterminate和mIndeterminate属性是不可能的,
你说:他并不是转换成java类,只是读取从XML属性读取想要的参数。
我们一般是通过findViewById()来根据layout中的XML文件设置的控件属性得到具体的View控件对象(关于转换成java类,我错了,其实我想说的是怎么得到的这个对象),
这个过程是不是也是通过反射机制来完成的?假如是的话,能给我提供些具体过程的资料呢?