trigger plugin installation on *.user.js file intent

This commit is contained in:
Philipp Schaefer 2014-02-12 23:01:02 +01:00
parent 2054b5f790
commit b9499e2d1b
5 changed files with 149 additions and 45 deletions

View File

@ -72,6 +72,45 @@
<data android:scheme="geo"/> <data android:scheme="geo"/>
</intent-filter> </intent-filter>
<!-- Handles external user plugins -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="application/x-javascript" />
<data android:mimeType="text/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="*"
android:scheme="file"
android:pathPattern=".*\\.user.js"/>
<data
android:host="*"
android:scheme="content"
android:pathPattern=".*\\.user.js"/>
<data
android:host="*"
android:scheme="http"
android:pathPattern=".*\\.user.js"/>
<data
android:host="*"
android:scheme="https"
android:pathPattern=".*\\.user.js"/>
</intent-filter>
<!-- Points to searchable meta data. --> <!-- Points to searchable meta data. -->
<meta-data <meta-data
android:name="android.app.searchable" android:name="android.app.searchable"

View File

@ -177,4 +177,9 @@
<string name="label_base_layer">Base Layer</string> <string name="label_base_layer">Base Layer</string>
<string name="label_overlay_layers">Overlay Layers</string> <string name="label_overlay_layers">Overlay Layers</string>
<string name="install_dialog_top">Install external plugin?</string>
<string name="install_dialog_msg">
IITCm was requested to install the following plugin:\n\n%1$s\n\nDo you want to proceed?
</string>
</resources> </resources>

View File

