很久没做安卓。为了不忘记。开始一个个人的小项目。
喜欢玩游戏,以前是魔兽世界,现在是英雄联盟。游戏玩的很糟糕,所以我就想走捷径,搞一些外挂。但是免费的有病毒,收费的又不想花钱。。。我是不是太小气了。
学编程这么久,其实内心还是一个外挂的心。但是可惜我学的不是C,做外挂是没戏了。
这两天玩游戏10连败,吐血啊,于是看看书,看看代码。突然感觉我应该做点啥,外挂做不成,游戏的辅助要做一个。
选游戏当然是英雄联盟,最熟悉的。 看看市场上的游戏辅助,最火的当属LOL盒子。电脑的客户端我做不出来,但是手机客户端我可以做。
参考下自己的能力,比较熟悉PHP和安卓。服务端和客户端都具备。
参与了不少项目,发现最难的就是坚持。一开始不能全部上。
我这个游戏辅助,最重要的功能就是 战绩查询,做好了,再做好友上线提醒。这是最核心。
客户端的外观只能模仿了。
功能思路整理了下:
检查了LOL盒子的在线查询,发现可以作为API使用。
地址是 http://lolbox.duowan.com/playerDetail.php
需要传递2个参数:服务器名称与角色名称
serverName 与 playerName
方式:get
返回的字符串是Html. 需要解析该html,获得自己想要的数据。
有了该接口以后。 就简单了。希望多玩别修改。
昨晚写了客户端,请求该接口,成功获得数据。 但是突然发现自己太笨了,客户端如果直接请求多玩的接口,以后万一 多玩返回的内容改变了,则出现内容错误。
于是修改了流程。 客户端请求 服务端的接口,服务端请求多玩的接口。 这样即使多玩出现改变,客户端也不会收到影响。 有利于控制。
万事具备,只欠东风。使用php和java分别实现了调用多玩的接口 ,解析Html的成功的小例子作备用。
服务端核心代码如下:使用了第三方开源的类库来解析html。
使用该类库需要开启php扩展:tidy 在php.ini中修改。
$baseUrl = ‘http://lolbox.duowan.com/playerDetail.php‘; $serverName=‘均衡教派‘; $playerName =‘随心与娱乐‘; $serverName = urlencode($serverName); $playerName = urlencode($playerName); $url = $baseUrl."?serverName=".$serverName."&playerName=".$playerName; $html = file_get_contents($url); //引入类库 Vendor(‘h.Parser‘); $html_dom = new \Parser(); $html_dom->parseStr($html); $ret = $html_dom->find(‘div.fighting‘,0);
客户端的实现代码:java
1 package cn.wuwenfu.test; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.UnsupportedEncodingException; 7 import java.net.HttpURLConnection; 8 import java.net.MalformedURLException; 9 import java.net.URL; 10 import java.net.URLEncoder; 11 import java.util.HashMap; 12 import java.util.Iterator; 13 import java.util.Set; 14 15 import org.htmlparser.Node; 16 import org.htmlparser.NodeFilter; 17 import org.htmlparser.Parser; 18 import org.htmlparser.filters.AndFilter; 19 import org.htmlparser.filters.HasAttributeFilter; 20 import org.htmlparser.filters.HasChildFilter; 21 import org.htmlparser.filters.NodeClassFilter; 22 import org.htmlparser.filters.TagNameFilter; 23 import org.htmlparser.nodes.RemarkNode; 24 import org.htmlparser.util.NodeIterator; 25 import org.htmlparser.util.NodeList; 26 27 28 29 30 public class TestHtml { 31 private static String ENCODE = "GBK"; 32 33 34 public static void main(String[] args) { 35 36 37 HashMap<String,String> m = new HashMap<String,String>(); 38 39 m.put("serverName", "均衡教派"); 40 m.put("playerName", "3douniwan3"); 41 42 43 String str = getHTML("http://lolbox.duowan.com/playerDetail.php",m, "utf-8"); 44 45 46 try{ Parser parser = new Parser(str); 47 48 //添加过滤器 49 //过滤器1:标签名为div的所有标签 50 // NodeFilter filter= new TagNameFilter("DIV"); 51 //过滤器2:子节点为div的节点、必须传递一个过滤器参数到构造中去。还提供一个构造,有2个参数,第二个参数控制子节点的深度。 52 // HasChildFilter childFilter = new HasChildFilter(filter); 53 //过滤器3:匹配属性的节点 54 // NodeFilter filter =new HasAttributeFilter(); 55 // NodeFilter filter =new HasAttributeFilter("id"); 56 // NodeFilter filter =new HasAttributeFilter("id","playerNameLink"); 57 //过滤器3:可以组合过滤器。必须符合某种逻辑才匹配出 58 // NodeFilter f1 =new HasAttributeFilter("id"); 59 // NodeFilter f2 =new HasAttributeFilter("class","mod-tabs"); 60 // NodeFilter f3 =new AndFilter(f1, f2); 61 // 62 //过滤器4:节点类型过滤器:这里过滤的是有注册的标签 63 NodeClassFilter filter = new NodeClassFilter(RemarkNode.class); 64 65 //过滤器5:字符串过滤器 66 67 68 69 70 NodeList nodes = parser.extractAllNodesThatMatch(filter); 71 // NodeList nodes = parser.extractAllNodesThatMatch(childFilter); 72 // NodeList nodes = parser.extractAllNodesThatMatch(f3); 73 74 for (int i = 0; i < nodes.size(); i++) { 75 Node n = nodes.elementAt(i); 76 message("================================================="); 77 message("getText:"+n.getText()); 78 message("getPlainText:"+n.toPlainTextString()); 79 message("toHtml:"+n.toHtml()); 80 message("toHtml(true):"+n.toHtml(true)); 81 message("toHtml(false):"+n.toHtml(false)); 82 message("toString:"+n.toString()); 83 message("================================================="); 84 } 85 86 87 // for (NodeIterator i = parser.elements (); i.hasMoreNodes(); ) { 88 // Node node = i.nextNode(); 89 // message("getText:"+node.getText()); 90 // message("getPlainText:"+node.toPlainTextString()); 91 // // message("toHtml:"+node.toHtml()); 92 // // message("toHtml(true):"+node.toHtml(true)); 93 // // message("toHtml(false):"+node.toHtml(false)); 94 // message("toString:"+node.toString()); 95 // message("================================================="); 96 // } 97 } 98 catch( Exception e ) { 99 System.out.println( "Exception:"+e ); 100 } 101 102 //System.out.println(str); 103 } 104 105 106 public static String getHTML(String httpUrl,HashMap<String,String> map, String Charset) { 107 String html = ""; 108 String query = "?"; 109 110 Set<String> key = map.keySet(); 111 for (Iterator it = key.iterator(); it.hasNext();) { 112 String s = (String) it.next(); 113 //System.out.println(map.get(s)); 114 try { 115 query +=s+"="+URLEncoder.encode(map.get(s), "utf-8"); 116 query +="&"; 117 118 } catch (UnsupportedEncodingException e) { 119 // TODO Auto-generated catch block 120 e.printStackTrace(); 121 } 122 } 123 124 try { 125 126 System.out.println("====="+httpUrl.toString()+query); 127 URL url = new URL(httpUrl.toString()+query); 128 StringBuffer document = new StringBuffer(); 129 try { 130 HttpURLConnection urlCon = (HttpURLConnection) url.openConnection(); 131 urlCon.connect(); 132 BufferedReader reader = new BufferedReader( 133 new InputStreamReader(urlCon.getInputStream(),"utf-8")); 134 String Result = ""; 135 while ((Result = reader.readLine()) != null) { 136 document.append(Result); 137 // System.out.println(Result); 138 } 139 140 html = document.toString(); 141 } catch (IOException e) { 142 html = "服务未响应"; 143 144 } 145 } catch (MalformedURLException e) { 146 html = "不支持的协议"; 147 148 } 149 150 return html; 151 } 152 153 private static void message( String szMsg ) { 154 try{ System.out.println(new String(szMsg.getBytes(ENCODE), System.getProperty("file.encoding"))); } catch(Exception e ){} 155 } 156 157 158 }
安卓界面代码
package com.wuwenfu.lolhelp; import android.support.v7.app.ActionBarActivity; import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; @SuppressLint("ShowToast") public class MainActivity extends ActionBarActivity implements OnClickListener { private static final String TAG = "调试"; private static final int MSG_SUCCESS = 0;//获取成功的标识 private static final int MSG_FAILURE = 1;//获取失败的标识 private Button submitBtn; private EditText roleName; private EditText serverName; private ProgressBar proBar; private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case MSG_SUCCESS: Toast.makeText(getApplicationContext(), "成功", Toast.LENGTH_LONG).show(); proBar.setVisibility(View.GONE); Log.e(TAG, "-------成功--------"); break; case MSG_FAILURE: Toast.makeText(getApplicationContext(), (String)msg.obj, Toast.LENGTH_LONG).show(); proBar.setVisibility(View.GONE); Log.e(TAG, "-------失败--------"); break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); Log.e(TAG, "-------启动完毕--------"); } @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; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private void init(){ submitBtn = (Button) this.findViewById(R.id.submit); submitBtn.setOnClickListener(this); roleName = (EditText) this.findViewById(R.id.rolename); serverName = (EditText) this.findViewById(R.id.servername); proBar = (ProgressBar) this.findViewById(R.id.probar); } //监听点击事件 @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.submit: Log.e(TAG, "--------点击按钮-------"); //先显示进度条再进行操作 proBar.setVisibility(View.VISIBLE); Log.e(TAG, "------显示进度条---------"); //开始线程处理事务 new Thread(new NetConnect(mHandler)).start(); //跳转到 // startActivity(new Intent (MainActivity.this, ResultActivity.class) ); break; default: break; } } }
客户端的目录结构暂时如下