AI2 Component  (Version nb184)
AssetFetcher.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright 2018-2020 MIT, All rights reserved
3 // Released under the Apache License, Version 2.0
4 // http://www.apache.org/licenses/LICENSE-2.0
5 
6 package com.google.appinventor.components.runtime.util;
7 
8 import android.util.Log;
9 
12 
13 import java.io.BufferedInputStream;
14 import java.io.BufferedOutputStream;
15 import java.io.File;
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 
19 import java.net.HttpURLConnection;
20 import java.net.URL;
21 
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.concurrent.ExecutorService;
25 import java.util.concurrent.Executors;
26 
27 import org.json.JSONArray;
28 import org.json.JSONException;
29 
30 
50 public class AssetFetcher {
51 
52  private static final String LOG_TAG = AssetFetcher.class.getSimpleName();
53 
54  // We use a single threaded executor so we only load one asset at a time!
55  private static ExecutorService background = Executors.newSingleThreadExecutor();
56 
57  private static volatile boolean inError = false; // true means we are displaying the "End Application" Error dialog already
58  private static final Object semaphore = new Object();
59 
60  /* We are only used statically */
61  private AssetFetcher() {
62  }
63 
64  public static void fetchAssets(final String cookieValue,
65  final String projectId, final String uri, final String asset) {
66  background.submit(new Runnable() {
67  @Override
68  public void run() {
69  String fileName = uri + "/ode/download/file/" + projectId + "/" + asset;
70  if (getFile(fileName, cookieValue, asset, 0) != null) {
72  }
73  }
74  });
75  }
76 
77  public static void upgradeCompanion(final String cookieValue, final String inputUri) {
78  // The code below is commented out because of issues with the Google Play Store
79  //
80  // background.submit(new Runnable() {
81  // @Override
82  // public void run() {
83  // String [] parts = inputUri.split("/", 0);
84  // String asset = parts[parts.length-1];
85  // File assetFile = getFile(inputUri, cookieValue, asset, 0);
86  // if (assetFile != null) {
87  // try {
88  // Form form = Form.getActiveForm();
89  // Intent intent = new Intent(Intent.ACTION_VIEW);
90  // Uri packageuri = NougatUtil.getPackageUri(form, assetFile);
91  // intent.setDataAndType(packageuri, "application/vnd.android.package-archive");
92  // intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
93  // form.startActivity(intent);
94  // } catch (Exception e) {
95  // Log.e(LOG_TAG, "ERROR_UNABLE_TO_GET", e);
96  // RetValManager.sendError("Unable to Install new Companion Package.");
97  // }
98  // }
99  // }
100  // });
101  return;
102  }
103 
104  public static void loadExtensions(String jsonString) {
105  Log.d(LOG_TAG, "loadExtensions called jsonString = " + jsonString);
106  try {
107  ReplForm form = (ReplForm) Form.getActiveForm();
108  JSONArray array = new JSONArray(jsonString);
109  List<String> extensionsToLoad = new ArrayList<String>();
110  if (array.length() == 0) { // No extensions
111  Log.d(LOG_TAG, "loadExtensions: No Extensions");
112  RetValManager.extensionsLoaded(); // This kicks things going
113  return;
114  }
115  for (int i = 0; i < array.length(); i++) {
116  String extensionName = array.optString(i);
117  if (extensionName != null) {
118  Log.d(LOG_TAG, "loadExtensions, extensionName = " + extensionName);
119  extensionsToLoad.add(extensionName);
120  } else {
121  Log.e(LOG_TAG, "extensionName was null");
122  return;
123  }
124  }
125  try {
126  form.loadComponents(extensionsToLoad);
128  } catch (Exception e) {
129  Log.e(LOG_TAG, "Error in form.loadComponents", e);
130  }
131  } catch (JSONException e) {
132  Log.e(LOG_TAG, "JSON Exception parsing extension string", e);
133  }
134  }
135 
136  private static File getFile(final String fileName, String cookieValue, String asset, int depth) {
137  Form form = Form.getActiveForm();
138  if (depth > 1) {
139  synchronized (semaphore) { // We are protecting the inError variable
140  if (inError) {
141  return null;
142  } else {
143  inError = true;
144  form.runOnUiThread(new Runnable() {
145  public void run() {
146  RuntimeErrorAlert.alert(Form.getActiveForm(), "Unable to load file: " + fileName,
147  "Error!", "End Application");
148  }
149  });
150  return null;
151  }
152  }
153  }
154  try {
155  boolean error = false;
156  File outFile = null;
157  URL url = new URL(fileName);
158  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
159  if (connection != null) {
160  connection.setRequestMethod("GET");
161  connection.addRequestProperty("Cookie", "AppInventor = " + cookieValue);
162  int responseCode = connection.getResponseCode();
163  Log.d(LOG_TAG, "asset = " + asset + " responseCode = " + responseCode);
164  outFile = new File(QUtil.getReplAssetPath(form), asset.substring("assets/".length()));
165  File parentOutFile = outFile.getParentFile();
166  if (!parentOutFile.exists() && !parentOutFile.mkdirs()) {
167  throw new IOException("Unable to create assets directory " + parentOutFile);
168  }
169  BufferedInputStream in = new BufferedInputStream(connection.getInputStream(), 0x1000);
170  BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outFile), 0x1000);
171  try {
172  while (true) {
173  int b = in.read();
174  if (b == -1) {
175  break;
176  }
177  out.write(b);
178  }
179  out.flush();
180  } catch (IOException e) {
181  Log.e(LOG_TAG, "copying assets", e);
182  error = true;
183  } finally {
184  out.close();
185  }
186  connection.disconnect();
187  } else {
188  error = true; // Connection was null, failed to open?
189  }
190  if (error) { // Try again recursively
191  return getFile(fileName, cookieValue, asset, depth + 1);
192  }
193  return outFile;
194  } catch (Exception e) {
195  Log.e(LOG_TAG, "Exception while fetching " + fileName, e);
196  // Try again recursively
197  return getFile(fileName, cookieValue, asset, depth + 1);
198  }
199  }
200 }
com.google.appinventor.components.runtime.ReplForm
Definition: ReplForm.java:62
com.google.appinventor.components
com.google.appinventor.components.runtime.util.AssetFetcher
Definition: AssetFetcher.java:50
com.google.appinventor.components.runtime.ReplForm.loadComponents
void loadComponents(List< String > extensionNames)
Definition: ReplForm.java:404
com.google.appinventor.components.runtime.util.RetValManager.extensionsLoaded
static void extensionsLoaded()
Definition: RetValManager.java:182
com.google.appinventor.components.runtime.util.AssetFetcher.fetchAssets
static void fetchAssets(final String cookieValue, final String projectId, final String uri, final String asset)
Definition: AssetFetcher.java:64
com.google.appinventor.components.runtime
Copyright 2009-2011 Google, All Rights reserved.
Definition: AccelerometerSensor.java:8
com.google
com
com.google.appinventor.components.runtime.util.AssetFetcher.upgradeCompanion
static void upgradeCompanion(final String cookieValue, final String inputUri)
Definition: AssetFetcher.java:77
com.google.appinventor.components.runtime.util.RetValManager
Definition: RetValManager.java:27
com.google.appinventor.components.runtime.Form.getActiveForm
static Form getActiveForm()
Definition: Form.java:2181
com.google.appinventor.components.runtime.Form
Definition: Form.java:126
com.google.appinventor.components.runtime.util.RetValManager.assetTransferred
static void assetTransferred(String name)
Definition: RetValManager.java:156
com.google.appinventor.components.runtime.util.AssetFetcher.loadExtensions
static void loadExtensions(String jsonString)
Definition: AssetFetcher.java:104
com.google.appinventor