安卓开发学习笔记。
Mar 27
 

禁止屏幕随手机旋转变化

有时候我们希望让一个程序的界面始终保持在一个方向,不随手机方向旋转而变化:
在AndroidManifest.xml的每一个需要禁止转向的Activity配置中加入 android:screenOrientation=”landscape” 属性。

landscape = 横向
portrait = 纵向

避免在转屏时重启Activity

android中每次屏幕方向切换时都会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次 Create的时候载入配置,那样,进行中的游戏就不会自动重启了!
要避免在转屏时重启Activity,可以通过在AndroidManifest.xml文件中重新定义方向(给每个Activity加上 android:configChanges=”keyboardHidden|orientation”属性)。
在需要控制屏幕显示方向的Activity中重写 onConfigurationChanged(Configuration newConfig)方法,这样在转屏时就不会重启Activity了。

01if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
02  
03        //横向
04        setContentView(R.layout.file_list_landscape);
05  
06}else{
07  
08        //竖向
09         setContentView(R.layout.file_list);
10  
11}

在模拟器中可以按 CTL+F11 模拟做屏幕旋转。

Tags:
Feb 13
Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之间相互通信。为了实现进程之间的相互通信,Andorid采用了一种轻量级的实现方式RPC(Remote Procedure Call 远程进程调用)来完成进程之间的通信,并且Android通过接口定义语言(Andorid Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码,例如,你在Activity里的代码需要访问Service中的一个方法,那么就可以通过这种方式来实现了。

   AIDL是Android的一种接口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成 AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象。

   AIDL RPC机制是通过接口来实现的,类似Windows中的COM或者Corba,但他是轻量级的,客户端和被调用实现之间是通过代理模式实现的,代理类和被代理类实现同一个接口Ibinder接口。

下面是实现Activity访问Service例子的步骤:

一.创建.aidl文件

    AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。重要的是必须导入导入除了内建类型(例如:int,boolean等)外的任何其他类型,哪怕是这些类型是在与接口相同的包中。具体的要求如下:

  • JAVA基本数据类型不需要导入
  • String,List,MapCharSequence不需要导入

使用Eclipse的ADT插件创建一个BookInfo.aidl文件,该文件有4个方法:

setName(String name)设置图书的书名,setPrice(int price)设置图书的价格,setPublish(String pname)设置图书的出版社和String display()显示图书的信息.

BookInfo.aidl文件

  1. package com.Android.aidl;  
  2.  
  3. //BookInfo接口  
  4. interface BookInfo{  
  5.       
  6.     void setName(String name);  
  7.     void setPrice(int price);  
  8.     void ssetPublish(String pname);  
  9.     //显示图书的信息  
  10.     String display();  

创建好BookInfo.aidl文件,系统会自动在gen目录下生成Java接口文件BookInfo.java



二.实现AIDL文件生成的JAVA接口

    AIDL会生成一个和.aidl文件同名的JAVA接口文件,该接口中有一个静态抽象内部类Stub,该类中声明了AIDL文件中定义的所有方法,其中有一个重要的方法是asInterface(),该方法通过代理模式返回JAVA接口的实现我们可以定义一个实现类,BookImpl,该类继承Stub 类,实现我们定义的4个方法

  1. package com.Android.aidl;  
  2. import Android.os.RemoteException;  
  3.  
  4. public class BookInfoImpl extends BookInfo.Stub {  
  5.     //声明三个个变量  
  6.     private int price;  
  7.     private String name,pname;  
  8.     //显示书名,价格,出版社  
  9.     public String display() throws RemoteException{  
  10.         return "书名:"+name+";价格:"+price+";出版社:"+price;  
  11.     }  
  12.     @Override 
  13.     //设置书名  
  14.     public void setName(String name) throws RemoteException {  
  15.         // TODO Auto  
  16.         this.name= name;  
  17.     }  
  18.  
  19.     @Override 
  20.     //设置价格  
  21.     public void setPrice(int price) throws RemoteException {  
  22.         // TODO Auto-generated method stub  
  23.         this.price = price;  
  24.     }  
  25.     @Override 
  26.     //设置出版社  
  27.     public void setPublish(String pname) throws RemoteException {  
  28.         // TODO Auto  
  29.         this.pname= pname;  
  30.     }     
  31. }  

三.向客户端暴露接口

现在已经实现了BookInfo接口,接下来要将该接口暴露给客户端调用。一般通过定义一个Service来实现,在Service的onBind()方法中返回该接口,当我们绑定该接口时调用该方法。

  1. package com.Android.aidl;  
  2.  
  3. import com.Android.aidl.BookInfo.Stub;  
  4. import Android.app.Service;  
  5. import android.content.Intent;  
  6. import Android.os.IBinder;  
  7.  
  8. public class RemoteService extends Service {  
  9.     //声明BookInfo接口  
  10.     private Stub bookifo = new BookInfoImpl();  
  11.     public IBinder onBind(Intent intent){  
  12.         return bookifo;  
  13.     }  

四.在客户端调用

定义一个Activity来绑定远程Service,获得BookInfo接口,通过RPC机制调用接口中的方法。

  1. package com.Android.aidl;  
  2.  
  3. import Android.app.Activity;  
  4. import Android.app.Service;  
  5. import android.content.ComponentName;  
  6. import Android.content.Intent;  
  7. import android.content.ServiceConnection;  
  8. import Android.os.Bundle;  
  9. import android.os.IBinder;  
  10. import Android.os.RemoteException;  
  11. import android.view.View;  
  12. import Android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14. import Android.widget.Toast;  
  15.  
  16. public class MainActivity extends Activity {  
  17.     // 声明IPerson接口  
  18.     private BookInfo bookInfo;  
  19.     // 声明 Button  
  20.     private Button btn;  
  21.     // 实例化ServiceConnection  
  22.     private ServiceConnection conn = new ServiceConnection() {  
  23.         @Override 
  24.         synchronized public void onServiceConnected(ComponentName name, IBinder service) {  
  25.             // 获得IPerson接口  
  26.             bookInfo = BookInfo.Stub.asInterface(service);  
  27.             if (bookInfo != null)  
  28.                 try {  
  29.                     // RPC 方法调用  
  30.                     bookInfo.setName("Google Android SDK开发范例大全");  
  31.                     bookInfo.setPrice(55);  
  32.                     bookInfo.setPublish("人民邮电出版社");  
  33.                     String msg = bookInfo.display();  
  34.                     // 显示方法调用返回值  
  35.                     Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG)  
  36.                             .show();  
  37.                 } catch (RemoteException e) {  
  38.                     e.printStackTrace();  
  39.                 }  
  40.         }  
  41.  
  42.         @Override 
  43.         public void onServiceDisconnected(ComponentName name) {  
  44.  
  45.         }  
  46.     };  
  47.  
  48.     @Override 
  49.     public void onCreate(Bundle savedInstanceState) {  
  50.         super.onCreate(savedInstanceState);  
  51.         // 设置当前视图布局  
  52.         setContentView(R.layout.main);  
  53.         // 实例化Button  
  54.         btn = (Button) findViewById(R.id.Button1);  
  55.         //为Button添加单击事件监听器  
  56.         btn.setOnClickListener(new OnClickListener() {  
  57.             @Override 
  58.             public void onClick(View v) {  
  59.                 // 实例化Intent  
  60.                 Intent intent = new Intent();  
  61.                 // 设置Intent Action 属性  
  62.                 intent.setAction("com.Android.aidl.action.MY_REMOTE_SERVICE");  
  63.                 // 绑定服务  
  64.                 bindService(intent, conn, Service.BIND_AUTO_CREATE);  
  65.             }  
  66.         });  
  67.     }  

五.main.xml和AndroidManifest.xml文件

main.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="vertical" 
  4.     Android:layout_width="fill_parent" 
  5.     android:layout_height="fill_parent" 
  6.     > 
  7.     <Button   
  8.         Android:text="远程调用Service"   
  9.         android:id="@+id/Button1"   
  10.         Android:layout_width="wrap_content"   
  11.         android:layout_height="wrap_content" 
  12.         /> 
  13. </LinearLayout> 

AndroidManifest.xml文件16~20声明Service

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <manifest xmlns:Android="http://schemas.android.com/apk/res/android" 
  3.       package="com.android.aidl" 
  4.       Android:versionCode="1" 
  5.       android:versionName="1.0"> 
  6.     <uses-sdk Android:minSdkVersion="10" /> 
  7.  
  8.     <application Android:icon="@drawable/icon" android:label="@string/app_name"> 
  9.         <activity android:name=".MainActivity" 
  10.                   Android:label="@string/app_name"> 
  11.             <intent-filter> 
  12.                 <action Android:name="android.intent.action.MAIN" /> 
  13.                 <category android:name="android.intent.category.LAUNCHER" /> 
  14.             </intent-filter> 
  15.         </activity> 
  16.      <service Android:name="RemoteService"> 
  17.             <intent-filter> 
  18.                 <action Android:name="com.android.aidl.action.MY_REMOTE_SERVICE"/> 
  19.             </intent-filter> 
  20.     </service> 
  21.     </application> 
  22. </manifest> 

效果图:


Feb 13
一.Spinner的简介与创建

1.Spinner的简介


 Spinner(下拉列表)是一个每次只能选择所有项中一项的控件,相当于Html中的下拉列表框。它的继承关系如下:
java.lang.Object
 ↳ Android.view.View
   ↳ Android.view.ViewGroup
     ↳ Android.widget.AdapterView<T extends android.widget.Adapter>
        ↳ Android.widget.AbsSpinner 
           ↳ Android.widget.Spinner

  Spinner常用的XML属性:

属性名称

描述

Android:prompt

该提示在下拉列表对话框显示时显示。(译者注:对话框的标题:


2.创建使用Spinner的步骤如下:

①需要在布局中定时Spinner组件,然后向Spinner添加需要选择的数据

②设置事件监听器setOnItemSelectedListener( )并实现onItemSelected( )

3.Spinner添加数据的两种方法:

①在Java代码中载入列表数据
 

具体的例子如下:

MainActivity.java

  1. package com.Android.spinner;  
  2.  
  3. import Android.app.Activity;  
  4. import Android.os.Bundle;  
  5. import Android.view.View;  
  6. import Android.widget.AdapterView;  
  7. import Android.widget.ArrayAdapter;  
  8. import Android.widget.Spinner;  
  9. import Android.widget.TextView;  
  10.  
  11. public class MainActivity extends Activity {  
  12.     private static final String[] province={"广东","广西","湖南","河南","福建"};  
  13.     private TextView text;  
  14.     private Spinner spinner;  
  15.     private ArrayAdapter<String> adapter;  
  16.     @Override 
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         text=(TextView)findViewById(R.id.text);  
  21.         spinner=(Spinner)findViewById(R.id.spinner);  
  22.           
  23.         //将Spinner里面的可选择内容通过ArrayAdapter连接起来  
  24.         adapter=new ArrayAdapter<String>(this,Android.R.layout.simple_spinner_item,province);  
  25.         //设置Spinner的样式  
  26.         adapter.setDropDownViewResource(Android.R.layout.simple_spinner_dropdown_item);  
  27.         //为对话框设置标题  
  28.         //也可在XMl文件中通过“Android:prompt”设置  
  29.         spinner.setPrompt("你来自哪个省");  
  30.         //为Spinner设置适配器  
  31.         spinner.setAdapter(adapter);  
  32.         //添加Spinner事件监听  
  33.         spinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener(){  
  34.             @Override 
  35.             public void onItemSelected(AdapterView<?> arg0, View arg1,  
  36.                     int arg2, long arg3) {  
  37.                 // TODO Auto-generated method stub  
  38.                 text.setText("你所在的城市是:"+province[arg2]);  
  39.                 //设置显示当前选择的项  
  40.                 arg0.setVisibility(View.VISIBLE);  
  41.             }  
  42.  
  43.             @Override 
  44.             public void onNothingSelected(AdapterView<?> arg0) {  
  45.                 // TODO Auto-generated method stub                
  46.             }         
  47.         });  
  48.     }  
 

main.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="vertical"   
  4.     Android:padding="10dip" 
  5.     android:layout_width="fill_parent"   
  6.     Android:layout_height="wrap_content" 
  7.     > 
  8.     <TextView   
  9.         Android:id="@+id/text" 
  10.         Android:layout_width="fill_parent" 
  11.         android:layout_height="wrap_content"   
  12.         Android:layout_marginTop="10dip" 
  13.         android:text="@string/planet_prompt"   
  14.         /> 
  15.     <Spinner   
  16.         Android:id="@+id/spinner"   
  17.         android:layout_width="fill_parent" 
  18.         Android:layout_height="wrap_content" 
  19.         /> 
  20. </LinearLayout> 

 strings.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <resources> 
  3.     <string name="planet_prompt">你来自的省份是:</string> 
  4.     <string name="app_name">测试Spinner</string> 
  5. </resources> 

效果图:


 

②在XML文件中定义列表的数据

具体的例子如下:

MainActivity.java

  1. package com.Android.spinner;  
  2.  
  3. import Android.app.Activity;  
  4. import Android.os.Bundle;  
  5. import android.view.View;  
  6. import Android.widget.AdapterView;  
  7. import android.widget.AdapterView.OnItemSelectedListener;  
  8. import Android.widget.ArrayAdapter;  
  9. import android.widget.Spinner;  
  10. import Android.widget.Toast;  
  11.  
  12. public class MainActivity extends Activity {  
  13.  
  14.     @Override 
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.         Spinner spinner = (Spinner) findViewById(R.id.spinner);  
  19.         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(  
  20.                 this, R.array.province,  
  21.                 Android.R.layout.simple_spinner_item);  
  22.         //调用setDropDownViewResource方法,以XML的方式定义下拉菜单要显示的样式  
  23.         adapter.setDropDownViewResource(Android.R.layout.simple_spinner_dropdown_item);  
  24.         //为spinner设置适配器  
  25.         spinner.setAdapter(adapter);  
  26.         spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());  
  27.     }  
  28.       
  29.      public class MyOnItemSelectedListener implements OnItemSelectedListener {      
  30.         public void onItemSelected(AdapterView<?> parent,View view, int pos, long id) {        
  31.             Toast.makeText(parent.getContext(), "你来自的省份是: " +  
  32.                  parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();      
  33.             }    
  34.           
  35.         public void onNothingSelected(AdapterView<?> parent) {        
  36.             // TODO Auto-generated method stub       
  37.         }  
  38.     }  
 

main.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="vertical"   
  4.     Android:padding="10dip" 
  5.     android:layout_width="fill_parent"   
  6.     Android:layout_height="wrap_content" 
  7.     > 
  8.     <TextView   
  9.         Android:id="@+id/text" 
  10.         Android:layout_width="fill_parent" 
  11.         android:layout_height="wrap_content"   
  12.         Android:layout_marginTop="10dip" 
  13.         android:text="@string/planet_prompt"   
  14.         /> 
  15.     <Spinner   
  16.         Android:id="@+id/spinner"   
  17.         android:layout_width="fill_parent" 
  18.         Android:layout_height="wrap_content" 
  19.         android:prompt="@string/planet_prompt" 
  20.         /> 
  21. </LinearLayout> 

strings.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <resources> 
  3.     <string name="planet_prompt">你来自的省份是</string> 
  4.     <string name="app_name">测试Spinner</string> 
  5.     <string-array name="province"> 
  6.         <item>广东</item> 
  7.         <item>广西</item> 
  8.         <item>湖南</item> 
  9.         <item>河南</item> 
  10.         <item>福建</item> 
  11.     </string-array> 
  12. </resources> 

效果图:

 二.AutoCompleteTextView简介

   我们平常上网的时候经常会用到Google或百度,在输入框中输入类似”51CTO“,和51CTO相关的信息就会被列出来,供用户选择,非常方便。这种效果在Android中是用AutoCompleteTextView实现的。在AutoCompleteTextView中,主要是设置想显示资源的适配器(Adapter)。

    AutoCompleteTextView有三个重要的方法clearListSelection():清除选中的列表项、dismissDropDown():如果存在关闭下拉菜单、getAdapter():获取适配器。

具体的例子如下:

MainActivity.java

  1. package com.Android.autocomplete;  
  2.  
  3. import Android.app.Activity;  
  4. import Android.os.Bundle;  
  5. import android.widget.ArrayAdapter;  
  6. import Android.widget.AutoCompleteTextView;  
  7.  
  8. public class MainActivity extends Activity {  
  9.     private AutoCompleteTextView atv;  
  10.     //创建字符串数组  
  11.     private static final String[] strs = {"an""and""Android""abc","abcdef" };  
  12.     @Override 
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.         atv = (AutoCompleteTextView) findViewById(R.id.AutoCompleteTextView1);  
  17.         //创建适配器  
  18.         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,   
  19.                 Android.R.layout.simple_dropdown_item_1line, strs);  
  20.         //为AutoCompleteTextView设置适配器  
  21.         atv.setAdapter(adapter);  
  22.     }  

main.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="vertical" 
  4.     Android:layout_width="fill_parent" 
  5.     android:layout_height="fill_parent" 
  6.     > 
  7.     <TextView   
  8.         Android:layout_width="wrap_content"   
  9.         android:layout_height="wrap_content"   
  10.         Android:text="自动完成文本框" 
  11.         /> 
  12.     <AutoCompleteTextView   
  13.         Android:id="@+id/AutoCompleteTextView1"   
  14.         Android:layout_width="fill_parent"   
  15.         android:layout_height="wrap_content" 
  16.         /> 
  17. </LinearLayout> 

效果图:

Feb 12

如果是PHP做的服务端,要用Android去访问,如何办?当然可以用REST,但也可以用点笨的方法,比如PHP的服务端可以用JSON和XML提供返回的数据,而android端则可以用APACHE的httpclient去访问.

下面是一个例子,假设数据表中users表有如下字段(mysql):

idusers,UserName,FullName,加点数据.然后在服务端PHP,建立一个

webservice1.php,作用是直接返回服务端数据库的数据,如下:

  1. <?php    
  2. if(isset($_GET['user']) && intval($_GET['user'])) {   
  3.   
  4.   
  5.      $format = strtolower($_GET['format']) == 'json' ? 'json' : 'xml'//xml is the default   
  6.   $user_id = intval($_GET['user']); //no default   
  7.   
  8.   /* 连接数据库*/  
  9.   $link = mysql_connect('localhost','root','xxxxx') or die('Cannot connect to the DB');   
  10.   mysql_select_db('jsonAndroid',$link) or die('Cannot select the DB');   
  11.   
  12.      $query = "SELECT * FROM `users`;";   
  13.   $result = mysql_query($query,$link) or die('Errant query:  '.$query);   
  14.   
  15.     $posts = array();   
  16.   if(mysql_num_rows($result)) {   
  17.     while($post = mysql_fetch_assoc($result)) {   
  18.       $posts[] = array('post'=>$post);   
  19.     }   
  20.   }   
  21.   
  22.   /* json格式*/  
  23.   if($format == 'json') {   
  24.     header('Content-type: application/json');   
  25.     echo json_encode(array('posts'=>$posts));   
  26.   }   
  27.   else {   
  28.     header('Content-type: text/xml');   
  29.     echo '<posts>';   
  30.     foreach($posts as $index => $post) {   
  31.       if(is_array($post)) {   
  32.         foreach($post as $key => $value) {   
  33.           echo '<',$key,'>';   
  34.           if(is_array($value)) {   
  35.             foreach($value as $tag => $val) {   
  36.               echo '<',$tag,'>',htmlentities($val),'</',$tag,'>';   
  37.             }   
  38.           }   
  39.           echo '</',$key,'>';   
  40.         }   
  41.       }   
  42.     }   
  43.     echo '</posts>';   
  44.   }   
  45.   
  46.   }   
  47.  ?>   

则可以把数据表输出为JSON或者XML格式了.客户端的Android调用:

  1. try {   
  2.                
  3.             HttpParams httpParams = new BasicHttpParams();   
  4.             HttpConnectionParams.setConnectionTimeout(httpParams,   
  5.                     TIMEOUT_MILLISEC);   
  6.             HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);   
  7.                
  8.             HttpParams p = new BasicHttpParams();   
  9.                
  10.             p.setParameter("user""1");   
  11.   
  12.                
  13.             HttpClient httpclient = new DefaultHttpClient(p);   
  14.             String url = "http://10.0.2.2:8082/myphp/phpWebservice/webservice1.php?user=1&format=json";   
  15.             HttpPost httppost = new HttpPost(url);   
  16.   
  17.                
  18.             try {   
  19.                 Log.i(getClass().getSimpleName(), "send  task - start");   
  20.                    
  21.                 List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(   
  22.                         2);   
  23.                 nameValuePairs.add(new BasicNameValuePair("user""1"));   
  24.                 httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));   
  25.                 ResponseHandler<String> responseHandler = new BasicResponseHandler();   
  26.                 String responseBody = httpclient.execute(httppost,   
  27.                         responseHandler);   
  28.                 // 解析JSON返回的                JSONObject json = new JSONObject(responseBody);   
  29.                 JSONArray jArray = json.getJSONArray("posts");   
  30.                 ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();   
  31.   
  32.                 for (int i = 0; i < jArray.length(); i++) {   
  33.                     HashMap<String, String> map = new HashMap<String, String>();   
  34.                     JSONObject e = jArray.getJSONObject(i);   
  35.                     String s = e.getString("post");   
  36.                     JSONObject jObject = new JSONObject(s);   
  37.   
  38.                     map.put("idusers", jObject.getString("idusers"));   
  39.                     map.put("UserName", jObject.getString("UserName"));   
  40.                     map.put("FullName", jObject.getString("FullName"));   
  41.   
  42.                     mylist.add(map);   
  43.                 }   
  44.                 Toast.makeText(this, responseBody, Toast.LENGTH_LONG).show(); 

再搞个webservice2.php,该文件用来把客户端传送过去的JSON数据保存

  1. <?php    
  2.   
  3. $json = file_get_contents('php://input');   
  4. $obj = json_decode($json);   
  5.   
  6. //echo $json;   
  7.   
  8.   
  9. //保存数据库   
  10. $con = mysql_connect('localhost','root','XXX') or die('Cannot connect to the DB');   
  11. mysql_select_db('jsonAndroid',$con);   
  12.   
  13.   mysql_query("INSERT INTO `users` (UserName, FullName)   
  14. VALUES ('".$obj->{'UserName'}."''".$obj->{'FullName'}."')");   
  15.   
  16. mysql_close($con);   
  17.   $posts = array(1);   
  18.     header('Content-type: application/json');   
  19.     echo json_encode(array('posts'=>$posts));   
  20.   
  21. ?>  

Android端的,可以构造JSON,发送到webservice2.php

  1. try {   
  2.             JSONObject json = new JSONObject();   
  3.             json.put("UserName""test2");   
  4.             json.put("FullName""1234567");   
  5.             HttpParams httpParams = new BasicHttpParams();   
  6.             HttpConnectionParams.setConnectionTimeout(httpParams,   
  7.                     TIMEOUT_MILLISEC);   
  8.             HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);   
  9.             HttpClient client = new DefaultHttpClient(httpParams);   
  10.                                     String url = "http://10.0.2.2:8082//myphp/phpWebservice/webservice2.php";   
  11.   
  12.             HttpPost request = new HttpPost(url);   
  13.             request.setEntity(new ByteArrayEntity(json.toString().getBytes(   
  14.                     "UTF8")));   
  15.             request.setHeader("json", json.toString());   
  16.             HttpResponse response = client.execute(request);   
  17.             HttpEntity entity = response.getEntity();   
  18.                
  19.             if (entity != null) {   
  20.                 InputStream instream = entity.getContent();   
  21.   
  22.                 String result = RestClient.convertStreamToString(instream);   
  23.                 Log.i("Read from server", result);   
  24.                 Toast.makeText(this,  result,   
  25.                         Toast.LENGTH_LONG).show();   
  26.             }  

这样,就可以把Android发送的数据保存到服务端了。

Feb 12

由于手机端应用的响应,与当时的无线通信网络状况有很大的关联。而通信网络往往具有不稳定,延迟长的特点。所以,在我们的应用程序中,当我们请求网络的时候,超时机制的应用就显得特别重要。

超时机制主要有:

1、HTTP请求超时机制

2、Socket通信超时机制

HTTP请求超时机制

  1. public static void main(String[] args){   
  2.   
  3. long a=System.currentTimeMillis();   
  4. try{   
  5. URL myurl = new URL(“http://www.linuxidc.com”);   
  6. URLConnection myurlcon = myurl.openConnection();   
  7. myurlcon.setConnectTimeout(1000);   
  8. myurlcon.setReadTimeout(1000);   
  9. BufferedReader in = new BufferedReader(new InputStreamReader(myurlcon.getInputStream(),”UTF-8″));   
  10. String inputLine;   
  11.   
  12. while ((inputLine = in.readLine()) != null){   
  13. System.out.println(inputLine);   
  14. in.close();   
  15. System.out.println(System.currentTimeMillis()-a);   
  16. }   
  17. catch (MalformedURLException e) {   
  18. e.printStackTrace();   
  19. catch (UnsupportedEncodingException e) {   
  20. e.printStackTrace();   
  21. catch (IOException e) {   
  22. e.printStackTrace();   
  23. }   
  24.   
  25. }   
  26.   
  27.   
  28. 如果超时 将 抛出 以下 异常   
  29.   
  30. java.net.SocketTimeoutException: Read timed out   
  31. at java.net.SocketInputStream.socketRead0(Native Method)   
  32. at java.net.SocketInputStream.read(SocketInputStream.java:129)   
  33. at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)   
  34. at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)   
  35. at java.io.BufferedInputStream.read(BufferedInputStream.java:313)   
  36. at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:606)   
  37. at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:554)   
  38. at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:940)   
  39. at com.Test.main(Test.java:52)

补充内容:

Android项目中,如果有用到http请求,就必须也应该加上http请求的超时管理,异常管理,项目中遇到这个需求,google上搜索到了一大堆,但是写的都比较简单,做个demo还行,用在项目中还是不够完善。自己写了一个例子,有不完善之处,欢迎大家指正。

  需要注意的地方:有三个方面

  如何控制超时机制

  如何处理异常

  如何处理请求错误的

  1. private class XmlAsyncLoader extends XmlResourceRequest {   
  2.   
  3.  private boolean mIsCancle = false;   
  4.  private HttpGet mGet;   
  5.  private HttpClient mHttp;   
  6.   
  7.  public XmlAsyncLoader(MxActivity<?> activity, String url)   
  8.  throws MalformedURLException {   
  9.  super(activity, url);   
  10.  }   
  11.   
  12.  @Override  
  13.  protected void doTaskInBackground() {   
  14.  // 请求数据   
  15.  if (mUrl.toLowerCase().startsWith("http://")) {   
  16.  mGet = initHttpGet(mUrl);   
  17.  mHttp = initHttp();   
  18.  try {   
  19.  HttpResponse response = mHttp.execute(mGet);   
  20.  if (mIsCancle) {   
  21.  return;   
  22.  }   
  23.  if (response != null) {   
  24.  if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){   
  25.  onResponseError("network error");   
  26.  Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode());   
  27.  return;   
  28.  }   
  29.  notifyUpdateProgress(70);   
  30.  Document doc = getDocumet(response);   
  31.  Element root = doc.getDocumentElement();   
  32.  NodeList appList = root   
  33.  .getElementsByTagName(Item_ELEMENT_NAME);   
  34.  final int len = appList.getLength();   
  35.  if (len <= 0) {// 没有items   
  36.  onFoundNoItems();   
  37.  return;   
  38.  }   
  39.  for (int i = 0; i < len; i++) {   
  40.  Element item = (Element) appList.item(i);   
  41.  if (item.getNodeType() == Node.ELEMENT_NODE) {   
  42.  HahaItemInfo info = createHahaItemIno(item);   
  43.  if (mIsCancle){   
  44.  return;   
  45.  }   
  46.  onFoundItem(info, 80 + 20 * (i + 1) / len);   
  47.  addUrlToQueue(info.userIconUrl);   
  48.  }   
  49.  };   
  50.     
  51.  }   
  52.  }catch(ConnectTimeoutException e){   
  53.  onResponseError("time out");   
  54.  } catch (ClientProtocolException e) {   
  55.  --mCurrentPage;   
  56.  e.printStackTrace();   
  57.  } catch (IOException e) {   
  58.  --mCurrentPage;   
  59.  e.printStackTrace();   
  60.  } catch (XmlPullParserException e) {   
  61.  --mCurrentPage;   
  62.  e.printStackTrace();   
  63.  }finally{   
  64.  notifyLoadFinish();   
  65.  notifyLoadImages();   
  66.  mHttp.getConnectionManager().shutdown();   
  67.  }   
  68.   
  69.  }   
  70.  }   
  71.   
  72.   
  73.  private HttpClient initHttp() {   
  74.  HttpClient client = new DefaultHttpClient();   
  75.  client.getParams().setIntParameter(   
  76.  HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置   
  77.  client.getParams().setIntParameter(   
  78.  HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时   
  79.  return client;   
  80.  }   
  81.   
  82.  private HttpGet initHttpGet(String mUrl) {   
  83.  HttpGet get = new HttpGet(mUrl);   
  84.  initHeader(get);   
  85.  return get;   
  86.  }   
  87.   
  88.   
  89.  @Override  
  90.  public boolean tryCancel() {   
  91.  Log.i(TAG, "tryCanle is working");   
  92.  mGet.abort();   
  93.  mIsCancle = true;   
  94.  mHttp.getConnectionManager().shutdown();   
  95.  notifyLoadFinish();   
  96.  return true;   
  97.  }   
  98.   
  99.  }  

这是一个异步任务类,发送get请求请求数据,解析服务器的响应数据,同时通知ui线程更新ui

Android中,互联网交互的写法有很多,可以使用apache提供的包,也可以使用google提供的api,我不知道那种更好,只是习惯于使用

apache的api。

1. 设置超时机制

client.getParams().setIntParameter( HttpConnectionParams.SO_TIMEOUT, TIME_OUT_DELAY); // 超时设置 client.getParams().setIntParameter( HttpConnectionParams.CONNECTION_TIMEOUT, TIME_OUT_DELAY);// 连接超时

这里设置了两种超时,第一种是请求超时,第二种时连接超时。

当向服务器发出请求后,请求和服务器建立socket连接,但是很长时间内都没有建立socket连接,这就时第一种请求超时,这种情况主要发生在请求了

一个不存在的服务器。超时之后,会抛出InterruptedIOException异常。

Timeout for blocking operations. The argument value is specified in milliseconds. An InterruptedIOException is thrown if this timeout expires.

客户端已经与服务器建立了socket连接,但是服务器并没有处理客户端的请求,没有相应服务器,这就是第二种连接超时。这中超时会抛出

ConnectTimeoutException异常,ConnectTimeoutException继承自InterruptedIOException,所以只要捕获ConnectTimeoutException 就可以了。

2. 分析一下请求的过程

 2.1 HttpResponse response = mHttp.execute(mGet);

执行请求方法,获取服务器响应,(这里有个不太成熟的看法,response不可能为null,还有待验证)。

2.2 获取请求响应码

if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){ onResponseError("network error"); Log.v(TAG, "the code is :"+response.getStatusLine().getStatusCode()); return; }

  即使连接上服务器,并且从服务器上获取了数据,也有可能时服务器返回的错误信息,因此也需要特殊处理。

2.3 异常处理

  对于异常,不能简单的捕获就完事,例如上面的代码中,我请求第三页的数据,如果发生异常,请求不成功,那么我就需要让当前页数回滚,

如果成功了就不用回滚了,所以需要对异常进行处理

2.4 finally关键字

  不管是请求成功,还是失败,都需要关闭链接。

分页: 1/6 第一页 1 2 3 4 5 6 下页 最后页 [ 显示模式: 摘要 | 列表 ]