android小项目 连接PHP开发的服务端
来源:互联网 发布:java wait 参数 编辑:程序博客网 时间:2024/05/22 06:37
github 链接:
https://github.com/RenjiaLu9527/AndroidSampledemocnnctMysqlbyPHP
//随手打开一个记事本 记录开发时的疑惑 有点乱 20160701 - 20160705 [简单的吐槽小程序] Android - php - mysql
////////////////////////////////////////////////////////////start
//新建一个txt文档,不输入任何内容。然后“另存为”,将编码由默认的 ANSI 修改为 Unicode 或 UTF-8。可解决php文件默认编码的问题
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
//PHP文件 返回 echo '[OK]'public class netthread extends Thread {
@Override
public void run() {
Looper.prepare();
line = "";
super.run();
try {
URL url = new URL("http://192.168.1.109/mytest/index.php?name=" + user + "&psw=" + passwd);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStreamReader isr = new InputStreamReader(urlConnection.getInputStream());
BufferedReader br = new BufferedReader(isr);
String readbr;
while ((readbr = br.readLine()) != null)
line += readbr + "\n";
urlConnection.disconnect();//关闭http连接
} catch (UnknownHostException e) {
e.printStackTrace();
line += e.toString();
} catch (IOException e) {
e.printStackTrace();
line += e.toString();
} finally {
Log.i("Mactivity_Thread", "line = " + line);
Message msg = new Message();
// msg.set
msg.obj = new String(line);
mHandler.sendMessage(msg);
Looper.loop();
}
}
获取的 line编码通过 msg传到handler后
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String strmsg =new String("[OK]");
msg.obj = new String(msg.obj.toString().replaceAll("\r|\n", ""));
tvlog.setText("等待服务器回应...\n" + "用户名:" + user + " 密码:" + passwd + "\n服务器反馈信息:[" + msg.obj + "]");
if (strmsg.equals(msg.obj)) {
Toast.makeText(MainActivity.this, "登陆成功", Toast.LENGTH_SHORT).show();
Intent ntnt_feedback = new Intent(MainActivity.this, feedback.class);
startActivity(ntnt_feedback);
} else {
tvlog.setText(tvlog.getText() + "else [" + strmsg + "]");
}
}
?why
android view显示其值
[[OK]]else[[OK]]
其中前面的[[OK]]中 [[ ]]贴的不够紧密
后[[OK]]中 的 [[ 贴的很紧密
贴不紧的 length() = 5
贴紧的 length() = 2
【解答】
调用此函数处理之后即可去掉其中空格,
//处理串
public String trimInnerSpaceStr(String str) {
str = str.trim();
while (str.startsWith(" ")||str.startsWith("\n")) {
str = str.substring(1, str.length()).trim();
}
while (str.endsWith(" ")||str.endsWith("\n")) {
str = str.substring(0, str.length() - 1).trim();
}
return str;
}
//再次遇到
[!]错误:strFlagInfo[0] FLAG判断不等于OK或ERROR [[?OK]][[OK]]
php返回
echo 'OK&'."$name";
android先解码 后分组 再比较时:
"OK".equals(strFlagInfo[0]) 一直false
【解答】
利用正则表达式 去掉其中 非字母 非数字的 隐形字符后就可以了;但是不知为何???
strFlagInfo[0] = new String(strFlagInfo[0].toString().replaceAll("[^0-9a-zA-Z]+", ""));
strFlagInfo[1] = new String(strFlagInfo[1].toString().replaceAll("[^0-9a-zA-Z]+", ""));
//我保存 txt文件时,发现弹窗“该文件含有 Unicode 格式的字符,若保存ANSI文件将丢失 Unicode字符。。。。”
我一直剪切保存测试到底是哪个字符是 Unicode字符,最后发现是【[[?OK]][[OK]]】中左边的ok有问题,
猜测:【待解决】
20160705
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
$sqlr = "SELECT * FROM usercomment
WHERE umID>=1 AND umID<=5";【取出umID 1-5 以及umID所属的 单条完整数据】
与
$sqlr = "SELECT unID FROM usercomment
WHERE umID>=1 AND umID<=5";【只取出 umID 1-5:12345而不取出附带数据】
不一样;
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
String testStr = "abc\\123";//形式表示【abc\\123】; 实际表示 【abc\123】
String [] a = testStr.split("\\\\");//形式表示【\\\\】;实际表示【\\】
即:split()以 实际【\\】 去划分 形式【abc\\123】得数组【abc】和【123】
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
//越来越觉得 模块化 低耦合性代码 的重要性 20160704
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
//PHP中 【\\】 URLDecode.Decode解码后为【\】容易组合成为转义字符 所以慎重
正斜杠"/"
"\\"==> 反斜杠
/叫斜杠 \叫反斜杠
* \n : 回车
* \t : 水平制表符
* \r : 换行
* \f : 换页
* \' :单引号
* \'' : 双引号
* \\ : 反斜杠
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
//代码布局的如何给其中控件添加 统一的监听器
private class feedbackViewOnClikListener implements OnClickListener{
@Override
public void onClick(View view) {
if(view.getid ==)
}
}
没有 R.id.xx的id匹配
【解答】
http://www.cnblogs.com/codingblock/p/5090441.html
【 ·方案二:在res/values/下添加ids.xml(名字可随意)文件,代码如下:
1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="my_view" type="id" />
</resources>
然后在代码中做如下设置即可:
1
my_view.setId(R.id.my_view);】
这样: loadingLayout.setId(R.id.LL_listfooterview);//DIY_id.xml 自定义的id
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
android 线程handler发送消息activity
其实这些线程间发送消息,没有什么;关键还是在于构造Handler时传入谁的Looper.
为实现子线程给自己本身发送消息,关键还是在于构造Handler时传入的Looper.
* 在此就传入该子线程自己的Looper即调用Looper.myLooper(),代码如下:
* Looper.prepare();
* mHandlerTest1=new HandlerTest1(Looper.myLooper());
* Looper.loop();
*
* 所以当mHandlerTest1.sendMessage(message);发送消息时
* 当然是发送到了它自己的消息队列.
*
* 当子线程中收到自己发送的消息后,可继续发送消息到主线程.此时只要注意构造
* Handler时传入的Handler是主线程的Handler即可,即getMainLooper().
http://www.bkjia.com/Androidjc/893149.html
// //临时 Message,防止主线程同时访问 msg导致出错
Message msg_copy =new Message();
msg_copy.obj = new String(msg.obj.toString());//新的类,不是引用
msg_copy.what = msg.what;
feedback.mhandler.sendMessage(msg_copy);//发送消息 msg以引用形式被发送至 主线程
Looper.loop();
////////////////////////////////////////////////////////////end
////////////////////////////////////////////////////////////start
//问题:ListView每次刷新都会跑到最顶,而不是停留在刷新前的页面
【解答】 【 //ListView lv设置 TranscriptMode取消‘alwaysScroll’->永远停在最顶端
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED);】
借鉴:
哈哈,其实我找到问题了。原来在我的listview中加了android:transcriptMode="alwaysScroll"这个属性,
导致有变动都会回到底部。在下拉刷新的时候,
设置[mw_shl_code=java,true]listview.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED);
[/mw_shl_code]然后计算下原来的位置,数据刷新Adapter.notifyDataSetChanged();接着就是设置listview.setSelection,
这样基本是平滑的,没有跳动。体验不错哦
////////////////////////////////////////////end////////////////////////////////////////////////////////////////////////////////end////////////////////////////////////
////////////////////////////////////////////end////////////////////////////////////////////////////////////////////////////////end////////////////////////////////////
////////////////////////////////////////////end////////////////////////////////////////////////////////////////////////////////end////////////////////////////////////
20160701 - 20160705 [简单的吐槽小程序] 概述:提供注册 登陆功能登陆 吐槽界面,可在吐槽界面发送文字评论,后台连接php文件,php连接MySql数据库,实现 mysql -php-Android的数据传输, 本例使用 GET方法与php交互。
【工程目录】
(布局文件中的 listfoot.xml文件无效,不用)
其中 netthread.java 为 网络传输数据的线程,MainActivity.java为主界面 实现用户名密码登陆功能,feedback.java为吐槽界面 主要是一个带footerview刷新的ListView;特别的是res/values/diy_id.xml文件,这是个自定义xml,是为了解决下面的一个无法获取 在代码布局中的以代码定义的控件 的id(R.id.xx)的问题;
【1.问题】那就说这个问题吧,
-问题来源:
//下面这段代码 设置ListView的FooterView,代码布局没有调用xml文件,当我想 设置监听器监听这个footerview时,发现在函数里面直接
//AddFooterViewtoListView函数开始{loadingLayout.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { }});}//AddFooterViewtoListView函数结尾
</pre>这样设置监听器时,没反应,我感觉也是不行的,这只是一个函数而不是一个类,函数运行结束就结束了所以达不到监听的效果;所以我将 loadingLayout定义成一个 全局变量,在函数外面设置其监听器,private LinearLayout loadingLayout;//listview的footerview布局//OnCreate 函数中 添加FooterView 到ListView AddFooterViewtoListview(); loadingLayout.setId(R.id.LL_listfooterview);//DIY_id.xml 自定义的id loadingLayout.setOnClickListener(new feedbackViewOnClikListener());然后在重写的监听器中:<pre name="code" class="java">private class feedbackViewOnClikListener implements OnClickListener{ @Override public void onClick(View view) { switch (view.getId()){ case R.id.LL_listfooterview: {}//略<pre name="code" class="java" style="font-size: 17.6px; font-weight: bold;">case R.id.xx这里发现 loadingLayout 没有和他匹配的id,因为他是用代码布局的而不是xml;所以得重新通过其他方式指定一个id,【摘】http://www.cnblogs.com/codingblock/p/5090441.html//在res/values/下添加ids.xml(名字可随意)文件,代码如下:<?xml version="1.0" encoding="utf-8"?><resources> <item name="my_view" type="id" /></resources> //然后在代码中做如下设置即可:my_view.setId(R.id.my_view);】【1.问题】完美解决其他问题我在 随笔txt中,大概记录了下,有特别的问题特别说明。//完整源代码//MainActivity.javapackage com.learn4.wheee.androidclient;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.net.URLEncoder;import java.util.Random;public class MainActivity extends Activity { private EditText et_username; private EditText et_userpsw; private TextView tvlog; private Button bn_login;//登陆 private Button bn_register;//注册 static String URLLOGIN_PHP = "http://192.168.1.109/mytest/login.php?a_lgninout="; static String URLLOGIN_PHP_IN = "IN";//登陆 static String URLLOGIN_PHP_RGST = "RGST";//注册 static String sttc_name;//正确的 name ;全局变量 整个acitvity共用一个 name 用户名 private String usernm;//临时 name private String passwd;//临时 psw public Handler mainHandler; private String line; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_username = (EditText) this.findViewById(R.id.et_name); et_userpsw = (EditText) this.findViewById(R.id.et_psw); bn_login = (Button) findViewById(R.id.bn_login);//登陆 bn_register = (Button) findViewById(R.id.bn_register);//注册 tvlog = (TextView) findViewById(R.id.tv_log);//log信息 bn_login.setOnClickListener(new MainOnClickLstnr()); bn_register.setOnClickListener(new MainOnClickLstnr()); mainHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what == 0){ //与 php 传输数据流时出错 tvlog.setText("[!]错误:android-php网络出错 请稍后重试\n耗时:"+msg.getWhen()); Toast.makeText(MainActivity.this,"网络出错 请稍后重试",Toast.LENGTH_LONG).show(); Log.i("mainHandler","[!]错误 android-php 网络出错 请稍后重试"); }else { //String strmsg = new String(msg.obj.toString().replaceAll("[^0-9a-zA-Z]+", "")); String strmsg = new String(netthread.trimInnerSpaceStr(msg.obj.toString())); Log.i("mainHandler", "去掉首尾空格的strmsg=" + strmsg); //先分组 后解码 (login.php文件返回值为【flag&info】) //1-2【分组】 String[] strFlagInfo = strmsg.split("&"); if (strFlagInfo.length != 2) { Log.i("mainHandler", "strFlagInfo.length!=2 [!]错误 strmsg=" + strmsg); } //理论上只分成 2 组 //2-2【解码】并去掉解码后的 首尾空格回车 try { strFlagInfo[0] = netthread.trimInnerSpaceStr(URLDecoder.decode(strFlagInfo[0].toString(), "UTF-8")); strFlagInfo[1] = netthread.trimInnerSpaceStr(URLDecoder.decode(strFlagInfo[1].toString(), "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.i("mainHandler", "分组 解码后[OK_or_ERROR]?:strFlagInfo[0]=[" + strFlagInfo[0] + "] [login_ok_or_MaxId]?:strFlagInfo[1]=[" + strFlagInfo[1]+"]"); //判断flag是否为 OK strFlagInfo[0] = new String(strFlagInfo[0].toString().replaceAll("[^0-9a-zA-Z]+", "")); strFlagInfo[1] = new String(strFlagInfo[1].toString().replaceAll("[^0-9a-zA-Z]+", "")); if ("OK".equals(strFlagInfo[0])) { //操作成功 RGST//返回OK和最大ID,更新用户名控件值 :【'OK&'+$MaxId;】 //IN //echo 'OK&login_ok'; Log.i("mainHandler", "【操作成功】等待判断是什么操作strFlagInfo[0]=" + strFlagInfo[0]+"strFlagInfo[1]="+strFlagInfo[1]); if ("LOGINOK".equals(strFlagInfo[1])) { //【登陆成功】 sttc_name = et_username.getText().toString();// tvlog.setText("登陆成功\n耗时:"+msg.getWhen()); Log.i("mainHandler", "【登陆成功】 sttc_name=" + sttc_name + "&跳转到feedback.java"); //跳转到 feedback.java Toast.makeText(MainActivity.this, "【登陆成功】", Toast.LENGTH_SHORT).show(); Intent ntnt_feedback = new Intent(MainActivity.this, feedback.class); startActivity(ntnt_feedback); } else { //【注册成功】 sttc_name = new String(strFlagInfo[1]);//末尾加上唯一id tvlog.setText("注册成功\n耗时:"+msg.getWhen()); Log.i("mainHandler", "【注册成功】 sttc_name=" + sttc_name + "&设置EditText_name_psw的值,等待用户点击登陆按钮"); et_username.setText(sttc_name); et_userpsw.setText(passwd); } } else if ("ERROR".equals(strFlagInfo[0].toString())) { //操作失败 tvlog.setText("[!]错误:php-mysql 连接数据库出错\n"+strmsg+"\n耗时:"+msg.getWhen());//输出错误信息 Log.i("mainHandler","[!]错误:php-mysql 连接数据库出错"); }else{ Log.i("mainHandler","[!]错误:strFlagInfo[0] FLAG判断不等于OK或ERROR\n[["+strFlagInfo[0]+"]][["+"OK"+"]]"); } }//if-else msg.what == 0? -end// tvlog.setText("等待服务器回应:\n" + "用户名:" + sttc_name + " 密码:" + passwd + "\n反馈信息:[" + strmsg + "]" + strmsg.length());// if ("OK".equals(strmsg)) {// Toast.makeText(MainActivity.this, "登陆成功", Toast.LENGTH_SHORT).show();// Intent ntnt_feedback = new Intent(MainActivity.this, feedback.class);// startActivity(ntnt_feedback);// } else if ("ERROR".equals(strmsg)) {// tvlog.setText(tvlog.getText() + "else [" + "OK" + "OK".length() + "]");// } } };//mainHandler -end// bn_login.setOnClickListener(new View.OnClickListener() {// @Override// public void onClick(View view) {// sttc_name = et_username.getText().toString();// passwd = et_userpsw.getText().toString();////// Log.i("MainActivity_bn_OnClick", "开始登陆-启动线程 连接服务器【" + sttc_name + "】【" + passwd + "】");// //new netthread().start();// Intent ntnt_feedback = new Intent(MainActivity.this, feedback.class);// startActivity(ntnt_feedback);//// }// }); }//onCreate -end class MainOnClickLstnr implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { case R.id.bn_login: Log.i("MainActivityOnClick", "你点击了 登陆按钮"); usernm = et_username.getText().toString(); passwd = et_userpsw.getText().toString(); if (usernm == null || passwd == null) { //用户名 或 密码 为空 EditText boo = (usernm == null) ? et_username : et_userpsw; boo.setHint("请输入" + ((usernm == null) ? "用户名" : "密码")); break; } Log.i("case R.id.bn_login:", "开始登陆-启动线程 连接服务器【" + usernm + "】【" + passwd + "】"); String url_login = ""; try { //编码 url_login = URLLOGIN_PHP + URLLOGIN_PHP_IN + "&a_name=" + URLEncoder.encode(usernm, "UTF-8") + "&a_psw=" + URLEncoder.encode(passwd, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } //启动线程 验证登陆信息 netthread ntthrd_login = new netthread(url_login, mainHandler); ntthrd_login.start(); break; case R.id.bn_register: Log.i("MainActivityOnClick", "你点击了 注册按钮"); String name_RGST = netthread.trimInnerSpaceStr("" + android.os.Build.MODEL).toString().replace(" ","");//替换空格 String psw_RGST = "psw" + (new Random().nextInt(8999) + 1000);//产生 1000 - 9999 的随机数 //赋值给 未检测是否匹配的全局变量 usernm = name_RGST; passwd = psw_RGST; //编码 String url_rgst = ""; try { url_rgst = URLLOGIN_PHP + URLLOGIN_PHP_RGST + "&a_name=" + URLEncoder.encode(name_RGST, "UTF-8") + "&a_psw=" + URLEncoder.encode(psw_RGST, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.i("case R.id.bn_register","即将提交的注册信息 url_rgst="+url_rgst+"【name_RGST】="+name_RGST+"【psw_RGST】="+psw_RGST); //启动线程 发送注册信息 netthread ntthrd_rgst = new netthread(url_rgst, mainHandler); ntthrd_rgst.start(); break; default: break; } } }//MainOnClickLstnr -end// public class netthread extends Thread {// @Override// public void run() {// Looper.prepare();// line = "";// super.run();//// try {//// URL url = new URL("http://192.168.1.109/mytest/index.php?name=" + sttc_name + "&psw=" + passwd);// HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();// InputStreamReader isr = new InputStreamReader(urlConnection.getInputStream());// BufferedReader br = new BufferedReader(isr);// String readbr;// while ((readbr = br.readLine()) != null)// line += readbr + "\n";//// isr.close();// urlConnection.disconnect();//关闭http连接//// } catch (UnknownHostException e) {// e.printStackTrace();// line += e.toString();// } catch (IOException e) {//// e.printStackTrace();// line += e.toString();// } finally {//// Log.i("Mactivity_Thread", "line = " + line);// Message msg = new Message();// // msg.set// msg.obj = new String(line);// mHandler.sendMessage(msg);// Looper.loop();//// }// }// }}//ALL END
//2 feedback.javapackage com.learn4.wheee.androidclient;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.view.inputmethod.InputMethodManager;import android.widget.AbsListView;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.SimpleAdapter;import android.widget.TextView;import android.widget.Toast;import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.net.URLEncoder;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;/** * Created by Wheee on 2016/7/2. */public class feedback extends Activity { private String username; private String usercomment; //footerview的文字 与 圆形进度框 private ProgressBar progressBar; private TextView textView; private EditText et_comment; private Button bn_send; static Handler mhandler; static String URLBASE = "http://192.168.1.109/mytest/write.php?a_wORr="; static String URLBASE_WRT = "write"; static String URLBASE_RD = "read"; static int LISTITEMNUM = 15;//默认显示 20 条listitem private int LISTITEMNOW=0;//当前共显示了多少条ListView private int LISTVISIBCOUNT = 0;//当前页面可以显示多少条数据 List<HashMap<String, String>> mylist;//mylist每次获取 都更新里面所有值 ListView lv;//ListView private LinearLayout loadingLayout;//listview的footerview布局 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.feedback_layout); lv = (ListView) findViewById(R.id.lv_a); et_comment = (EditText) findViewById(R.id.et_comment); bn_send = (Button) findViewById(R.id.bn_send); //将MainActivity 的name 赋值 到这里 username = MainActivity.sttc_name; //ListView lv设置 TranscriptMode取消‘alwaysScroll’->永远停在最顶端 lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED); //设置监听器 bn_send.setOnClickListener(new feedbackViewOnClikListener());//初始化 //添加FooterView 到ListView AddFooterViewtoListview(); loadingLayout.setId(R.id.LL_listfooterview);//DIY_id.xml 自定义的id loadingLayout.setOnClickListener(new feedbackViewOnClikListener()); mylist = new ArrayList<HashMap<String, String>>();//每次全部替换其值 // et_comment.setText("http://192.168.1.109/mytest/write.php?a_user=lurenyi&a_comment=吐槽几句abc123&a_time=2016-07-03-11:00:01"); //接收 netthread 线程反馈消息 msg.what 1:0 mhandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); //判断是否 为 write 返回值,不是则为 read //操作成功 时 Log.i("handleMessage","【读】【写】 操作判断msg.what="+msg.what+"msg.obj="+msg.obj.toString()); if (netthread.SUCCEED_FLAG_WRT.equals(msg.obj.toString())) { //【写】操作成功 Toast.makeText(feedback.this,"【写】 操作成功",Toast.LENGTH_SHORT).show(); Log.i("handleMessage","【写】 操作成功msg.what="+msg.what); } else if (msg.what == 1) { //【读】操作成功 //read 则msg.obj储存着read数据,已被处理去掉首位空格换行// try {// //解码 UTF-8 PHP中 【/】解码后为【/】// msg.obj = URLDecoder.decode(msg.obj.toString(), "UTF-8");// } catch (UnsupportedEncodingException e) {// e.printStackTrace();// } //先分组 再解码 //【分组】PHP中 【/】解码后为【/】,待处理串中只剩 【/】 String[] UserCommTime = msg.obj.toString().split("/");// 形式表示【\\\\】 可以正确划分 形式表示为【\\】的数组 //【解码】 String str="";//临时变量 for(int i=0;i<UserCommTime.length;i++) { try { str = URLDecoder.decode(UserCommTime[i], "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } UserCommTime[i]=new String(str.toString()); }//解码完毕 //处理末尾的 【读】成功标志位 UserCommTime[UserCommTime.length - 1] = netthread.trimInnerSpaceStr(UserCommTime[UserCommTime.length - 1]); Log.i("handleMessage", "处理末尾的 【读】成功标志位" + UserCommTime[UserCommTime.length - 1]); if (netthread.SUCCEED_FLAG_RD.equals(UserCommTime[UserCommTime.length - 1]))//"ROK" == 数组最后的分组,理论上是ROK { //Toast.makeText(feedback.this, "确定为 【读】 操作" + UserCommTime[UserCommTime.length - 1], Toast.LENGTH_LONG).show(); Log.i("handlMessage", "" + "确定为 【读】 操作" + UserCommTime[UserCommTime.length - 1]); //【读】成功 //确定不是【写】操作,且获取到【读】操作成功FLAG //调用 ListSetAdapter(listview,拆分成数据整条的String数组) ListSetAdapter(UserCommTime);//mylist每次全部替换其值 //【读】完成后 textview改变值, progressBar隐藏 textView.setText("【加载完成】点击加载更多..."); progressBar.setVisibility(View.GONE); textView.setFocusableInTouchMode(true); } } //操作 失败和成功都显示 //Toast.makeText(feedback.this, msg.what == 1 ? "Done" : ("Failed" + msg.obj.toString()), Toast.LENGTH_LONG).show(); Log.i("handlMessage", "" + (msg.what == 1 ? "Done" + msg.obj.toString() : ("Failed" + msg.obj.toString()))); } }; //第一次运行前 获取 listitem 显示 //必须先 创建handler实例 ,第一次只更新 LISTITEMNUM 数量的ListItem final netthread ntthrd_fstread = new netthread(URLBASE + URLBASE_RD + ("&a_nowid=" + LISTITEMNUM),mhandler); ntthrd_fstread.start(); //ListView 滑动监听 lv.setOnScrollListener(new AbsListView.OnScrollListener() { private String url_read = URLBASE + URLBASE_RD;//读取mysql数据 private int lastItemIndex;//是否滑到底了 //private netthread ntForread = new netthread("test"); @Override public void onScrollStateChanged(AbsListView absListView, int scrollState) { // Log.i("onScrollStateChanged", "scrollState = " + scrollState); } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { Log.i("onScroll", "firstVisibleItem = " + firstVisibleItem + " visibleItemCount=" + visibleItemCount + " totalItemCount=" + totalItemCount); lastItemIndex = firstVisibleItem + visibleItemCount - 1;//第一个可见的 加上当前页面可见的listitem数目 = 总共-1 //更新 【当前共显示多少条ListItem】 LISTITEMNOW = totalItemCount-1; LISTVISIBCOUNT=visibleItemCount;//当前页面显示多少条 Log.i("lastItemIndex", "滑动停止 最新数据条数:lastItemIndex = " + lastItemIndex+"\nLISTITEMNOW="+LISTITEMNOW+" LISTVISIBCOUNT="+LISTVISIBCOUNT); //lastItemIndex 索引等于 totalItemCount - 1 时,到达最下面的一个,可以加载刷新view了// if (lastItemIndex >= 0 && lastItemIndex == totalItemCount - 1 && !ntForread.isAlive()) {// // Toast.makeText(feedback.this, "刷新中...", Toast.LENGTH_SHORT).show();// //ntForread = new netthread(url_read + ("&a_nowid=" + lastItemIndex));// // ntForread.start();// Log.i("onScroll_ntForread", "ntForread.isAlive()线程不在活动中 启动线程开始读取listitem");// } else if (ntForread.isAlive()) {// Toast.makeText(feedback.this, "正在刷新中 请稍后...", Toast.LENGTH_SHORT).show();//// } } }); }//Create 函数end //更新 ListView 数据 ;类作为函数参数传递时,传递的是引用 public void ListSetAdapter(String[] StrData) { Log.i("进入ListSetAdapter", "进入ListSetAdapter函数" + StrData.length); //组织数据源 mylist = new ArrayList<HashMap<String, String>>();//mylist每次全部替换其值 //处理StrData ,urlencode($row["User"]).'+'.urlencode($row["Comment"]).'+'.urlencode($row["Time"]).'\\'; for (int i = StrData.length-2; i>=0; i--) { HashMap<String, String> map = new HashMap<String, String>();//中间变量 Hashmap初始定义 String[] singleData = StrData[i].split("&");//【&】分割符 Log.i("", "singleData长度" + singleData.length); singleData[1] = "[" + singleData[2] + "]: " + singleData[1];//singleData[1] = Time + Comment 合并为一条数据 map.put("itemuser", "" + singleData[0]);//USER name map.put("itemcomment", "" + singleData[1]);//USER comment mylist.add(map);//添加一条数据 }// //配置适配器 SimpleAdapter adapter = new SimpleAdapter( this, mylist, R.layout.listitem, new String[]{"itemuser", "itemcomment"}, new int[]{R.id.tv_user, R.id.tv_comment} ); // adapter.notifyDataSetChanged();//强制刷新 新的 ListView //添加进去 lv.setAdapter(adapter); //判断是否第一次显示 而不是后序的 加载更多 lv.setSelection((!(LISTITEMNOW==-1 &&LISTVISIBCOUNT == 0))?(LISTITEMNOW-LISTVISIBCOUNT+2):0);//总共显示了多少条数据 - 当前页面显示多少条 Log.i("进入ListSetAdapter", "ListView数据添加结束LISTITEMNOW="+LISTITEMNOW+" LISTVISIBCOUNT="+LISTVISIBCOUNT); } private void AddFooterViewtoListview() { /** * 设置布局显示属性 */ LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); /** * 设置布局显示目标最大化属性 */ LinearLayout.LayoutParams FFlayoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); //线性布局 LinearLayout layout = new LinearLayout(this); //设置布局水平方向 layout.setOrientation(LinearLayout.HORIZONTAL); //进度条 // final ProgressBar progressBar = new ProgressBar(this); progressBar = new ProgressBar(this); progressBar.setVisibility(View.GONE);//不占用空间 不可见 //把进度条加入到layout中 layout.addView(progressBar, mLayoutParams); //文本内容 // final TextView textView = new TextView(this); textView = new TextView(this); textView.setText("【加载完成】点击加载更多...");// textView.setTextSize(28);//setTextSize()默认的单位是sp textView.setGravity(Gravity.CENTER_VERTICAL);// textView.setOnClickListener(new View.OnClickListener() {// @Override// public void onClick(View view) {// textView.setText("加载中...");// progressBar.setVisibility(View.VISIBLE);//可见// }// }); //把文本加入到layout中 layout.addView(textView, FFlayoutParams); //设置layout的重力方向,即对齐方式是 layout.setGravity(Gravity.CENTER); //设置ListView的页脚layout loadingLayout = new LinearLayout(this); loadingLayout.addView(layout, mLayoutParams); loadingLayout.setGravity(Gravity.CENTER); lv.addFooterView(loadingLayout); } //feedbackViewOnClikListener feedbackView事件监听器 private class feedbackViewOnClikListener implements OnClickListener{ @Override public void onClick(View view) { switch (view.getId()){ case R.id.LL_listfooterview: { Log.i("feedbackView点击监听器","你点击了 ListView的footerview加载更多"); //显示 圆形进度条 progressBar.setVisibility(View.VISIBLE);//可见//感觉这是不安全的做法 textView.setText("加载中..."); //获取数据库 更新ListView;LISTITEMNUM + LISTITEMNOW条数据 netthread ntthrd_read = new netthread(URLBASE + URLBASE_RD + ("&a_nowid=" + (LISTITEMNUM+LISTITEMNOW)),mhandler); ntthrd_read.start(); break; } case R.id.et_comment: { Log.i("feedbackView点击监听器","你点击了 评论编辑框"); } case R.id.bn_send: { //判断是否为空 if(et_comment.getText().toString().equals("")) { et_comment.setFocusable(true); et_comment.setFocusableInTouchMode(true); break;} Log.i("feedbackView点击监听器","你点击了 发送评论的按钮"); //发送数据 String url_write = URLBASE + URLBASE_WRT; SimpleDateFormat myfmt = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss "); Date dt = new Date(); //获取 View 数据 // username = netthread.trimInnerSpaceStr(""+android.os.Build.MODEL); usercomment = et_comment.getText().toString(); String timestr = new String(myfmt.format(dt)); try { url_write = url_write + "&a_user=" + (URLEncoder.encode(username, "utf-8")) + "&a_comment=" + URLEncoder.encode(usercomment, "utf-8") + "&a_time=" + URLEncoder.encode(timestr, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.i("setOnClickListener_启动线程", url_write + ""); //启动线程 netthread nt_write = new netthread(url_write,mhandler); nt_write.start(); et_comment.setText(""); //关闭输入法 如果输入法在窗口上已经显示,则隐藏,反之则显示 InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); //创建线程更新 ListView //获取数据库 更新ListView;LISTITEMNUM + LISTITEMNOW条数据 netthread ntthrd_read = new netthread(URLBASE + URLBASE_RD + ("&a_nowid=" + (LISTITEMNUM+LISTITEMNOW)),mhandler); ntthrd_read.start(); } } } }}// //点击 提交按钮发送至服务器mysql存储// bn_send.setOnClickListener(new OnClickListener() {// @Override// public void onClick(View view) {//// String url_write = URLBASE + URLBASE_WRT;//// SimpleDateFormat myfmt = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss ");//// Date dt = new Date();//////////// //获取 View 数据//// username = netthread.trimInnerSpaceStr(""+android.os.Build.MODEL);//// usercomment = et_comment.getText().toString();//// String timestr = new String(myfmt.format(dt));//////// try {//// url_write = url_write + "&a_user=" +//// (URLEncoder.encode(username, "utf-8")) + "&a_comment=" +//// URLEncoder.encode(usercomment, "utf-8") + "&a_time=" +//// URLEncoder.encode(timestr, "utf-8");//// } catch (UnsupportedEncodingException e) {//// e.printStackTrace();//// }//// Log.i("setOnClickListener_启动线程", url_write + "");//// //启动线程//// netthread nt_write = new netthread(url_write);//// nt_write.start();//// et_comment.setText("");// }// });//setOnClickListener函数end
//3 netthread.java 网络线程package com.learn4.wheee.androidclient;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.Log;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;import java.net.UnknownHostException;public class netthread extends Thread { private String threadInfo; private String urlstring; static Message msg = new Message(); private Handler ntthrd_handler;//未指定activity的handler static String SUCCEED_FLAG_WRT = "WOK";//操作成功后服务器的返回值 write static String SUCCEED_FLAG_RD = "ROK";// read// static boolean issucceed = false; netthread(String url,Handler h) { this.urlstring = url; this.ntthrd_handler = h;//指定activity } @Override public void run() { Looper.prepare(); super.run(); threadInfo = ""; msg.obj = null; msg.what = 0;//初始化 //0-ERROR 表示android端与php传输数据流是出错 而不是mysql与php之间的错误 try { //GET方式发送数据 URL url = new URL(urlstring); //接收服务器反馈 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStreamReader isr = new InputStreamReader(urlConnection.getInputStream()); BufferedReader br = new BufferedReader(isr); String strbr="",Allstrbr="";//中间变量 while ((strbr = br.readLine()) != null) Allstrbr += strbr + "\n"; threadInfo = Allstrbr;//赋值,去除threadInfo的初始值 isr.close();//流 关闭 urlConnection.disconnect();//关闭http连接 msg.what = 1;//可能出错的语句 全部执行完毕 } catch (UnknownHostException e) { e.printStackTrace(); threadInfo += e.toString() + "AND"; msg.what = 0;//ERROR } catch (IOException e) { e.printStackTrace(); threadInfo += e.toString() + "AND"; msg.what = 0;//ERROR 与php传输数据流是出错 而不是mysql与php之间的错误 } finally { //简单处理 去掉首位空格换行 threadInfo = trimInnerSpaceStr(threadInfo); Log.i("我是线程:netthread", "android-php 网络传输过程的信息threadInfo=" + threadInfo); msg.obj = new String(threadInfo); //临时 Message,防止主线程同时访问 msg导致出错 Message msg_copy =new Message(); msg_copy.obj = new String(msg.obj.toString());//新的类,不是引用 msg_copy.what = msg.what; //feedback.mhandler.sendMessage(msg_copy);//发送消息 msg以引用形式被发送至 主线程 this.ntthrd_handler.sendMessage(msg_copy); Looper.loop(); } } //处理串 去掉String 首位所有 换行 空格 static String trimInnerSpaceStr(String str) { str = str.trim(); while (str.startsWith(" ") || str.startsWith("\n")) { str = str.substring(1, str.length()).trim(); } while (str.endsWith(" ") || str.endsWith("\n")) { str = str.substring(0, str.length() - 1).trim(); } return str; }}
//listitem.xml ListView的单条数据布局文件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_item" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#F0FFFF" android:orientation="horizontal" android:paddingTop="10dp" android:paddingBottom="10dp"> <TextView android:id="@+id/tv_user" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.2" android:text="用户 甲" android:textColor="#000000" android:textSize="20sp" /> <ScrollView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.8"> <TextView android:id="@+id/tv_comment" android:layout_width="match_parent" android:layout_height="match_parent" android:includeFontPadding="true" android:scrollHorizontally="true" android:text="我想吐槽的是......" /> </ScrollView></LinearLayout>
//feedback_layout.xml<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/LL_lv" android:layout_marginTop="130px" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:id="@+id/lv_a" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:focusable="true" android:focusableInTouchMode="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="100px" android:orientation="horizontal" android:background="#FFFAF0" android:weightSum="1"> <EditText android:id="@+id/et_comment" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.8" android:hint=" 吐槽点什么吧.." /> <Button android:id="@+id/bn_send" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.2" android:text="发送" /> </LinearLayout></RelativeLayout>
//MainActivity.xml 实现登陆注册界面<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@mipmap/ic_launcher" > <LinearLayout android:orientation="vertical" android:layout_marginTop="600px" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/et_name" android:layout_width="600px" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:hint="用户名" /> <EditText android:id="@+id/et_psw" android:layout_width="600px" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:hint="密 码" /><RelativeLayout android:layout_width="600px" android:layout_gravity="center_horizontal" android:orientation="horizontal" android:layout_height="wrap_content"> <Button android:id="@+id/bn_login" android:layout_toLeftOf="@id/et_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登陆" /> <Button android:id="@+id/bn_register" android:layout_alignParentRight="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="一键注册"/> <TextView android:layout_below="@id/bn_login" android:layout_alignParentRight="true" android:padding="20px" android:id="@+id/tv_log" android:layout_width="6000px" android:layout_height="wrap_content" android:minHeight="600px" android:background="#bf696969" android:text="等待服务器回应..." android:textColor="#696969" android:textSize="30px" /></RelativeLayout> </LinearLayout></RelativeLayout>
//diy_id.xml 添加id的xml文件<?xml version="1.0" encoding="utf-8"?> <resources> <item name="LL_listfooterview" type="id" /></resources>
最后吐槽一句:csdn每次点开固定两个广告,能不能换换风格,还有这个 编辑器比较难用,字体大小颜色说变就变。。不知咋回事。忘了php//login.php<?php$LGN_IN_RGST = $_GET['a_lgninout'];//denglu-IN OR zhuce-RGST$name = $_GET['a_name'];$psw = $_GET['a_psw']; $con = mysqli_connect("localhost","root","","testlogin");if (!$con){//die('Could not connect: ' . mysqli_error($con));die ('ERROR&服务器连接失败 请重试');} else{if($LGN_IN_RGST == "IN"){//INmysqli_query($con,'set names utf8');$sql = "select * from users WHERE name = '$name'";$result = mysqli_query($con,$sql);//name 查询不存在if(!$result){die ('ERROR&此用户名没有注册');}$row = mysqli_fetch_array($result,MYSQLI_BOTH);//比较 name对应的 pswif($psw == $row[2]){echo 'OK&LOGINOK';}else{die('ERROR&密码不正确'); }}//IN -end////else{//RGST//获取最新的一条数据的 umID$sql = "select max(id) from users";$result = mysqli_query($con,$sql);$row = mysqli_fetch_array($result,MYSQLI_BOTH);$MaxId = $row[0];//zuixin//$name 附上当前id,使其独一无二$name = $name.''.$MaxId;mysqli_query($con,'set names utf8');$sql = "INSERT INTO users(name, psw) VALUES ('$name','$psw')";if (!mysqli_query($con,$sql)){die('ERROR&注册失败 请联系管理员');}else{//返回OK和最大ID,更新用户名控件值echo 'OK&'."$name";}}//RGST -end}mysqli_close($con);?>//write.php<?php $con = mysqli_connect("localhost","root","","testlogin");if (!$con){die('Could not connect: ' . mysqli_error($con));} $wrtORrd = $_GET['a_wORr'];if($wrtORrd == 'write') //WRITE{$comment = $_GET['a_comment'];$user = $_GET['a_user'];$time = $_GET['a_time']; mysqli_query($con,'set names utf8');$sql = "INSERT INTO usercomment(User, Comment, Time) VALUES ('$user','$comment', '$time')";if (!mysqli_query($con,$sql)){die('Error: '.mysqli_error($con));}else{echo 'WOK';}}else if($wrtORrd == 'read') //READ{ $NowId = $_GET['a_nowid'];//获取多少条数据mysqli_query($con,'set names utf8');//获取最新的一条数据的 umID$sql = "select max(umID) from usercomment";$result = mysqli_query($con,$sql);$row = mysqli_fetch_array($result,MYSQLI_BOTH);$MaxId = $row[0];//zuixin//echo "MaxId =$MaxId";//【MaxId】越界判断//umID没有第0条数据$min = $MaxId-$NowId+1;//NowId 条数据if($min <= 0){$min = 0;}mysqli_query($con,'set names utf8');$sqlr = "SELECT * FROM usercommentWHERE umID>=$min AND umID<=$MaxId";$result = mysqli_query($con,$sqlr);//echo 'OK';while($row = mysqli_fetch_array($result,MYSQLI_ASSOC)){ //echo $row["User"].'+'.$row["Comment"].'+'.$row["Time"];//echo '<br>'; echo urlencode($row["User"]).'&'.urlencode($row["Comment"]).'&'.urlencode($row["Time"]).'/';//echo '<br>'; }echo 'ROK';//读取结束}else{echo 'wrtOrrdERROR';}mysqli_close($con);function characet($data){if( !empty($data) ){ $fileType = mb_detect_encoding($data , array('UTF-8','GBK','LATIN1','BIG5')) ; if( $fileType != 'UTF-8'){ $data = mb_convert_encoding($data ,'utf-8' , $fileType); } } return $data; }?>
大概思路:androi端 点击 一键注册 按钮,由android端自动生成【用户名】【密码】,经编码后,调用GET方法向write.php传递编码后包含数据的url,write.php收到来自Android端请求,开始解析url,然后对应选择 相应语句,发送指令到mysql,要求增加一条表单数据同时将来自android端的【用户名】【密码】发送到mysql;mysql收到来自php的请求,做出反应,向对应表单中增加了一条来自android端的【用户名】【密码】数据,然后返回php,php收到mysql的返回值,判断处理后,再向android端发送返回值,android就收到来自php的反馈信息,处理判断是否操作成功。写了大段话,按了个靠右快捷键ctrl R 居然被刷新,!!!为何不设置个提示,刷新会清空当前所写的????csdn感觉不好啊,刚开始记录代码生涯,若有不妥之处还请告知1176222373@qq.com
- android小项目 连接PHP开发的服务端
- PHP服务端项目开发经历——解决Android客户端中多图片上传的问题
- 服务端开发的一些小问题
- 服务端开发小感
- 服务端开发小感
- 服务端开发小感
- 服务端开发小感
- 服务端开发小感
- 开发android服务端的开发环境配置
- 大三软件工程小项目-小技术集合-服务端连接MySQL及对表插入、删除、查询
- Android开发项目小总结
- Android 蓝牙开发小项目
- android-开发一个小项目
- 【转】服务端开发小感
- android中对服务端的长连接【socket】
- Android与服务端的Socket连接实现简单数据传输
- android中对服务端的长连接【socket】
- 使用mina保持android端和服务端的长连接
- 代码中调用 linux 命令批量删除指定redis缓存数据
- Set,List,Map(一)(Java面试)
- ios9模拟器上下出现黑边
- JAVA传入实体返回实体工具
- Android接入支付宝支付服务
- android小项目 连接PHP开发的服务端
- Android ScrollView监听值判断在底部还是顶部
- 使用Markdown设置文档样式,生成html文件
- C语言的指针
- 分析iOS Crash文件:符号化iOS Crash文件的3种方法
- docker registry_v2 部署过程中遇到的坑
- Convert polygon faces to triangles or quadrangles
- 【R语言】用Shiny包搭建交互网页
- ubuntu系统中webpy的使用