@ -1,7 +1,9 @@
package com.cradle.iitc_mobile; package com.cradle.iitc_mobile;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.AssetManager; import android.content.res.AssetManager;
@ -22,11 +24,14 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PipedInputStream; import java.io.PipedInputStream;
import java.io.PipedOutputStream; import java.io.PipedOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.HashMap; import java.util.HashMap;
@ -118,15 +123,17 @@ public class IITC_FileManager {
} }
private final AssetManager mAssetManager; private final AssetManager mAssetManager;
private final IITC_Mobile mIitc; private final Activity mActivity;
private final String mIitcPath; private final String mIitcPath;
private final SharedPreferences mPrefs; private final SharedPreferences mPrefs;
public static final String PLUGINS_PATH = Environment.getExternalStorageDirectory().getPath()
+ "/IITC_Mobile/plugins/";
public IITC_FileManager(final IITC_Mobile iitc) { public IITC_FileManager(final Activity activity) {
mIitc = iitc; mActivity = activity;
mIitcPath = Environment.getExternalStorageDirectory().getPath() + "/IITC_Mobile/"; mIitcPath = Environment.getExternalStorageDirectory().getPath() + "/Activity/";
mPrefs = PreferenceManager.getDefaultSharedPreferences(iitc); mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
mAssetManager = mIitc.getAssets(); mAssetManager = mActivity.getAssets();
} }
private InputStream getAssetFile(final String filename) throws IOException { private InputStream getAssetFile(final String filename) throws IOException {
@ -135,10 +142,10 @@ public class IITC_FileManager {
try { try {
return new FileInputStream(file); return new FileInputStream(file);
} catch (final FileNotFoundException e) { } catch (final FileNotFoundException e) {
mIitc.runOnUiThread(new Runnable() { mActivity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(mIitc, "File " + mIitcPath + Toast.makeText(mActivity, "File " + mIitcPath +
"dev/" + filename + " not found. " + "dev/" + filename + " not found. " +
"Disable developer mode or add iitc files to the dev folder.", "Disable developer mode or add iitc files to the dev folder.",
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
@ -233,6 +240,73 @@ public class IITC_FileManager {
return EMPTY; return EMPTY;
} }
public void installPlugin(final String uri, final boolean invalidateHeaders) {
if (uri != null) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mActivity);
// set title
alertDialogBuilder.setTitle(mActivity.getString(R.string.install_dialog_top));
// set dialog message
String text = mActivity.getString(R.string.install_dialog_msg);
text = String.format(text, uri);
alertDialogBuilder
.setMessage(text)
.setCancelable(true)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
copyPlugin(uri, invalidateHeaders);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
}
private void copyPlugin(final String uri, final boolean invalidateHeaders) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
final URL url = new URL(uri);
final URLConnection conn = url.openConnection();
final String fileName = uri.substring( uri.lastIndexOf('/')+1, uri.length() );
final InputStream is = conn.getInputStream();
// create IITCm external plugins directory if it doesn't already exist
final File pluginsDirectory = new File(PLUGINS_PATH);
pluginsDirectory.mkdirs();
// create in and out streams and copy plugin
File outFile = new File(pluginsDirectory + "/" + fileName);
OutputStream os = new FileOutputStream(outFile);
IITC_FileManager.copyStream(is, os, true);
} catch (IOException e) {
Log.w(e);
}
}
});
thread.start();
if (invalidateHeaders) {
try {
thread.join();
((IITC_PluginPreferenceActivity) mActivity).invalidateHeaders();
} catch (InterruptedException e) {
Log.w(e);
}
}
}
private class FileRequest extends WebResourceResponse implements ResponseHandler, Runnable { private class FileRequest extends WebResourceResponse implements ResponseHandler, Runnable {
private Intent mData; private Intent mData;
private final String mFunctionName; private final String mFunctionName;
@ -258,16 +332,18 @@ public class IITC_FileManager {
target.addCategory(Intent.CATEGORY_OPENABLE); target.addCategory(Intent.CATEGORY_OPENABLE);
try { try {
mIitc.startActivityForResult(Intent.createChooser(target, "Choose file"), this); final IITC_Mobile iitc = (IITC_Mobile) mActivity;
iitc.startActivityForResult(Intent.createChooser(target, "Choose file"), this);
} catch (final ActivityNotFoundException e) { } catch (final ActivityNotFoundException e) {
Toast.makeText(mIitc, "No activity to select a file found." + Toast.makeText(mActivity, "No activity to select a file found." +
"Please install a file browser of your choice!", Toast.LENGTH_LONG).show(); "Please install a file browser of your choice!", Toast.LENGTH_LONG).show();
} }
} }
@Override @Override
public void onActivityResult(final int resultCode, final Intent data) { public void onActivityResult(final int resultCode, final Intent data) {
mIitc.deleteResponseHandler(this); // to enable garbage collection final IITC_Mobile iitc = (IITC_Mobile) mActivity;
iitc.deleteResponseHandler(this); // to enable garbage collection
mResultCode = resultCode; mResultCode = resultCode;
mData = data; mData = data;

View File

@ -228,6 +228,13 @@ public class IITC_Mobile extends Activity
.show(); .show();
} }
} }
if (uri.getPath().endsWith(".user.js")) {
final Intent prefIntent = new Intent(this, IITC_PluginPreferenceActivity.class);
prefIntent.putExtra("url", uri.toString());
startActivity(prefIntent);
// TODO receive intent, start dialog if user want to install $plugin, reload IITC
}
} }
if (Intent.ACTION_SEARCH.equals(action)) { if (Intent.ACTION_SEARCH.equals(action)) {

View File

@ -5,7 +5,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -23,10 +22,8 @@ import com.cradle.iitc_mobile.fragments.PluginsFragment;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -47,6 +44,8 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
new TreeMap<String, ArrayList<IITC_PluginPreference>>(); new TreeMap<String, ArrayList<IITC_PluginPreference>>();
private static int mDeletedPlugins = 0; private static int mDeletedPlugins = 0;
private IITC_FileManager mFileManager;
@Override @Override
public void setListAdapter(final ListAdapter adapter) { public void setListAdapter(final ListAdapter adapter) {
if (adapter == null) { if (adapter == null) {
@ -86,6 +85,13 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
getIntent() getIntent()
.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PluginsFragment.class.getName()); .putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PluginsFragment.class.getName());
} }
mFileManager = new IITC_FileManager(this);
final String uri = getIntent().getStringExtra("url");
if (uri != null) {
mFileManager.installPlugin(uri, true);
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@ -147,7 +153,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
case COPY_PLUGIN_REQUEST: case COPY_PLUGIN_REQUEST:
if (data != null && data.getData() != null) { if (data != null && data.getData() != null) {
String filePath = data.getData().getPath(); String filePath = data.getData().getPath();
copyPlugin(filePath); mFileManager.installPlugin("file://" + filePath, true);
return; return;
} }
break; break;
@ -158,28 +164,6 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
} }
} }
private void copyPlugin(String pluginPath) {
try {
File inFile = new File(pluginPath);
// create IITCm external plugins directory if it doesn't already exist
File pluginsDirectory = getUserPluginsDirectory();
pluginsDirectory.mkdirs();
// create in and out streams and copy plugin
File outFile = new File(pluginsDirectory.getPath() + "/" + inFile.getName());
InputStream is = new FileInputStream(inFile);
OutputStream os = new FileOutputStream(outFile);
IITC_FileManager.copyStream(is, os, true);
// invalidate headers to build a fresh preference screen with the new plugin listed
invalidateHeaders();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override @Override
protected boolean isValidFragment(final String s) { protected boolean isValidFragment(final String s) {
return true; return true;
@ -206,15 +190,8 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity {
return asset_array; return asset_array;
} }
private File getUserPluginsDirectory() {
final String iitc_path = Environment.getExternalStorageDirectory().getPath()
+ "/IITC_Mobile/";
final File directory = new File(iitc_path + "plugins/");
return directory;
}
private File[] getUserPlugins() { private File[] getUserPlugins() {
final File directory = getUserPluginsDirectory(); final File directory = new File(IITC_FileManager.PLUGINS_PATH);
File[] files = directory.listFiles(); File[] files = directory.listFiles();
if (files == null) { if (files == null) {
files = new File[0]; files = new File[0];