11package com .ionicframework .common ;
22
3- import android .app .Dialog ;
43import android .content .Context ;
54import android .content .SharedPreferences ;
6- import android .graphics . Color ;
5+ import android .content . res . AssetManager ;
76import android .net .Uri ;
8- import android .view .animation .AlphaAnimation ;
9- import android .view .animation .Animation ;
10- import android .view .animation .DecelerateInterpolator ;
11- import android .view .Display ;
12- import android .view .WindowManager ;
13- import android .widget .ImageView ;
14- import android .widget .LinearLayout ;
15- import android .widget .LinearLayout .LayoutParams ;
167
8+ import org .apache .commons .io .FileUtils ;
179import org .apache .cordova .CordovaWebView ;
1810import org .apache .cordova .CallbackContext ;
1911import org .apache .cordova .CordovaPlugin ;
2315import org .json .JSONObject ;
2416import org .json .JSONException ;
2517
18+ import android .os .Environment ;
2619import android .util .Log ;
2720import android .app .Activity ;
2821import android .content .pm .PackageInfo ;
2922import android .os .Build ;
3023
24+ import java .io .DataInputStream ;
3125import java .io .File ;
26+ import java .io .FileOutputStream ;
27+ import java .io .IOException ;
28+ import java .io .InputStream ;
29+ import java .io .OutputStream ;
30+ import java .net .URL ;
3231import java .util .Iterator ;
3332import java .util .UUID ;
3433
3534public class IonicCordovaCommon extends CordovaPlugin {
3635 public static final String TAG = "IonicCordovaCommon" ;
3736 private static final String PREFS_KEY = "ionicDeploySavedPreferences" ;
3837 private static final String CUSTOM_PREFS_KEY = "ionicDeployCustomPreferences" ;
38+ private AssetManager assetManager ;
39+
3940
4041 private SharedPreferences prefs ;
4142 private String uuid ;
4243
44+ private interface FileOp {
45+ void run (final JSONArray args , final CallbackContext callbackContext ) throws Exception ;
46+ }
47+
4348 /**
4449 * Sets the context of the Command. This can then be used to do things like
4550 * get file paths associated with the Activity.
@@ -53,11 +58,23 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
5358 // Initialize shared preferences
5459 Context cxt = this .cordova .getActivity ().getApplicationContext ();
5560 this .prefs = cxt .getSharedPreferences ("com.ionic.common.preferences" , Context .MODE_PRIVATE );
61+ assetManager = cordova .getContext ().getAssets ();
5662
5763 // Get or generate a plugin UUID
5864 this .uuid = this .prefs .getString ("uuid" , UUID .randomUUID ().toString ());
5965 prefs .edit ().putString ("uuid" , this .uuid ).apply ();
66+ }
6067
68+ private void threadhelper (final FileOp f , final JSONArray args , final CallbackContext callbackContext ){
69+ cordova .getThreadPool ().execute (new Runnable () {
70+ public void run () {
71+ try {
72+ f .run (args , callbackContext );
73+ } catch ( Exception e ) {
74+ callbackContext .error (e .getMessage ());
75+ }
76+ }
77+ });
6178 }
6279
6380 /**
@@ -77,13 +94,202 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
7794 this .setPreferences (callbackContext , args .getJSONObject (0 ));
7895 } else if (action .equals ("configure" )){
7996 this .configure (callbackContext , args .getJSONObject (0 ));
97+ } else if (action .equals ("copyTo" )){
98+ this .copyTo (callbackContext , args .getJSONObject (0 ));
99+ } else if (action .equals ("remove" )){
100+ this .remove (callbackContext , args .getJSONObject (0 ));
101+ } else if (action .equals ("downloadFile" )){
102+ threadhelper ( new FileOp ( ){
103+ public void run (final JSONArray passedArgs , final CallbackContext cbcontext ) throws JSONException {
104+ downloadFile (cbcontext , passedArgs .getJSONObject (0 ));
105+ }
106+ }, args , callbackContext );
107+
80108 } else {
81109 return false ;
82110 }
83111
84112 return true ;
85113 }
86114
115+ private File getDirectory (String directory ) {
116+ Context c = cordova .getContext ();
117+ switch (directory ) {
118+ case "DOCUMENTS" :
119+ return Environment .getExternalStoragePublicDirectory (Environment .DIRECTORY_DOCUMENTS );
120+ case "DATA" :
121+ return c .getFilesDir ();
122+ case "CACHE" :
123+ return c .getCacheDir ();
124+ case "EXTERNAL" :
125+ return c .getExternalFilesDir (null );
126+ case "EXTERNAL_STORAGE" :
127+ return Environment .getExternalStorageDirectory ();
128+ }
129+ return null ;
130+ }
131+
132+ private void copyAssets (String assetPath , String targetDir ) throws IOException {
133+ String [] files = null ;
134+ try {
135+ files = assetManager .list (assetPath );
136+ } catch (IOException e ) {
137+ Log .e ("tag" , "Failed to get asset file list." , e );
138+ }
139+ if (files != null ) for (String filename : files ) {
140+ InputStream in = null ;
141+ OutputStream out = null ;
142+ try {
143+ if (assetManager .list (assetPath + "/" + filename ).length > 0 ) {
144+ File newDir = new File (targetDir , filename );
145+ newDir .mkdir ();
146+ copyAssets (assetPath + "/" + filename , newDir .getPath ());
147+ continue ;
148+ }
149+ in = assetManager .open (assetPath + "/" + filename );
150+ File destDir = new File (targetDir );
151+ if (!destDir .exists ()) {
152+ destDir .mkdirs ();
153+ }
154+ File outFile = new File (targetDir , filename );
155+ out = new FileOutputStream (outFile );
156+ copyFile (in , out );
157+ } catch (IOException e ) {
158+ Log .e ("tag" , "Failed to copy asset file: " + filename , e );
159+ }
160+ finally {
161+ if (in != null ) {
162+ try {
163+ in .close ();
164+ } catch (IOException e ) {
165+ // NOOP
166+ }
167+ }
168+ if (out != null ) {
169+ try {
170+ out .close ();
171+ } catch (IOException e ) {
172+ // NOOP
173+ }
174+ }
175+ }
176+ }
177+ }
178+
179+ private void copyFile (InputStream in , OutputStream out ) throws IOException {
180+ byte [] buffer = new byte [1024 ];
181+ int read ;
182+ while ((read = in .read (buffer )) != -1 ){
183+ out .write (buffer , 0 , read );
184+ }
185+ }
186+
187+ /**
188+ * copy a directory or file to another location
189+ *
190+ */
191+ public void copyTo (CallbackContext callbackContext , JSONObject options ) throws JSONException {
192+ Log .d (TAG , "copyTo called with " + options .toString ());
193+ PluginResult result ;
194+
195+ try {
196+ JSONObject source = options .getJSONObject ("source" );
197+ String target = options .getString ("target" );
198+
199+ if (source .getString ("directory" ).equals ("APPLICATION" )) {
200+ this .copyAssets (source .getString ("path" ), target );
201+ } else {
202+ File srcDir = this .getDirectory (source .getString ("directory" ));
203+ File srcFile = new File (srcDir .getPath () + "/" + source .getString ("path" ));
204+
205+ if (!srcFile .exists ()) {
206+ result = new PluginResult (PluginResult .Status .ERROR , "source file or directory does not exist" );
207+ result .setKeepCallback (false );
208+ callbackContext .sendPluginResult (result );
209+ return ;
210+ }
211+
212+ if (srcFile .isDirectory ()) {
213+ FileUtils .copyDirectory (srcFile , new File (target ));
214+ } else {
215+ FileUtils .copyFile (srcFile , new File (target ));
216+ }
217+ }
218+ } catch (Exception e ) {
219+ result = new PluginResult (PluginResult .Status .ERROR , e .getMessage ());
220+ result .setKeepCallback (false );
221+ callbackContext .sendPluginResult (result );
222+ return ;
223+ }
224+
225+ result = new PluginResult (PluginResult .Status .OK );
226+ result .setKeepCallback (false );
227+ callbackContext .sendPluginResult (result );
228+ }
229+
230+ /**
231+ * recursively remove a directory or a file
232+ *
233+ */
234+ public void remove (CallbackContext callbackContext , JSONObject options ) throws JSONException {
235+ Log .d (TAG , "recursiveRemove called with " + options .toString ());
236+ String target = options .getString ("target" );
237+ File dest = new File (target );
238+ final PluginResult result ;
239+
240+ if (!dest .exists ()) {
241+ result = new PluginResult (PluginResult .Status .ERROR , "file or directory does not exist" );
242+ result .setKeepCallback (false );
243+ callbackContext .sendPluginResult (result );
244+ return ;
245+ }
246+
247+ try {
248+ FileUtils .forceDelete (dest );
249+ } catch (IOException e ) {
250+ result = new PluginResult (PluginResult .Status .ERROR , e .getMessage ());
251+ result .setKeepCallback (false );
252+ callbackContext .sendPluginResult (result );
253+ return ;
254+ }
255+
256+ result = new PluginResult (PluginResult .Status .OK );
257+ result .setKeepCallback (false );
258+ callbackContext .sendPluginResult (result );
259+ }
260+
261+ public void downloadFile (CallbackContext callbackContext , JSONObject options ) throws JSONException {
262+ Log .d (TAG , "downloadFile called with " + options .toString ());
263+ String url = options .getString ("url" );
264+ String dest = options .getString ("target" );
265+ final PluginResult result ;
266+
267+ try {
268+ URL u = new URL (url );
269+ InputStream is = u .openStream ();
270+
271+ DataInputStream dis = new DataInputStream (is );
272+
273+ byte [] buffer = new byte [1024 ];
274+ int length ;
275+
276+ FileOutputStream fos = new FileOutputStream (new File (dest ));
277+ while ((length = dis .read (buffer ))>0 ) {
278+ fos .write (buffer , 0 , length );
279+ }
280+
281+ } catch (Exception e ) {
282+ Log .e (TAG , "downloadFile error" , e );
283+ result = new PluginResult (PluginResult .Status .ERROR , e .getMessage ());
284+ result .setKeepCallback (false );
285+ callbackContext .sendPluginResult (result );
286+ return ;
287+ }
288+ result = new PluginResult (PluginResult .Status .OK );
289+ result .setKeepCallback (false );
290+ callbackContext .sendPluginResult (result );
291+ }
292+
87293 /**
88294 * Get basic app information. Used for the Ionic monitoring service.
89295 *
@@ -289,4 +495,3 @@ private static String toDirUrl(File f) {
289495 }
290496
291497}
292-
0 commit comments