原文: Cordova app 检查更新 ----创建项目、添加插件、修改插件(一)
使用Cordova 进行跨平台应用程序的开发
1.创建Cordova项目
$ cordova create hello com.example.hello HelloWorld
2.添加插件
2.1切换到Plugins目录
2.2 添加一下插件
1cordova plugin add cordova-plugin-device 2 3cordova plugin add cordova-plugin-file 4 5cordova plugin add cordova-plugin-file-transfer 6 7cordova plugin add https://github.com/pwlin/cordova-plugin-file-opener2
3.修改插件
3.1需要修改Android项目的插件:
3.1.1修改cordova-plugin-file-transfer 下边的 FileTransfer.java 文件 ,引入import android.os.Environment;
1/** 2 * 获取当前目录在sdcard中的路径 3 * @param rootFolder 根目录 4 * @param aFolder 当前目录 5 */ 6 public String getStorageDirectory(String rootFolder,String aFolder){ 7 String storagePath= Environment.getExternalStorageDirectory().getPath()+"/"+rootFolder+"/"+aFolder; 8 return storagePath; 9 } 10 11 /** 12 * 创建目录 13 * @param fileDirectory 目录名称 14 */ 15 public File createDirectory(String fileDirectory){ 16 File sdcardFile=new File(fileDirectory); 17 if(!sdcardFile.exists()){ 18 sdcardFile.mkdirs(); 19 } 20 return sdcardFile; 21 } 22 23 /** 24 * Downloads a file form a given URL and saves it to the specified directory. 25 * 26 * @param source URL of the server to receive the file 27 * @param target Full path of the file on the file system 28 */ 29 private void download(final String source, final String target, JSONArray args, CallbackContext callbackContext) throws JSONException { 30 Log.d(LOG_TAG, "download " + source + " to " + target); 31 32 String localPath=this.getStorageDirectory("GaussQGY", "download"); 33 this.createDirectory(localPath); 34 35 final CordovaResourceApi resourceApi = webView.getResourceApi(); 36 37 final boolean trustEveryone = args.optBoolean(2); 38 final String objectId = args.getString(3); 39 final JSONObject headers = args.optJSONObject(4); 40 41 final Uri sourceUri = resourceApi.remapUri(Uri.parse(source)); 42 final String targetPath = localPath +'/'+ target; 43 Log.e(LOG_TAG, "文件存放路径: " + targetPath); 44 // Accept a path or a URI for the source. 45 Uri tmpTarget = Uri.parse(targetPath); 46 final Uri targetUri = resourceApi.remapUri( 47 tmpTarget.getScheme() != null ? tmpTarget : Uri.fromFile(new File(targetPath))); 48 49 int uriType = CordovaResourceApi.getUriType(sourceUri); 50 final boolean useHttps = uriType == CordovaResourceApi.URI_TYPE_HTTPS; 51 final boolean isLocalTransfer = !useHttps && uriType != CordovaResourceApi.URI_TYPE_HTTP; 52 if (uriType == CordovaResourceApi.URI_TYPE_UNKNOWN) { 53 JSONObject error = createFileTransferError(INVALID_URL_ERR, source, targetPath, null, 0, null); 54 Log.e(LOG_TAG, "Unsupported URI: " + sourceUri); 55 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error)); 56 return; 57 } 58 59 /* This code exists for compatibility between 3.x and 4.x versions of Cordova. 60 * Previously the CordovaWebView class had a method, getWhitelist, which would 61 * return a Whitelist object. Since the fixed whitelist is removed in Cordova 4.x, 62 * the correct call now is to shouldAllowRequest from the plugin manager. 63 */ 64 Boolean shouldAllowRequest = null; 65 if (isLocalTransfer) { 66 shouldAllowRequest = true; 67 } 68 if (shouldAllowRequest == null) { 69 try { 70 Method gwl = webView.getClass().getMethod("getWhitelist"); 71 Whitelist whitelist = (Whitelist)gwl.invoke(webView); 72 shouldAllowRequest = whitelist.isUrlWhiteListed(source); 73 } catch (NoSuchMethodException e) { 74 } catch (IllegalAccessException e) { 75 } catch (InvocationTargetException e) { 76 } 77 } 78 if (shouldAllowRequest == null) { 79 try { 80 Method gpm = webView.getClass().getMethod("getPluginManager"); 81 PluginManager pm = (PluginManager)gpm.invoke(webView); 82 Method san = pm.getClass().getMethod("shouldAllowRequest", String.class); 83 shouldAllowRequest = (Boolean)san.invoke(pm, source); 84 } catch (NoSuchMethodException e) { 85 } catch (IllegalAccessException e) { 86 } catch (InvocationTargetException e) { 87 } 88 } 89 90 if (!Boolean.TRUE.equals(shouldAllowRequest)) { 91 Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'"); 92 JSONObject error = createFileTransferError(CONNECTION_ERR, source, targetPath, null, 401, null); 93 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error)); 94 return; 95 } 96 97 98 final RequestContext context = new RequestContext(source, targetPath, callbackContext); 99 synchronized (activeRequests) { 100 activeRequests.put(objectId, context); 101 } 102 103 cordova.getThreadPool().execute(new Runnable() { 104 public void run() { 105 if (context.aborted) { 106 return; 107 } 108 HttpURLConnection connection = null; 109 HostnameVerifier oldHostnameVerifier = null; 110 SSLSocketFactory oldSocketFactory = null; 111 File file = null; 112 PluginResult result = null; 113 TrackingInputStream inputStream = null; 114 boolean cached = false; 115 116 OutputStream outputStream = null; 117 try { 118 OpenForReadResult readResult = null; 119 120 file = resourceApi.mapUriToFile(targetUri); 121 context.targetFile = file; 122 123 Log.d(LOG_TAG, "Download file:" + sourceUri); 124 125 FileProgressResult progress = new FileProgressResult(); 126 127 if (isLocalTransfer) { 128 readResult = resourceApi.openForRead(sourceUri); 129 if (readResult.length != -1) { 130 progress.setLengthComputable(true); 131 progress.setTotal(readResult.length); 132 } 133 inputStream = new SimpleTrackingInputStream(readResult.inputStream); 134 } else { 135 // connect to server 136 // Open a HTTP connection to the URL based on protocol 137 connection = resourceApi.createHttpConnection(sourceUri); 138 if (useHttps && trustEveryone) { 139 // Setup the HTTPS connection class to trust everyone 140 HttpsURLConnection https = (HttpsURLConnection)connection; 141 oldSocketFactory = trustAllHosts(https); 142 // Save the current hostnameVerifier 143 oldHostnameVerifier = https.getHostnameVerifier(); 144 // Setup the connection not to verify hostnames 145 https.setHostnameVerifier(DO_NOT_VERIFY); 146 } 147 148 connection.setRequestMethod("GET"); 149 150 // TODO: Make OkHttp use this CookieManager by default. 151 String cookie = getCookies(sourceUri.toString()); 152 153 if(cookie != null) 154 { 155 connection.setRequestProperty("cookie", cookie); 156 } 157 158 // This must be explicitly set for gzip progress tracking to work. 159 connection.setRequestProperty("Accept-Encoding", "gzip"); 160 161 // Handle the other headers 162 if (headers != null) { 163 addHeadersToRequest(connection, headers); 164 } 165 166 connection.connect(); 167 if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { 168 cached = true; 169 connection.disconnect(); 170 Log.d(LOG_TAG, "Resource not modified: " + source); 171 JSONObject error = createFileTransferError(NOT_MODIFIED_ERR, source, targetPath, connection, null); 172 result = new PluginResult(PluginResult.Status.ERROR, error); 173 } else { 174 if (connection.getContentEncoding() == null || connection.getContentEncoding().equalsIgnoreCase("gzip")) { 175 // Only trust content-length header if we understand 176 // the encoding -- identity or gzip 177 if (connection.getContentLength() != -1) { 178 progress.setLengthComputable(true); 179 progress.setTotal(connection.getContentLength()); 180 } 181 } 182 inputStream = getInputStream(connection); 183 } 184 } 185 186 if (!cached) { 187 try { 188 synchronized (context) { 189 if (context.aborted) { 190 return; 191 } 192 context.connection = connection; 193 } 194 195 // write bytes to file 196 byte[] buffer = new byte[MAX_BUFFER_SIZE]; 197 int bytesRead = 0; 198 outputStream = resourceApi.openOutputStream(targetUri); 199 while ((bytesRead = inputStream.read(buffer)) > 0) { 200 outputStream.write(buffer, 0, bytesRead); 201 // Send a progress event. 202 progress.setLoaded(inputStream.getTotalRawBytesRead()); 203 PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject()); 204 progressResult.setKeepCallback(true); 205 context.sendPluginResult(progressResult); 206 } 207 } finally { 208 synchronized (context) { 209 context.connection = null; 210 } 211 safeClose(inputStream); 212 safeClose(outputStream); 213 } 214 215 Log.d(LOG_TAG, "Saved file: " + targetPath); 216 217 218 // create FileEntry object 219 Class webViewClass = webView.getClass(); 220 PluginManager pm = null; 221 try { 222 Method gpm = webViewClass.getMethod("getPluginManager"); 223 pm = (PluginManager) gpm.invoke(webView); 224 } catch (NoSuchMethodException e) { 225 } catch (IllegalAccessException e) { 226 } catch (InvocationTargetException e) { 227 } 228 if (pm == null) { 229 try { 230 Field pmf = webViewClass.getField("pluginManager"); 231 pm = (PluginManager)pmf.get(webView); 232 } catch (NoSuchFieldException e) { 233 } catch (IllegalAccessException e) { 234 } 235 } 236 file = resourceApi.mapUriToFile(targetUri); 237 context.targetFile = file; 238 FileUtils filePlugin = (FileUtils) pm.getPlugin("File"); 239 if (filePlugin != null) { 240 JSONObject fileEntry = filePlugin.getEntryForFile(file); 241 if (fileEntry != null) { 242 result = new PluginResult(PluginResult.Status.OK, fileEntry); 243 } else { 244 JSONObject error = createFileTransferError(CONNECTION_ERR, source, targetPath, connection, null); 245 Log.e(LOG_TAG, "File plugin cannot represent download path"); 246 result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); 247 } 248 } else { 249 Log.e(LOG_TAG, "File plugin not found; cannot save downloaded file"); 250 result = new PluginResult(PluginResult.Status.ERROR, "File plugin not found; cannot save downloaded file"); 251 } 252 } 253 } catch (FileNotFoundException e) { 254 JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, targetPath, connection, e); 255 Log.e(LOG_TAG, error.toString(), e); 256 result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); 257 } catch (IOException e) { 258 JSONObject error = createFileTransferError(CONNECTION_ERR, source, targetPath, connection, e); 259 Log.e(LOG_TAG, error.toString(), e); 260 result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); 261 } catch (JSONException e) { 262 Log.e(LOG_TAG, e.getMessage(), e); 263 result = new PluginResult(PluginResult.Status.JSON_EXCEPTION); 264 } catch (Throwable e) { 265 JSONObject error = createFileTransferError(CONNECTION_ERR, source, targetPath, connection, e); 266 Log.e(LOG_TAG, error.toString(), e); 267 result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); 268 } finally { 269 synchronized (activeRequests) { 270 activeRequests.remove(objectId); 271 } 272 273 if (connection != null) { 274 // Revert back to the proper verifier and socket factories 275 if (trustEveryone && useHttps) { 276 HttpsURLConnection https = (HttpsURLConnection) connection; 277 https.setHostnameVerifier(oldHostnameVerifier); 278 https.setSSLSocketFactory(oldSocketFactory); 279 } 280 } 281 282 if (result == null) { 283 result = new PluginResult(PluginResult.Status.ERROR, createFileTransferError(CONNECTION_ERR, source, targetPath, connection, null)); 284 } 285 // Remove incomplete download. 286 if (!cached && result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) { 287 file.delete(); 288 } 289 context.sendPluginResult(result); 290 } 291 } 292 }); 293 }
3.1.2 修改Android项目下的 cordova-plugin-file-opener2 找到FileOpener2.java ,然后引入 import android.os.Environment;
修改_open方法
1private void _open(String fileArg, String contentType, CallbackContext callbackContext) throws JSONException { 2 String fileName = ""; 3 String filePath = Environment.getExternalStorageDirectory().getPath() + fileArg; 4 try { 5 CordovaResourceApi resourceApi = webView.getResourceApi(); 6 Uri fileUri = resourceApi.remapUri(Uri.parse(filePath)); 7 fileName = this.stripFileProtocol(fileUri.toString()); 8 } catch (Exception e) { 9 fileName = filePath; 10 } 11 File file = new File(fileName); 12 if (file.exists()) { 13 try { 14 Uri path = Uri.fromFile(file); 15 Intent intent = new Intent(Intent.ACTION_VIEW); 16 intent.setDataAndType(path, contentType); 17 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 18 /* 19 * @see 20 * http://stackoverflow.com/questions/14321376/open-an-activity-from-a-cordovaplugin 21 */ 22 cordova.getActivity().startActivity(intent); 23 //cordova.getActivity().startActivity(Intent.createChooser(intent,"Open File in...")); 24 callbackContext.success(); 25 } catch (android.content.ActivityNotFoundException e) { 26 JSONObject errorObj = new JSONObject(); 27 errorObj.put("status", PluginResult.Status.ERROR.ordinal()); 28 errorObj.put("message", "Activity not found: " + e.getMessage()); 29 callbackContext.error(errorObj); 30 } 31 } else { 32 JSONObject errorObj = new JSONObject(); 33 errorObj.put("status", PluginResult.Status.ERROR.ordinal()); 34 errorObj.put("message", "File not found"); 35 callbackContext.error(errorObj); 36 } 37 }
3.2 需要修改iOS项目中的Cordova 插件 下的 cordova-plugin-file-opener2
3.2.1 修改FileOpener2.h
定义一个openURL 方法
1#import <Cordova/CDV.h> 2 3@interface FileOpener2 : CDVPlugin <UIDocumentInteractionControllerDelegate> { 4 NSString *localFile; 5} 6 7@property(nonatomic, strong) UIDocumentInteractionController *controller; 8 9- (void) open: (CDVInvokedUrlCommand*)command; 10- (void) openURL: (CDVInvokedUrlCommand*)command; 11 12@end
3.2.2 修改FileOpener2.m
实现_FileOpener2.h中定义的openURL 方法_
1#import "FileOpener2.h" 2#import <Cordova/CDV.h> 3 4#import <QuartzCore/QuartzCore.h> 5#import <MobileCoreServices/MobileCoreServices.h> 6 7@implementation FileOpener2 8 9#pragma mask --- 加载其它应用 10- (void)openURL:(CDVInvokedUrlCommand *)command 11{ 12 NSString *path = command.arguments[0]; 13 NSURL *url= [NSURL URLWithString: path]; 14 [[UIApplication sharedApplication] openURL:url]; 15} 16 17#pragma mask --- 打开本地文件 18- (void) open: (CDVInvokedUrlCommand*)command { 19 20 NSString *path = command.arguments[0]; 21 NSString *uti = command.arguments[1]; 22 if (!uti || (NSNull*)uti == [NSNull null]) { 23 NSArray *dotParts = [path componentsSeparatedByString:@"."]; 24 NSString *fileExt = [dotParts lastObject]; 25 26 uti = (__bridge NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExt, NULL); 27 } 28 29 CDVViewController* cont = (CDVViewController*)[ super viewController ]; 30 31 dispatch_async(dispatch_get_main_queue(), ^{ 32 // TODO: test if this is a URI or a path 33 NSURL *fileURL = [NSURL URLWithString:path]; 34 35 localFile = fileURL.path; 36 37 NSLog(@"looking for file at %@", fileURL); 38 NSFileManager *fm = [NSFileManager defaultManager]; 39 if(![fm fileExistsAtPath:localFile]) { 40 NSDictionary *jsonObj = @{@"status" : @"9", 41 @"message" : @"File does not exist"}; 42 CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR 43 messageAsDictionary:jsonObj]; 44 [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 45 return; 46 } 47 48 self.controller = [UIDocumentInteractionController interactionControllerWithURL:fileURL]; 49 self.controller.delegate = self; 50 self.controller.UTI = uti; 51 52 CGRect rect = CGRectMake(0, 0, 1000.0f, 150.0f); 53 CDVPluginResult* pluginResult = nil; 54 BOOL wasOpened = [self.controller presentOptionsMenuFromRect:rect inView:cont.view animated:NO]; 55 56 if(wasOpened) { 57 pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: @""]; 58 } else { 59 NSDictionary *jsonObj = @{@"status" : @"9", 60 @"message" : @"Could not handle UTI"}; 61 pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR 62 messageAsDictionary:jsonObj]; 63 } 64 [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 65 }); 66} 67 68@end