今天算是有点小激动呢!拿到Android与PHP这个课题已经两个星期了,直到今天才算是有了一点点小收获。
虽然还是没能成功上传到服务器,不过已经看到了曙光,已经实现了一半了,那就是已经连接到了服务器。不
说废话了,还是写点自己的记录吧!
如果想要实现Android与PHP的交互我们首先应该知道一个叫AsynTask的抽象类。
下面是我的笔记:
为了方便在子线程中对UI进行操作,Android提供了一些好用烦人工具类,AsynTask就是其中之一。借助AsynTask
,可以十分简单地从子线程切换到主线程,它的原理也是基于异步消息处理机制的。
AsynTask的基本用法:
1.AsynTask是一个抽象类,因此使用它必须要创建一个类去继承它。在继承AsynTask时,可以为其指定三个泛型
参数,这三个参数的用途如下所示:
Params:在执行AsynTask时需要传入的参数,用于后台的任务中使用。
Progress:后台任务执行时,如果需要在界面上显示当前的进度,则使用该参数作为进度单位。
Result:当任务执行完毕后,如果需要对结果进行返回,则使用该参数作为返回值类型。
例如:class DownLoadTask extends AsynTask<void,Integer,Boolean>{
...
}
通常使用AsynTask时,需要重写它的4个方法。
1.onPreExcute():这个方法在后台任务执行之前调用,一般用于界面上初始化操作,例如,显示一个
进度条对话框等。
2.doInBackground(Params...):这个方法在子线程中运行,用于处理耗时操作,操作一旦完既可以
通过return语句将任务的执行结果返回。如果AsynTask的第三个泛型参数指定的是void则可以不用返回
结果。需要注意的是,这个方法不能进行更新UI操作,如果要在该方法中更新UI可以手动调动
publishProgress(Progress...)方法来完成。
3.onProgressUpdate(Progress...):如果在doInBackground(Params...)方法中调用了publishProgress
(Progress...)方法,这个方法就会很快被调用,方法中携带的参数就是后台任务中传递过来的
在这个方法可以对UI进行操作,利用参数Progress就可以对UI进行相应的更新。
4.onPostExcute(Result):当doInBackground(Params...)执行完毕通过return语句进行返回时,这个
方法会很快被调用。在doInBackground(Params...)中返回的数据会作为参数传递到该方法中。此时
可以利用返回的参数来进行UI操作,例如,提醒某个任务完成了。
package com.itcast.asyntask;
import android.os.AsyncTask;
import android.widget.Toast;
public class DownLoadTask extends AsyncTask<Void,Integer,Boolean>{
protected void onPreExecute(){
progressDialog.show();
}
@Override
protected Boolean doInBackground(Void... params) {
// TODO Auto-generated method stub
while(true){
int downloadPrecent = doDownload();
publishProgress(downloadPrecent);
if(downloadPrecent >= 100){
break;
}
}
return true;
}
protected void onProgressUpdate(Integer...values){
progressDialog.setMessage("Download"+values[0]+"%");
}
protected void onPostExecute(Boolean result){
progressDialog.dismiss();
if(result){
Toast.makeText(MainActivity.this, "下载成功", 0).show();
}else{
Toast.makeText(MainActivity.this, "下载失败", 0).show();
}
}
}
要执行DownLoadTask,还需要在UI线程中创建出DownLoadTask的实例,并调用DownLoadTask
实例的Excute()方法。代码如下:
new DownLoadTask().excute();
接下来是我的一个交互的小程序:
步骤为:1.写布局文件 2.写主程序 3.添加网络访问权限
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 11 <TextView 12 android:id="@+id/textView1" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:textSize="20sp" 16 android:text="上传文件" /> 17 18 <TextView 19 android:id="@+id/textView2" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:layout_below="@+id/textView1" 23 android:text="TextView" /> 24 25 <Button 26 android:id="@+id/button1" 27 android:layout_width="wrap_content" 28 android:layout_height="wrap_content" 29 android:layout_below="@+id/textView2" 30 android:text="确定上传" /> 31 32 33 </RelativeLayout>
package com.itcastupfile; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private String uploadFile = "/mnt/sdcard/DCIM/Camera/IMG_20160406_114143.JPG"; private String srcPath = "/mnt/sdcard/DCIM/Camera/IMG_20160406_114143.JPG"; private String actionUrl = "http://10.6.78.90/xampp/sse/index.php/home/Index/upload_file"; private TextView mText1; private TextView mText2; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mText1 = (TextView)findViewById(R.id.textView1); mText1.setText("文件路径: "+uploadFile); mText2 = (TextView)findViewById(R.id.textView2); mText2.setText("上传网址: "+actionUrl); mButton = (Button)findViewById(R.id.button1); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub uploadFile(actionUrl); //FileUploadTask fileuploadtask = new FileUploadTask(); //fileuploadtask.execute(); } }); } private void uploadFile(String actionUrl) { // TODO Auto-generated method stub String end = " "; String twoHyphens = "--"; String boundary = "******"; try{ URL url = new URL(actionUrl); HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); // 设置每次传输的流大小,可以有效防止手机因为内存不足崩溃 // 此方法用于在预先不知道内容长度时启用没有进行内部缓冲的 HTTP 请求正文的流。 httpURLConnection.setChunkedStreamingMode(128 * 1024);// 128K // 允许输入输出流 httpURLConnection.setDoInput(true); httpURLConnection.setDoOutput(true); httpURLConnection.setUseCaches(false); // 使用POST方法 httpURLConnection.setRequestMethod("POST"); httpURLConnection.setRequestProperty("Connection", "Keep-Alive"); httpURLConnection.setRequestProperty("Charset", "UTF-8"); httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); DataOutputStream dos = new DataOutputStream( httpURLConnection.getOutputStream()); dos.writeBytes(twoHyphens + boundary + end); dos.writeBytes("Content-Disposition: form-data; name="uploadedfile"; filename="" + srcPath.substring(srcPath.lastIndexOf("/") + 1) + """ + end); dos.writeBytes(end); FileInputStream fis = new FileInputStream(srcPath); byte[] buffer = new byte[8192]; // 8k int count = 0; // 读取文件 while ((count = fis.read(buffer)) != -1) { dos.write(buffer, 0, count); } fis.close(); dos.writeBytes(end); dos.writeBytes(twoHyphens + boundary + twoHyphens + end); dos.flush(); InputStream is = httpURLConnection.getInputStream(); InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); String result = br.readLine(); Toast.makeText(this, result, Toast.LENGTH_LONG).show(); dos.close(); is.close(); } catch (Exception e) { e.printStackTrace(); setTitle(e.getMessage()); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
<uses-permission android:name="android.permission.INTERNET" />
下面是我的运行结果:
看到的那个Toast就是PHP端的代码,判断是否上传成功!
不过此程序仍然存在问题就是无法显示上传成功,问题还在查询当中。
不过已经算是实现交互的功能了。接下来就是查找上传不成功的原因了。