开始拿到这个需求,我是首先解决软件启动的时候自动下载这个功能。拿到目标软件的url就行了。这里就借鉴百度手机助手,看了他们的应用之后,如果手机没有装百度手机助手。我又点击了高速下载想下一个其它软件,他们每次从浏览器下载平台应用都是以一个appName_id_code.apk命名。然后将这个apk丢在download文件夹下面。就猜想肯定是应用第一次启动的时候去扫描download、UCdownload等一系列可能存放apk的位置。然后直接根据文件名匹配。在匹配到他的平台应用apk。然后取出了中间的我要下载的目标软件的id然后应用中进行自动下载的。这个需求这样做了。这是手机没有安装平台应用好说。好问题是安装了就直接打开下载。当然第一反应是用sheme 如果安装直接通过设置:
<intent-filter> <data android:host="hostname" android:pathPrefix="路径" android:scheme="myapp" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" /> <action android:name="android.intent.action.VIEW" /> </intent-filter>
这样开启应用传递值过去,
if (Intent.ACTION_VIEW.equals(getIntent().getAction())) { //如果是跳转过来的得重置下这个状态让不要扫描SD卡 Env.isFirstDownLoad = false; Intent intent = getIntent(); Uri uri = intent.getData(); if (uri != null) { String dId = uri.getQueryParameter("dId"); String url = AppDetailUtils.APP_DETAIL_URL + "?masterId=" + dId; toDownload(url); } }
获取传递的值就行了。
接下来问题就来了。浏览器中怎么判断是否安装了本地应。。。在网上找了各种js方法都不能如意得到。不是浏览器打不开,就是各种弹窗。最后想到了是看网上有网友提出了一个起一个服务监听端口的方案。没找到代码 于是就凑合的写的试试。以手机作为服务端起一个服务监听一个定义的端口。如果在浏览器对这个地址有请求则证明安装了该应用就直接跳转。如果是没有响应就直接跳转到下载链接(其实主要是浏览器中怎么判断手机安装了应用的问题)。于是就试着写了很简单的服务器端口监听例子:
//服务端监听端口 然后页面进行访问
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.HashMap; import java.util.Map; import android.util.Log; public class HttpSocketServer extends Thread { private Socket socket; public HttpSocketServer(Socket socket) { this.socket = socket; } public void run() { String data = "getAppData && getAppData({\"error\":4});"; try { BufferedReader reader = new BufferedReader(new InputStreamReader( socket.getInputStream())); // jsonp处理,暂时没必要 Map<String, String> headMaps = new HashMap<String, String>(); String path = reader.readLine(); String headerStr; while (null != (headerStr = reader.readLine())) { if (headerStr.equals("")) { break; } } path = path.substring(path.indexOf(" "), path.lastIndexOf(" ")) .trim(); String paramstr; if (path.indexOf("?") != -1) { paramstr = path.substring(path.indexOf("?") + 1); } else { paramstr = path; } String[] strs = paramstr.split("&"); for (String ss : strs) { int index = ss.indexOf("="); if (index == -1) break; String key = ss.substring(0, ss.indexOf("=")); String value = ss.substring(ss.indexOf("=") + 1, ss.length()); headMaps.put(key, value); Log.i("pconline", key + " " + value); } if (null != headMaps && headMaps.get("callback") != null) { // data = headMaps.get("callback")+"("+data+")" ; } Log.i("pconline", "data=== " + data); OutputStreamWriter streamWriter = new OutputStreamWriter( socket.getOutputStream(), "utf-8"); BufferedWriter bufferedWriter = new BufferedWriter(streamWriter); bufferedWriter.write("HTTP/1.1 200 OK \r\n"); bufferedWriter.write("Content-Type: text/html\r\n"); bufferedWriter.write("Access-Control-Allow-Origin: *\r\n"); bufferedWriter.write("Date: Thu, 13 Nov 2014 01:27:22 GMT\r\n"); bufferedWriter.write("Connection: keep-alive\r\n"); bufferedWriter.write("Content-Length: " + data.length() + "\r\n\r\n"); bufferedWriter.write(data); bufferedWriter.write("\r\n"); bufferedWriter.flush(); reader.close(); bufferedWriter.close(); socket.close(); } catch (Exception e) { e.printStackTrace(); } } }
在电脑浏览器上面先试验肯定是可以的。写手机上面试了下。结果不错也很好。接下来就是手机浏览器中实验了。于是写了个测试例子:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GBK" /> <title>测试用</title> <script type="text/javascript"> var xmlHttp; function createXMLHttpRequest() { if(window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if(window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } } function startRequest(url) { createXMLHttpRequest(); try { xmlHttp.onreadystatechange = function(){ handleStateChange()}; xmlHttp.open("GET", url, false); //xmlhttp.SetRequestHeader("Content-Type","text/html; charset=UTF-8") xmlHttp.send(null); } catch(exception) { //这里跳转到下载链接 window.location.href="http://www1.pconline.com.cn/mobile/pconline.apk"; } } function handleStateChange() { if(xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { // 测试如果安装就开启应用 下载id为357956 的应用 window.location="myapp://appcenter.download/downloadwith?dId=357945"; }else{ //跳转到下载地址 } } } </script> </head> <body> <a href="javascript:startRequest('http://localhost:5869/')">调用测试</a> </body> </html>
如果安装了应用就会响应监听给返回值。其实返回值对我没用。我只需要知道能访问通就行了。访问不通就直接去下载平台应用。
PS: 之前这个不是很稳定,原来是程序退出的时候代码上面用的不是finish(),而是用的system.exit(0)。这个方法会关闭所有的进程。导致服务可能是被关闭了又重新启动。这样用上面方法跳转就不稳定了。有时候跳的过去,有时候跳不过去了。所以最好是将监听服务另起,以后不能用system.exit(0)退出。这就是坑啊!统一写一个activity管理内进行finish退出。