对安卓在浏览器中判断是否有本地应用安装,并打开本地应用的总结

开始拿到这个需求,我是首先解决软件启动的时候自动下载这个功能。拿到目标软件的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退出。

你可能感兴趣的:(对安卓在浏览器中判断是否有本地应用安装,并打开本地应用的总结)