首先声明一下小弟对ios也不是很熟,不喜勿喷啊。
首先说一下需求吧,现在有很多的应用已经是存储在数据库中,而ios的设备只需打开指定的网址点击相应应用链接即可完成应用的下载。
好,现在开始走流程具体实现的过程。
一、连接到sybase数据库(应用的数据是存储在这个数据库中的),连接需要的jdbc自己上网上找(jconn3.jar)。
package com.justsy.db;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBManager {
// 返回数据库连接对象
public Connection createConn() {
Connection conn = null;
try {
Class.forName("com.sybase.jdbc3.jdbc.SybDriver");
String url = "jdbc:sybase:Tds:192.168.2.143:2638/AfariaDb_Asa11";
conn = DriverManager.getConnection(url, "akwolf", "123456");
return conn;
} catch (Exception fe) {
System.err.println("createConn(): " + fe.getMessage());
return null;
}
}
}
二、一个设备要得到可用的应用列表是传递当前设备id到数据库中取得的,
AppList
template.plist
items
assets
kind
software-package
url
http://192.168.2.27:8080/justsy/CSuiteBuyer_Int1.ipa
kind
display-image
needs-shine
url
http://192.168.2.27:8080/justsy/ifw114.png
kind
full-size-image
needs-shine
url
http://192.168.2.27:8080/justsy/ifw114.png
metadata
bundle-identifier
com.sap.DS4M.C-SuiteBuyer.internal
bundle-version
8.0.3.99
kind
software
subtitle
Everlight
title
Everlight
1、取得设备id使用ajax请求回可用的应用列表,并拼装成超链接列表。
2、在拼装超链接列表时是有讲究的,http://192.168.2.101:8080/JustsyApp/template.plist">Install App
红色部分是一个应用的描述文件,而描述文件中指明了应用下载的地址,和显示图片的地址及一些描述信息
注意点:在做到这一步时遇到一个的问题,在url超链接中无法接参数加上"=","{}"或"&"之类的字符点击就没反应,最后的解决方案是使用":"进行参数的分割。不知道这其中有什么门道,知道的大虾可以指点哈。
三、好了现在的任务重点是根据点击的超链接动态的生成plist的描述xml文件,这里使用jdom(jar包自己上网上找)进行xml的相关操作,恩,,把根据应用id生成plist描述文件的代码贴出来
package com.justsy.productXML.jdom;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.xml.sax.SAXException;
import com.justsy.db.DBManager;
public class RroductFile extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String param = "" ;
// 格式[PackageID:2a67a513-bbd5-431d-8630-f03b39b89ea1]
Enumeration en = request.getParameterNames() ;
if(en.hasMoreElements()){
param = en.nextElement() ;
}
// 取得AppList.html中传递的PackageID,并将PackageId拼装到plist中并输出
String PackageID = param.substring(param.lastIndexOf(":")+1) ;
String responseText = this.cereatePlist(this.getServletContext()
.getRealPath("/"), PackageID);
OutputStream os = response.getOutputStream();
byte stringMsg[] = responseText.getBytes();
os.write(stringMsg);
} catch (SQLException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
}
}
private String cereatePlist(String path, String PackageID)
throws IOException, SQLException, JDOMException {
SAXBuilder sb = new SAXBuilder();
// 加载plist模板
Document doc = sb.build(new File(path + "manifest.plist"));
Element root = doc.getRootElement(); // 获取根元素
Element root2 = root.getChild("dict");
Element root3 = root2.getChild("array");
Element root4 = root3.getChild("dict");
Element root5 = root4.getChild("array");
Element metadataDict = root4.getChild("dict") ;
List root6 = root5.getChildren("dict");
Element msg = (Element) root6.get(0);
List stringList = msg.getChildren("string");
Element msgIpa = (Element) stringList.get(1);
//System.out.println(PackageID);
// 指向app下载的路径
msgIpa.setText("http://192.168.2.101:8080/JustsyApp/Applet?action=downPlist:ContentTypeID=1:PackageID="
+ PackageID);
Element msg2 = (Element) root6.get(1);
List stringList2 = msg2.getChildren("string");
Element msgImg = (Element) stringList2.get(1);
// 指向小图片显示地址
msgImg.setText("http://192.168.2.101:8080/JustsyApp/Applet?action=downImg:ContentTypeID=4:PackageID="+PackageID);
Element msg3 = (Element) root6.get(2);
List stringList3 = msg3.getChildren("string");
Element msgSmallImg = (Element) stringList3.get(1);
// 指向大图片显示地址
msgSmallImg.setText("http://192.168.2.101:8080/JustsyApp/Applet?action=downImg:ContentTypeID=5:PackageID="+PackageID);
InputStream stream = getAppInfoStream("{"+PackageID+"}") ;
saxContentInfo(metadataDict,stream) ;
Format format = Format.getPrettyFormat();
XMLOutputter xmlout = new XMLOutputter(format);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
xmlout.output(doc, bo);
String xmlStr = bo.toString();
System.out.println("xml created!!!");
bo.flush() ;
bo.close() ;
System.out.println(xmlStr);
return xmlStr;
}
// getContentInfo
// 对软件信息进行解析
private void saxContentInfo(Element metaData,InputStream stream) throws JDOMException, IOException{
List strings = metaData.getChildren("string") ;
Element identifier = (Element) strings.get(0) ;
Element version = (Element) strings.get(1) ;
Element subtitle = (Element) strings.get(3) ;
Element title = (Element) strings.get(4) ;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance() ;
try {
DocumentBuilder builder = factory.newDocumentBuilder() ;
org.w3c.dom.Document doc = builder.parse(stream) ;
String val1 = doc.getElementsByTagName("CFBundleIdentifier").item(0).getFirstChild().getNodeValue() ;
String val2 = doc.getElementsByTagName("CFBundleVersion").item(0).getFirstChild().getNodeValue() ;
String val3 = doc.getElementsByTagName("CFBundleName").item(0).getFirstChild().getNodeValue() ;
String val4 = doc.getElementsByTagName("CFBundleDisplayName").item(0).getFirstChild().getNodeValue() ;
//System.out.println(val);
identifier.setText(val1) ;
version.setText(val2) ;
subtitle.setText(val3) ;
title.setText(val4) ;
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
private InputStream getAppInfoStream(String packageId) throws SQLException, IOException {
//String str = "" ;
DBManager db = new DBManager();
Connection conn = db.createConn();
String sql = "select * from A_PRFL_PACKAGE_CONTENT where PackageID= ? and ContentTypeID=1";
PreparedStatement pstmt = conn.prepareStatement(sql) ;
pstmt.setString(1, packageId) ;
ResultSet rs = pstmt.executeQuery();
rs.next() ;
InputStream stream = rs.getBinaryStream("ContentVersion") ;
//rs.close() ;
//pstmt.close() ;
return stream ;
}
}
四、好走到这一步,数据库读取数据没问题的话就可以进行应用的下载安装了,但是在实际的测试中遇到下载速度相当的缓慢不知道什么原因。
五、在实际服务器端读取数据库中应用时,出现读取数据库(数据库使用的是sybase数据库)二进制文件32k的限制,后来在网上找到问题的解决方案。具体就是statement中设置set textsize 50000000,
/**
* 下载app
*
* @param response
* @throws IOException
* @throws SQLException
*/
private void downloadApp(HttpServletResponse response,
HttpServletRequest request) throws IOException, SQLException {
DBManager db = new DBManager();
Connection conn = db.createConn();
String param = request.getParameter("action");
// System.out.println(param);
String packageId = this.getParameter(param, "PackageID");
packageId = "{" + packageId + "}";
String sql = "select * from A_PRFL_PACKAGE_CONTENT where PackageID='"
+ packageId + "' and ContentTypeID=1";
System.out.println(sql);
Statement stmt = conn.createStatement();
stmt.executeUpdate("set textsize 50000000");
ResultSet rs = stmt.executeQuery(sql);
if (!rs.next()) {
return;
}
String appName = rs.getString("ContentFileName");
InputStream inputStream = rs.getBinaryStream("ContentData");
// conn.close();
sendDownload(response, inputStream, appName);
}
六、注意点plist中的ipa和图片地址不要使用https协议,可能导致应用无法下载。
Ok,,现在在ipad上测试点击应用的连接就可以进行应用的下载了