diff options
author | BogDan Vatra <bog_dan_ro@yahoo.com> | 2011-10-02 19:41:32 +0300 |
---|---|---|
committer | BogDan Vatra <bog_dan_ro@yahoo.com> | 2011-10-02 19:41:32 +0300 |
commit | 5853d88303e1d93beb2e93be36ca34384bcd7662 (patch) | |
tree | 61fb46cd9d0df41c7894140a3a20e8e7082d1436 | |
parent | 5d287f53a4f8ab799afcb2901a5a3f44f4ab5e1a (diff) |
Begin java redesign.
- move strings to resources, add Romanian translation.
- rename package domain name from eu.licentia.* to org.kde.*
- handle .jar/.apk files in Ministro.
19 files changed, 483 insertions, 396 deletions
diff --git a/Ministro/AndroidManifest.xml b/Ministro/AndroidManifest.xml index 2effe76..12e6a62 100644 --- a/Ministro/AndroidManifest.xml +++ b/Ministro/AndroidManifest.xml @@ -1,8 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="eu.licentia.necessitas.ministro" - android:versionCode="2" android:versionName="2.0"> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> + android:versionCode="2" android:versionName="2.0" package="org.kde.necessitas.ministro"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MinistroActivity" android:label="@string/app_name" @@ -12,20 +10,20 @@ <category android:name="android.intent.category.VIEW" /> </intent-filter> </activity> - <activity android:name="MinistroConfigActivity" + <activity android:name="org.kde.necessitas.ministro.MinistroConfigActivity" android:label="@string/app_name"> <intent-filter> - <action android:name="eu.licentia.necessitas.ministro.MinistroConfigActivity" /> + <action android:name="org.kde.necessitas.ministro.MinistroConfigActivity" /> <category android:name="android.intent.category.VIEW" /> </intent-filter> </activity> - <service android:name=".MinistroService"> + <service android:name="org.kde.necessitas.ministro.MinistroService"> <intent-filter> - <action android:name="eu.licentia.necessitas.ministro.IMinistro" /> <action android:name="org.kde.necessitas.ministro" /> </intent-filter> </service> </application> <uses-sdk android:minSdkVersion="4" /> -<uses-permission android:name="android.permission.INTERNET"></uses-permission> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> </manifest> diff --git a/Ministro/jni/chmode.c b/Ministro/jni/chmode.c index 9e175fb..ed73182 100644 --- a/Ministro/jni/chmode.c +++ b/Ministro/jni/chmode.c @@ -18,7 +18,7 @@ #include <jni.h> #include <sys/stat.h> -jint Java_eu_licentia_necessitas_ministro_MinistroActivity_nativeChmode(JNIEnv * env, jobject obj, jstring filePath, jint mode) +jint Java_org_kde_necessitas_ministro_MinistroActivity_nativeChmode(JNIEnv * env, jobject obj, jstring filePath, jint mode) { const char *file = (*env)->GetStringUTFChars(env, filePath, 0); int res = chmod(file, mode); diff --git a/Ministro/res/values-ro/strings.xml b/Ministro/res/values-ro/strings.xml new file mode 100644 index 0000000..116cafb --- /dev/null +++ b/Ministro/res/values-ro/strings.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">Ministro</string> + <string name="repositories_prompt">Alegeţi un depozit</string> + <string name="incompatible_ministo_api">Ministro nu este compatibil cu aplicaţia dumneavoastră. Vă rugăm să actualizaţi serviciul Ministro.</string> + <string name="ministro_network_access_msg">Ministro necesită acces la reţea. Activaţi reţeaua mobilă sau Wi-Fi pentru a descărca datele.</string> + <string name="setting_msg">Setări</string> + <string name="wait_for_network_connection_msg">Aştept conexiunea de reţea</string> + <string name="download_app_libs_msg">%1$s are nevoie de biblioteci suplimentare pentru a rula.\nDoriţi să le descărcaţi acum?</string> + <string name="start_downloading_msg">Încep descărcarea ...</string> + <string name="downloading_qt_libraries_msg">Descarc bibliotecile Qt</string> + <string name="checking_libraries_msg">Verific bibliotecile. Vă rugăm aşteptaţi ...</string> + <string name="extracting_SSL_msg">Extrag certificate SSL. Vă rugăm aşteptaţi ...</string> + <string name="new_qt_libs_msg">Au fost găsite biblioteci Qt noi</string> + <string name="new_qt_libs_tap_msg">Au fost găsite biblioteci Qt noi, apăsaţi pentru a le actualiza.</string> + <string name="ministro_repository_msg">Ministro va folosi depozitul %1$s</string> + <string name="ministro_repository_changed_msg">Depozitul Ministro s-a schimbat</string> + <string name="ministro_update_msg">Actualizare Ministro</string> + <string name="ministro_repository_changed_tap_msg">Ministro depozitul sa schimbat, apăsaţi pentru actualizare.</string> +</resources> diff --git a/Ministro/res/values/strings.xml b/Ministro/res/values/strings.xml index 45435cf..7194f1e 100644 --- a/Ministro/res/values/strings.xml +++ b/Ministro/res/values/strings.xml @@ -2,4 +2,19 @@ <resources> <string name="app_name">Ministro</string> <string name="repositories_prompt">Choose a repository</string> + <string name="incompatible_ministo_api">Ministro is not compatible with your application. Please upgrade Ministro service.</string> + <string name="ministro_network_access_msg">Ministro requires network access. Enable mobile network or Wi-Fi to download data.</string> + <string name="setting_msg">Setting</string> + <string name="wait_for_network_connection_msg">Waiting for network connection</string> + <string name="download_app_libs_msg"> %1$s needs extra libraries to run.\nDo you want to download them now?</string> + <string name="start_downloading_msg">Start downloading ...</string> + <string name="downloading_qt_libraries_msg">Downloading Qt libraries</string> + <string name="checking_libraries_msg">Checking libraries. Please wait...</string> + <string name="extracting_SSL_msg">Extracting SSL root certificates. Please wait...</string> + <string name="new_qt_libs_msg">New Qt libs found</string> + <string name="new_qt_libs_tap_msg">New Qt libs has been found tap to update.</string> + <string name="ministro_repository_msg">Ministro will use %1$s repository</string> + <string name="ministro_repository_changed_msg">Ministro repository changed</string> + <string name="ministro_update_msg">Ministro update</string> + <string name="ministro_repository_changed_tap_msg">Ministro repository changed tap to update.</string> </resources> diff --git a/Ministro/src/eu/licentia/necessitas/ministro/IMinistro.aidl b/Ministro/src/eu/licentia/necessitas/ministro/IMinistro.aidl deleted file mode 100644 index ec6a240..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/IMinistro.aidl +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the BogDan Vatra <bog_dan_ro@yahoo.com> nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY BogDan Vatra <bog_dan_ro@yahoo.com> ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package eu.licentia.necessitas.ministro; - -import eu.licentia.necessitas.ministro.IMinistroCallback; - -interface IMinistro -{ - /** - * Check/download required libs to run the application - * - * param callback - interface used by the service to notify the client when it has the libs - * param modules - Qt modules you want to check - * param appName - Application name, used to show more informations to user - * param ministroApiLevel - Ministro api level, used to check ministro service compatibility. - * Current API Level is 1 !!! - * param mecessitasApiLevel - Necessitas api level, used to download the right platform plugin. - * Current API Level is 1 !!! - */ - - void checkModules(in IMinistroCallback callback, in String[] modules, in String appName, in int ministroApiLevel, in int necessitasApiLevel); -} diff --git a/Ministro/src/eu/licentia/necessitas/ministro/IMinistroCallback.aidl b/Ministro/src/eu/licentia/necessitas/ministro/IMinistroCallback.aidl deleted file mode 100644 index a41a210..0000000 --- a/Ministro/src/eu/licentia/necessitas/ministro/IMinistroCallback.aidl +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the BogDan Vatra <bog_dan_ro@yahoo.com> nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY BogDan Vatra <bog_dan_ro@yahoo.com> ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package eu.licentia.necessitas.ministro; - -oneway interface IMinistroCallback { - /** - * This method is called by the Ministro service back into the application which - * implements this interface. - * - * <p>The method allows notifying the application about the result of the library - * lookup. In case the <code>errorCode</code> argument is 0, the called application - * can start without problems.</p> - * - * param in - libs, you have to load before load the application - * param in - evnVars, tab separated environment variables - * param in - params, tab separated paras which should be passed to the application - * param in - errorCode, the error number, the application should check the error code before starts - * - 0 no error - * - 1 no qt libs found - * - xxx - * param in - errorMessage, the error message (where available, translated into phone language). - */ - - void libs(in String[] libs,in String environmentVariables, in String applicationParams, in int errorCode, in String errorMessage); -} diff --git a/Ministro/src/org/kde/necessitas/ministro/IMinistro.aidl b/Ministro/src/org/kde/necessitas/ministro/IMinistro.aidl new file mode 100644 index 0000000..2735e8b --- /dev/null +++ b/Ministro/src/org/kde/necessitas/ministro/IMinistro.aidl @@ -0,0 +1,46 @@ +/* + Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +package org.kde.necessitas.ministro; + +import org.kde.necessitas.ministro.IMinistroCallback; + +interface IMinistro +{ + /** + * Check/download required libs to run the application + * + * param callback - interface used by the service to notify the client when it has the libs + * param modules - Qt modules you want to check + * param appName - Application name, used to show more informations to user + * param ministroApiLevel - Ministro api level, used to check ministro service compatibility. + * Current API Level is 1 !!! + * param qtApiLevel - Necessitas api level, used to download the right platform plugin. + * Current API Level is 4 !!! + */ + + void checkModules(in IMinistroCallback callback, in String[] modules, in String appName, in int ministroApiLevel, in int qtApiLevel); +} diff --git a/Ministro/src/org/kde/necessitas/ministro/IMinistroCallback.aidl b/Ministro/src/org/kde/necessitas/ministro/IMinistroCallback.aidl new file mode 100644 index 0000000..9922aa0 --- /dev/null +++ b/Ministro/src/org/kde/necessitas/ministro/IMinistroCallback.aidl @@ -0,0 +1,51 @@ +/* + Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package org.kde.necessitas.ministro; + +oneway interface IMinistroCallback { +/** +* This method is called by the Ministro service back into the application which +* implements this interface. +* +* param in - loader +* loader fields: +* * Key Name Key type Explanations +* * "error.code" Integer See below +* * "error.message" String Missing if no error, otherwise will contain the error message translated into phone language where available. +* * "dex.path" String The list of jar/apk files containing classes and resources, needed to be passed to application DexClassLoader +* * "lib.path" String The list of directories containing native libraries; may be missing, needed to be passed to application DexClassLoader +* * "loader.class.name" String Loader class name. +* +* "error.code" field possible errors: +* - 0 no error. +* - 1 incompatible Ministro version. Ministro needs to be upgraded. +* - 2 not all modules could be satisfy. +* +* This parameter will contain additional fields which are used by the loader to start your application, so it must be passed to loader. +*/ + + void loaderReady(in Bundle loaderParams); +} diff --git a/Ministro/src/eu/licentia/necessitas/ministro/Library.java b/Ministro/src/org/kde/necessitas/ministro/Library.java index 899b797..211f29b 100644 --- a/Ministro/src/eu/licentia/necessitas/ministro/Library.java +++ b/Ministro/src/org/kde/necessitas/ministro/Library.java @@ -15,7 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package eu.licentia.necessitas.ministro; +package org.kde.necessitas.ministro; import java.io.File; import java.io.FileInputStream; @@ -23,6 +23,8 @@ import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -79,6 +81,8 @@ class Library need.url=lib.getAttribute("url"); need.sha1=lib.getAttribute("sha1"); need.size=Long.valueOf(lib.getAttribute("size")); + if ( lib.hasAttribute("type") ) + need.type=lib.getAttribute("type"); needs.add(need); } } @@ -158,7 +162,8 @@ class Library public static boolean checkCRC(String fileName, String sha1) throws IOException { - try { + try + { byte[] tmp = new byte[2048]; MessageDigest digester = MessageDigest.getInstance("SHA-1"); int downloaded; @@ -198,6 +203,18 @@ class Library for (int i=0;i<files.length;i++) new File(path+files[i]).delete(); } + + public static String join(Collection<String> s, String delimiter) + { + if (s == null || s.isEmpty()) return ""; + Iterator<String> iter = s.iterator(); + StringBuilder builder = new StringBuilder(iter.next()); + while( iter.hasNext() ) + { + builder.append(delimiter).append(iter.next()); + } + return builder.toString(); + } }; class NeedsStruct @@ -205,6 +222,7 @@ class NeedsStruct public String name = null; public String filePath = null; public String sha1 = null; - public String url; + public String url = null; + public String type = null; public long size = 0; };
\ No newline at end of file diff --git a/Ministro/src/eu/licentia/necessitas/ministro/MinistroActivity.java b/Ministro/src/org/kde/necessitas/ministro/MinistroActivity.java index f999274..8956e8a 100644 --- a/Ministro/src/eu/licentia/necessitas/ministro/MinistroActivity.java +++ b/Ministro/src/org/kde/necessitas/ministro/MinistroActivity.java @@ -15,7 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package eu.licentia.necessitas.ministro; +package org.kde.necessitas.ministro; import java.io.File; import java.io.FileInputStream; @@ -32,7 +32,6 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Collections; import java.util.Enumeration; import javax.xml.parsers.DocumentBuilder; @@ -64,7 +63,8 @@ import android.os.Bundle; import android.os.IBinder; import android.provider.Settings; -public class MinistroActivity extends Activity { +public class MinistroActivity extends Activity +{ public native static int nativeChmode(String filepath, int mode); private static final String DOMAIN_NAME="http://files.kde.org/necessitas/ministro/"; @@ -80,25 +80,28 @@ public class MinistroActivity extends Activity { else { AlertDialog.Builder builder = new AlertDialog.Builder(MinistroActivity.this); - builder.setMessage("Ministro requires network access. Enable mobile network or Wi-Fi to download data."); + builder.setMessage(getResources().getString(R.string.ministro_network_access_msg)); builder.setCancelable(true); - builder.setNeutralButton("Setting", new DialogInterface.OnClickListener() { + builder.setNeutralButton(getResources().getString(R.string.setting_msg), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - final ProgressDialog m_dialog = ProgressDialog.show(MinistroActivity.this, null, "Waiting for network connection", true, true, new DialogInterface.OnCancelListener() { + final ProgressDialog m_dialog = ProgressDialog.show(MinistroActivity.this, null, getResources().getString(R.string.wait_for_network_connection_msg), true, true, new DialogInterface.OnCancelListener() { @Override - public void onCancel(DialogInterface dialog) { + public void onCancel(DialogInterface dialog) + { finishMe(); } }); getApplication().registerReceiver(new BroadcastReceiver() { @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(Context context, Intent intent) + { if (isOnline(MinistroActivity.this)) { getApplication().unregisterReceiver(this); runOnUiThread(new Runnable() { @Override - public void run() { + public void run() + { m_dialog.dismiss(); new CheckLibraries().execute(update); } @@ -110,14 +113,16 @@ public class MinistroActivity extends Activity { dialog.dismiss(); } }); - builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) + { dialog.cancel(); } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override - public void onCancel(DialogInterface dialog) { + public void onCancel(DialogInterface dialog) + { finishMe(); } }); @@ -126,24 +131,26 @@ public class MinistroActivity extends Activity { } } - private ServiceConnection m_ministroConnection=new ServiceConnection() { + private ServiceConnection m_ministroConnection=new ServiceConnection() + { @Override - public void onServiceConnected(ComponentName name, IBinder service) { + public void onServiceConnected(ComponentName name, IBinder service) + { if (getIntent().hasExtra("id") && getIntent().hasExtra("modules")) { m_id=getIntent().getExtras().getInt("id"); m_modules=getIntent().getExtras().getStringArray("modules"); AlertDialog.Builder builder = new AlertDialog.Builder(MinistroActivity.this); - builder.setMessage(getIntent().getExtras().getString("name")+ - " needs extra libraries to run.\nDo you want to download them now?") + builder.setMessage(getResources().getString(R.string.download_app_libs_msg, + getIntent().getExtras().getString("name"))) .setCancelable(false) - .setPositiveButton("Yes", new DialogInterface.OnClickListener() { + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); checkNetworkAndDownload(false); } }) - .setNegativeButton("No", new DialogInterface.OnClickListener() { + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); finishMe(); @@ -157,7 +164,8 @@ public class MinistroActivity extends Activity { } @Override - public void onServiceDisconnected(ComponentName name) { + public void onServiceDisconnected(ComponentName name) + { m_ministroConnection = null; } }; @@ -222,9 +230,9 @@ public class MinistroActivity extends Activity { InputStream instream = connection.getInputStream(); byte[] tmp = new byte[2048]; int downloaded; - while ((downloaded = instream.read(tmp)) != -1) { + while ((downloaded = instream.read(tmp)) != -1) outstream.write(tmp, 0, downloaded); - } + outstream.close(); MinistroService.instance().refreshLibraries(false); return version; @@ -242,21 +250,24 @@ public class MinistroActivity extends Activity { return -1; } - private class DownloadManager extends AsyncTask<Library, Integer, Long> { + private class DownloadManager extends AsyncTask<Library, Integer, Long> + { private ProgressDialog m_dialog = null; - private String m_status = "Start downloading ..."; + private String m_status = getResources().getString(R.string.start_downloading_msg); private int m_totalSize=0, m_totalProgressSize=0; @Override - protected void onPreExecute() { + protected void onPreExecute() + { m_dialog = new ProgressDialog(MinistroActivity.this); m_dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - m_dialog.setTitle("Downloading Qt libraries"); + m_dialog.setTitle(getResources().getString(R.string.downloading_qt_libraries_msg)); m_dialog.setMessage(m_status); m_dialog.setCancelable(true); m_dialog.setOnCancelListener(new DialogInterface.OnCancelListener(){ @Override - public void onCancel(DialogInterface dialog) { + public void onCancel(DialogInterface dialog) + { DownloadManager.this.cancel(false); finishMe(); } @@ -280,7 +291,8 @@ public class MinistroActivity extends Activity { int downloaded; byte[] tmp = new byte[2048]; int oldProgress=-1; - while ((downloaded = instream.read(tmp)) != -1) { + while ((downloaded = instream.read(tmp)) != -1) + { if (isCancelled()) break; progressSize+=downloaded; @@ -314,9 +326,12 @@ public class MinistroActivity extends Activity { m_totalProgressSize-=progressSize; return false; } + @Override - protected Long doInBackground(Library... params) { - try { + protected Long doInBackground(Library... params) + { + try + { for (int i=0;i<params.length;i++) { m_totalSize+=params[i].size; @@ -331,7 +346,8 @@ public class MinistroActivity extends Activity { { if (isCancelled()) break; - synchronized (m_status) { + synchronized (m_status) + { m_status=params[i].name+" "; } publishProgress(0, m_totalProgressSize); @@ -349,7 +365,8 @@ public class MinistroActivity extends Activity { if (null != params[i].needs) for (int j=0;j<params[i].needs.length;j++) { - synchronized (m_status) { + synchronized (m_status) + { m_status=params[i].needs[j].name+" "; } publishProgress(0, m_totalProgressSize); @@ -378,8 +395,10 @@ public class MinistroActivity extends Activity { } @Override - protected void onProgressUpdate(Integer... values) { - synchronized (m_status) { + protected void onProgressUpdate(Integer... values) + { + synchronized (m_status) + { m_dialog.setMessage(m_status+values[0]+"%"); m_dialog.setProgress(values[1]); } @@ -387,7 +406,8 @@ public class MinistroActivity extends Activity { } @Override - protected void onPostExecute(Long result) { + protected void onPostExecute(Long result) + { super.onPostExecute(result); if (m_dialog != null) { @@ -398,27 +418,32 @@ public class MinistroActivity extends Activity { } } - private class CheckLibraries extends AsyncTask<Boolean, Void, Double> { - + private class CheckLibraries extends AsyncTask<Boolean, Void, Double> + { private ProgressDialog dialog = null; private ArrayList<Library> newLibs = new ArrayList<Library>(); private String m_message; @Override - protected void onPreExecute() { - runOnUiThread(new Runnable() { + protected void onPreExecute() + { + runOnUiThread(new Runnable() + { @Override - public void run() { + public void run() + { dialog = ProgressDialog.show(MinistroActivity.this, null, - "Checking libraries. Please wait...", true, true); + getResources().getString(R.string.checking_libraries_msg), true, true); } }); super.onPreExecute(); } @Override - protected Double doInBackground(Boolean... update) { + protected Double doInBackground(Boolean... update) + { double version=0.0; - try { + try + { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document dom = null; @@ -439,13 +464,11 @@ public class MinistroActivity extends Activity { } else libraries = MinistroService.instance().getAvailableLibraries(); + ArrayList<String> notFoundModules = new ArrayList<String>(); if (m_modules!=null) - { - ArrayList<String> requiredModules = new ArrayList<String>(); - Collections.addAll(requiredModules, m_modules); - MinistroService.instance().checkModules(requiredModules, notFoundModules); - } + MinistroService.instance().checkModules(m_modules, notFoundModules); + dom = builder.parse(new FileInputStream(MinistroService.instance().getVersionXmlFile())); factory = DocumentBuilderFactory.newInstance(); @@ -459,7 +482,7 @@ public class MinistroActivity extends Activity { !preferences.getString("INCREMENTAL", "").equals(android.os.Build.VERSION.INCREMENTAL) || !preferences.getString("RELEASE", "").equals(android.os.Build.VERSION.RELEASE)) { - m_message = "Extracting SSL root certificates. Please wait..."; + m_message = getResources().getString(R.string.extracting_SSL_msg); publishProgress((Void[])null); String environmentVariables=root.getAttribute("environmentVariables"); environmentVariables=environmentVariables.replaceAll("MINISTRO_PATH", ""); @@ -471,13 +494,16 @@ public class MinistroActivity extends Activity { { String path=Library.mkdirParents(getFilesDir().getAbsolutePath(),environmentVariable[1], 0); Library.removeAllFiles(path); - try { + try + { KeyStore ks= KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStream instream = new FileInputStream(new File("/system/etc/security/cacerts.bks")); ks.load(instream, null); - for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements(); ) { + for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements(); ) + { String aName = aliases.nextElement(); - try{ + try + { X509Certificate cert=(X509Certificate) ks.getCertificate(aName); if (null==cert) continue; @@ -487,13 +513,9 @@ public class MinistroActivity extends Activity { outstream.write(buff, 0, buff.length); outstream.close(); nativeChmode(filePath, 0644); - } - catch(KeyStoreException e) - { + } catch(KeyStoreException e) { e.printStackTrace(); - } - catch(Exception e) - { + } catch(Exception e) { e.printStackTrace(); } } @@ -566,12 +588,15 @@ public class MinistroActivity extends Activity { } @Override - protected void onProgressUpdate(Void... nothing) { + protected void onProgressUpdate(Void... nothing) + { dialog.setMessage(m_message); super.onProgressUpdate(nothing); } + @Override - protected void onPostExecute(Double result) { + protected void onPostExecute(Double result) + { if (null != dialog) { dialog.dismiss(); @@ -590,29 +615,33 @@ public class MinistroActivity extends Activity { } @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) + { super.onCreate(savedInstanceState); setContentView(R.layout.main); m_qtLibsRootPath = getFilesDir().getAbsolutePath()+"/qt/"; File dir=new File(m_qtLibsRootPath); dir.mkdirs(); nativeChmode(m_qtLibsRootPath, 0755); - bindService(new Intent("eu.licentia.necessitas.ministro.IMinistro"), m_ministroConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent("org.kde.necessitas.ministro"), m_ministroConnection, Context.BIND_AUTO_CREATE); } @Override - protected void onDestroy() { + protected void onDestroy() + { super.onDestroy(); unbindService(m_ministroConnection); } @Override - public void onConfigurationChanged(Configuration newConfig) { + public void onConfigurationChanged(Configuration newConfig) + { //Avoid activity from being destroyed/created super.onConfigurationChanged(newConfig); } - static { + static + { System.loadLibrary("chmode"); } } diff --git a/Ministro/src/eu/licentia/necessitas/ministro/MinistroConfigActivity.java b/Ministro/src/org/kde/necessitas/ministro/MinistroConfigActivity.java index 294affc..e7c8156 100644 --- a/Ministro/src/eu/licentia/necessitas/ministro/MinistroConfigActivity.java +++ b/Ministro/src/org/kde/necessitas/ministro/MinistroConfigActivity.java @@ -15,7 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package eu.licentia.necessitas.ministro; +package org.kde.necessitas.ministro; import android.app.Activity; import android.app.Notification; @@ -49,8 +49,9 @@ public class MinistroConfigActivity extends Activity { public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { // TODO Auto-generated method stub - Toast.makeText(parent.getContext(), "Ministro will use " + - parent.getItemAtPosition(pos).toString()+" repository", Toast.LENGTH_LONG).show(); + Toast.makeText(parent.getContext() + , getResources().getString(R.string.ministro_repository_msg + , parent.getItemAtPosition(pos).toString()), Toast.LENGTH_LONG).show(); MinistroService.setRepository(MinistroConfigActivity.this, parent.getItemAtPosition(pos).toString()); } @@ -65,11 +66,11 @@ public class MinistroConfigActivity extends Activity { protected void onDestroy() { NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); int icon = R.drawable.icon; - CharSequence tickerText = "Ministro repository changed"; // ticker-text + CharSequence tickerText = getResources().getString(R.string.ministro_repository_changed_msg); // ticker-text long when = System.currentTimeMillis(); // notification time Context context = getApplicationContext(); // application Context - CharSequence contentTitle = "Ministro update"; // expanded message title - CharSequence contentText = "Ministro repository changed tap to update."; // expanded message text + CharSequence contentTitle = getResources().getString(R.string.ministro_update_msg); // expanded message title + CharSequence contentText = getResources().getString(R.string.ministro_repository_changed_tap_msg); // expanded message text Intent notificationIntent = new Intent(this, MinistroActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); diff --git a/Ministro/src/eu/licentia/necessitas/ministro/MinistroService.java b/Ministro/src/org/kde/necessitas/ministro/MinistroService.java index ed41368..db04050 100644 --- a/Ministro/src/eu/licentia/necessitas/ministro/MinistroService.java +++ b/Ministro/src/org/kde/necessitas/ministro/MinistroService.java @@ -15,13 +15,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package eu.licentia.necessitas.ministro; +package org.kde.necessitas.ministro; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -38,17 +40,37 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.AsyncTask; +import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; -public class MinistroService extends Service { +public class MinistroService extends Service +{ private static final String TAG = "MinistroService"; private static final String MINISTRO_CHECK_UPDATES_KEY="LASTCHECK"; private static final String MINISTRO_REPOSITORY_KEY="REPOSITORY"; private static final String MINISTRO_DEFAULT_REPOSITORY="stable"; + /// loader parameter keys + private static final String ERROR_CODE_KEY="error.code"; + private static final String ERROR_MESSAGE_KEY="error.message"; + private static final String DEX_PATH_KEY="dex.path"; + private static final String LIB_PATH_KEY="lib.path"; + private static final String LOADER_CLASS_NAME_KEY="loader.class.name"; + private static final String NATIVE_LIBRARIES_KEY="native.libraries"; + private static final String ENVIRONMENT_VARIABLES_KEY="environment.variables"; + private static final String APPLICATION_PARAMETERS_KEY="application.parameters"; + /// loader parameter keys + + /// loader error codes + private static final int EC_NO_ERROR=0; + private static final int EC_INCOMPATIBLE=1; + private static final int EC_NOT_FOUND=2; + /// loader error codes + + public static String getRepository(Context c) { SharedPreferences preferences=c.getSharedPreferences("Ministro", MODE_PRIVATE); @@ -72,12 +94,15 @@ public class MinistroService extends Service { private static MinistroService m_instance = null; private String m_environmentVariables = null; private String m_applicationParams = null; - + private String m_loaderClassName = null; + private String m_pathSeparator = null; public static MinistroService instance() { return m_instance; } - public MinistroService() { + + public MinistroService() + { m_instance = this; } @@ -89,7 +114,8 @@ public class MinistroService extends Service { ArrayList<Library> getDownloadedLibraries() { - synchronized (this) { + synchronized (this) + { return m_downloadedLibraries; } } @@ -98,7 +124,8 @@ public class MinistroService extends Service { private ArrayList<Library> m_availableLibraries = new ArrayList<Library>(); ArrayList<Library> getAvailableLibraries() { - synchronized (this) { + synchronized (this) + { return m_availableLibraries; } } @@ -106,17 +133,18 @@ public class MinistroService extends Service { class CheckForUpdates extends AsyncTask<Void, Void, Void> { @Override - protected void onPreExecute() { + protected void onPreExecute() + { if (m_version<MinistroActivity.downloadVersionXmlFile(MinistroService.this, true)) { NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); int icon = R.drawable.icon; - CharSequence tickerText = "New Qt libs found"; // ticker-text - long when = System.currentTimeMillis(); // notification time - Context context = getApplicationContext(); // application Context - CharSequence contentTitle = "Ministro update"; // expanded message title - CharSequence contentText = "New Qt libs has been found tap to update."; // expanded message text + CharSequence tickerText = getResources().getString(R.string.new_qt_libs_msg); // ticker-text + long when = System.currentTimeMillis(); // notification time + Context context = getApplicationContext(); // application Context + CharSequence contentTitle = getResources().getString(R.string.ministro_update_msg); // expanded message title + CharSequence contentText = getResources().getString(R.string.new_qt_libs_tap_msg); // expanded message text Intent notificationIntent = new Intent(MinistroService.this, MinistroActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(MinistroService.this, 0, notificationIntent, 0); @@ -127,10 +155,9 @@ public class MinistroService extends Service { notification.defaults |= Notification.DEFAULT_SOUND; notification.defaults |= Notification.DEFAULT_VIBRATE; notification.defaults |= Notification.DEFAULT_LIGHTS; - try{ + try { nm.notify(1, notification); - }catch(Exception e) - { + } catch(Exception e) { e.printStackTrace(); } } @@ -138,7 +165,6 @@ public class MinistroService extends Service { @Override protected Void doInBackground(Void... params) { - // TODO Auto-generated method stub return null; } } @@ -147,8 +173,10 @@ public class MinistroService extends Service { // this method reload all downloaded libraries synchronized ArrayList<Library> refreshLibraries(boolean checkCrc) { - synchronized (this) { - try { + synchronized (this) + { + try + { m_downloadedLibraries.clear(); m_availableLibraries.clear(); if (! (new File(m_versionXmlFile)).exists()) @@ -158,6 +186,7 @@ public class MinistroService extends Service { Document dom = documentBuilder.parse(new FileInputStream(m_versionXmlFile)); Element root = dom.getDocumentElement(); m_version = Double.valueOf(root.getAttribute("version")); + m_loaderClassName=root.getAttribute("loaderClassName"); m_applicationParams=root.getAttribute("applicationParameters"); m_applicationParams=m_applicationParams.replaceAll("MINISTRO_PATH", getFilesDir().getAbsolutePath()); m_environmentVariables=root.getAttribute("environmentVariables"); @@ -232,9 +261,11 @@ public class MinistroService extends Service { ArrayList<ActionStruct> m_actions = new ArrayList<ActionStruct>(); @Override - public void onCreate() { + public void onCreate() + { m_versionXmlFile = getFilesDir().getAbsolutePath()+"/version.xml"; m_qtLibsRootPath = getFilesDir().getAbsolutePath()+"/qt/"; + m_pathSeparator = System.getProperty("path.separator", ":"); SharedPreferences preferences=getSharedPreferences("Ministro", MODE_PRIVATE); long lastCheck = preferences.getLong(MINISTRO_CHECK_UPDATES_KEY,0); if (MinistroActivity.isOnline(this) && System.currentTimeMillis()-lastCheck>24l*3600*100) // check once/day @@ -251,39 +282,56 @@ public class MinistroService extends Service { } @Override - public void onDestroy() { + public void onDestroy() + { super.onDestroy(); } @Override - public IBinder onBind(Intent intent){ - return new IMinistro.Stub() { + public IBinder onBind(Intent intent) + { + return new IMinistro.Stub() + { @Override - public void checkModules(IMinistroCallback callback, - String[] modules, String appName, int ministroApiLevel, int necessitasApiLevel) throws RemoteException { + public void checkModules(IMinistroCallback callback, String[] modules + , String appName, int ministroApiLevel + , int necessitasApiLevel) throws RemoteException + { checkModulesImpl(callback, modules, appName, ministroApiLevel, necessitasApiLevel); } }; } /** - * Implements the {@link IMinistro.Stub#checkModules(IMinistroCallback, String[], String, int, int)} - * service method. - * - * @param callback - * @param modules - * @param appName - * @param ministroApiLevel - * @param necessitasApiLevel - * @throws RemoteException - */ - final void checkModulesImpl(IMinistroCallback callback, - String[] modules, String appName, int ministroApiLevel, int necessitasApiLevel) throws RemoteException { + * Implements the {@link IMinistro.Stub#checkModules(IMinistroCallback, String[], String, int, int)} + * service method. + * + * @param callback + * @param modules + * @param appName + * @param ministroApiLevel + * @param necessitasApiLevel + * @throws RemoteException + */ + final void checkModulesImpl(IMinistroCallback callback, String[] modules + , String appName, int ministroApiLevel + , int qtApiLevel) throws RemoteException + { if (ministroApiLevel<MINISTRO_MIN_API_LEVEL || ministroApiLevel>MINISTRO_MAX_API_LEVEL) { // panic !!! Ministro service is not compatible, user should upgrade Ministro package - Log.w(TAG, "Ministro cannot satisfy API version: " + ministroApiLevel); + Bundle loaderParams = new Bundle(); + loaderParams.putInt(ERROR_CODE_KEY, EC_INCOMPATIBLE); + loaderParams.putString(ERROR_MESSAGE_KEY, getResources().getString(R.string.incompatible_ministo_api)); + try + { + callback.loaderReady(loaderParams); + } + catch (Exception e) { + e.printStackTrace(); + } + Log.w(TAG, "Ministro cannot satisfy API version: " + ministroApiLevel); return; } @@ -292,36 +340,37 @@ public class MinistroService extends Service { // this method is called by the activity client who needs modules. ArrayList<String> notFoundModules = new ArrayList<String>(); - ArrayList<String> libraries = new ArrayList<String>(); - Collections.addAll(libraries, modules); - if (checkModules(libraries, notFoundModules)) + Bundle loaderParams = checkModules(modules, notFoundModules); + if (loaderParams.containsKey(ERROR_CODE_KEY) && EC_NO_ERROR == loaderParams.getInt(ERROR_CODE_KEY)) { - // All modules are available, as such the other application can be notified that it - // can start without problems. - String[] libs = new String[libraries.size()]; - libs = libraries.toArray(libs); - callback.libs(libs, m_environmentVariables, m_applicationParams, 0, null); + try + { + callback.loaderReady(loaderParams); + } + catch (Exception e) + { + e.printStackTrace(); + } } else { - // Starts a retrieval of the modules which are not readily accessible. + // Starts a retrieval of the modules which are not readily accessible. startRetrieval(callback, modules, notFoundModules, appName); } } /** - * Creates and sets up a {@link MinistroActivity} to retrieve the modules specified in the - * <code>notFoundModules</code> argument. - * - * @param callback - * @param modules - * @param notFoundModules - * @param appName - * @throws RemoteException - */ - private void startRetrieval(IMinistroCallback callback, - String[] modules, ArrayList<String> notFoundModules, String appName) - throws RemoteException + * Creates and sets up a {@link MinistroActivity} to retrieve the modules specified in the + * <code>notFoundModules</code> argument. + * + * @param callback + * @param modules + * @param notFoundModules + * @param appName + * @throws RemoteException + */ + private void startRetrieval(IMinistroCallback callback, String[] modules + , ArrayList<String> notFoundModules, String appName) throws RemoteException { ActionStruct as = new ActionStruct(callback, modules, notFoundModules, appName); m_actions.add(as); // if not, lets start an activity to do it. @@ -352,12 +401,12 @@ public class MinistroService extends Service { } /** - * Called by a finished {@link MinistroActivity} in order to let - * the service notify the application which caused the activity about - * the result of the retrieval. - * - * @param id - */ + * Called by a finished {@link MinistroActivity} in order to let + * the service notify the application which caused the activity about + * the result of the retrieval. + * + * @param id + */ void retrievalFinished(int id) { for (int i=0;i<m_actions.size();i++) @@ -366,7 +415,6 @@ public class MinistroService extends Service { if (action.id==id) { postRetrieval(action.callback, action.modules); - m_actions.remove(i); break; } @@ -376,89 +424,94 @@ public class MinistroService extends Service { } /** - * Helper method for the last step of the retrieval process. - * - * <p>Checks the availability of the requested modules and informs - * the requesting application about it via the {@link IMinistroCallback} - * instance.</p> - * - * @param callback - * @param modules - */ - private void postRetrieval(IMinistroCallback callback, String[] modules) { - ArrayList<String> libraries = new ArrayList<String>(); - Collections.addAll(libraries, modules); - + * Helper method for the last step of the retrieval process. + * + * <p>Checks the availability of the requested modules and informs + * the requesting application about it via the {@link IMinistroCallback} + * instance.</p> + * + * @param callback + * @param modules + */ + private void postRetrieval(IMinistroCallback callback, String[] modules) + { // Does a final check whether the libraries are accessible (without caring for // the non-accessible ones). - boolean res = checkModules(libraries, null); - - String[] libs = new String[libraries.size()]; - libs = libraries.toArray(libs); - try { - if (res) - callback.libs(libs, m_environmentVariables, m_applicationParams ,0, null); - else - callback.libs(libs, m_environmentVariables, m_applicationParams, 1, "Can't find all modules"); + callback.loaderReady(checkModules(modules, null)); } - catch (RemoteException e) + catch (Exception e) { - Log.w(TAG, "Was unable to do 'libs' callback after retrieving libraries. Ignoring and assuming that the other application exited."); + e.printStackTrace(); } - } /** - * Checks whether a given list of libraries are readily accessible (e.g. usable by a program). - * - * <p>If the <code>notFoundModules</code> argument is given, the method fills the list with - * libraries that need to be retrieved first.</p> - * - * @param libs - * @param notFoundModules - * @return - */ - boolean checkModules(ArrayList<String> libs, ArrayList<String> notFoundModules) + * Checks whether a given list of libraries are readily accessible (e.g. usable by a program). + * + * <p>If the <code>notFoundModules</code> argument is given, the method fills the list with + * libraries that need to be retrieved first.</p> + * + * @param libs + * @param notFoundModules + * @return true if all modules are available + */ + Bundle checkModules(String[] modules, ArrayList<String> notFoundModules) { - ArrayList<Module> modules= new ArrayList<Module>(); + Bundle params = new Bundle(); boolean res=true; - for (int i=0;i<libs.size();i++) - res = res & addModules(libs.get(i), modules, notFoundModules); // don't stop on first error + ArrayList<Module> libs= new ArrayList<Module>(); + Set<String> jars= new HashSet<String>(); + for (String module: modules) + res = res & addModules(module, libs, notFoundModules, jars); // don't stop on first error + ArrayList<String> tempStringArray = new ArrayList<String>(); // sort all libraries - Collections.sort(modules, new ModuleCompare()); - libs.clear(); - for (int i=0;i<modules.size();i++) - libs.add(m_qtLibsRootPath+modules.get(i).path); - return res; + Collections.sort(libs, new ModuleCompare()); + for (Module lib: libs) + tempStringArray.add(m_qtLibsRootPath+lib.path); + params.putString(NATIVE_LIBRARIES_KEY, Library.join(tempStringArray, m_pathSeparator)); + + tempStringArray.clear(); + for (String jar: jars) + tempStringArray.add(m_qtLibsRootPath+jar); + params.putString(DEX_PATH_KEY, Library.join(tempStringArray, m_pathSeparator)); + + params.putString(LOADER_CLASS_NAME_KEY, m_loaderClassName); + params.putString(LIB_PATH_KEY, m_qtLibsRootPath); + params.putString(ENVIRONMENT_VARIABLES_KEY, m_environmentVariables); + params.putString(APPLICATION_PARAMETERS_KEY, m_applicationParams); + params.putInt(ERROR_CODE_KEY, res?EC_NO_ERROR:EC_NOT_FOUND); + return params; } - /** +/** * Helper method for the module resolution mechanism. It deals with an individual module's * resolution request. - * + * * <p>The method checks whether a given <em>single</em> <code>module</code> is already * accessible or needs to be retrieved first. In the latter case the method returns * <code>false</code>.</p> - * + * * <p>The method traverses a <code>module<code>'s dependencies automatically.</p> - * + * * <p>In order to find out whether a <code>module</code> is accessible the method consults * the list of downloaded libraries. If found, an entry to the <code>modules</code> list is * added.</p> - * + * * <p>In case the <code>module</ocde> is not immediately accessible and the <code>notFoundModules</code> * argument exists, a list of available libraries is consulted to fill a list of modules which - * yet need to be retrieved.</p> - * + * yet need to be retrieved.</p> + * * @param module * @param modules * @param notFoundModules + * @param jars * @return <code>true</code> if the given module and all its dependencies are readily available. */ - private boolean addModules(String module, ArrayList<Module> modules, ArrayList<String> notFoundModules) + private boolean addModules(String module, ArrayList<Module> modules + , ArrayList<String> notFoundModules, Set<String> jars) { // Module argument is not supposed to be null at this point. if (modules == null) @@ -482,11 +535,15 @@ public class MinistroService extends Service { m.name=m_downloadedLibraries.get(i).name; m.path=m_downloadedLibraries.get(i).filePath; m.level=m_downloadedLibraries.get(i).level; + if (m_downloadedLibraries.get(i).needs != null) + for(NeedsStruct needed: m_downloadedLibraries.get(i).needs) + if (needed.type != null && needed.type.equals("jar")) + jars.add(needed.filePath); modules.add(m); boolean res = true; if (m_downloadedLibraries.get(i).depends != null) for (int depIt=0;depIt<m_downloadedLibraries.get(i).depends.length;depIt++) - res &= addModules(m_downloadedLibraries.get(i).depends[depIt], modules, notFoundModules); + res &= addModules(m_downloadedLibraries.get(i).depends[depIt], modules, notFoundModules, jars); return res; } } @@ -502,7 +559,7 @@ public class MinistroService extends Service { return false; } - // Deal with not yet readily accessible module's dependencies. + // Deal with not yet readily accessible module's dependencies. notFoundModules.add(module); for (int i = 0; i< m_availableLibraries.size(); i++) { @@ -510,7 +567,7 @@ public class MinistroService extends Service { { if (m_availableLibraries.get(i).depends != null) for (int depIt=0;depIt<m_availableLibraries.get(i).depends.length;depIt++) - addModules(m_availableLibraries.get(i).depends[depIt], modules, notFoundModules); + addModules(m_availableLibraries.get(i).depends[depIt], modules, notFoundModules, jars); break; } } @@ -518,28 +575,29 @@ public class MinistroService extends Service { return false; } -/** Sorter for libraries. - * - * Hence the order in which the libraries have to be loaded is important, it is neccessary - * to sort them. - */ -static private class ModuleCompare implements Comparator<Module> { - @Override - public int compare(Module a, Module b) { - return a.level-b.level; + /** Sorter for libraries. + * + * Hence the order in which the libraries have to be loaded is important, it is neccessary + * to sort them. + */ + static private class ModuleCompare implements Comparator<Module> + { + @Override + public int compare(Module a, Module b) + { + return a.level-b.level; + } } -} - -/** Helper class which allows manipulating libraries. - * - * It is similar to the {@link Library} class but has fewer fields. - */ -static private class Module -{ - String path; - String name; - int level; -} + /** Helper class which allows manipulating libraries. + * + * It is similar to the {@link Library} class but has fewer fields. + */ + static private class Module + { + String path; + String name; + int level; + } }
\ No newline at end of file diff --git a/MinistroConfigurationTool/AndroidManifest.xml b/MinistroConfigurationTool/AndroidManifest.xml index b3dd7a8..64e5ce8 100644 --- a/MinistroConfigurationTool/AndroidManifest.xml +++ b/MinistroConfigurationTool/AndroidManifest.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="eu.licentia.ministro.config" + package="org.kde.ministro.config" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> - <activity android:name="MinistroConfigurationToolActivity" + <activity android:name=".MinistroConfigurationToolActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/MinistroConfigurationTool/res/values-ro/strings.xml b/MinistroConfigurationTool/res/values-ro/strings.xml new file mode 100644 index 0000000..7933125 --- /dev/null +++ b/MinistroConfigurationTool/res/values-ro/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">Instrument de configurare Ministro</string> + <string name="install_ministro_msg">Acest instrument are nevoie de cel mai recent serviciu Ministro. Doriţi să-l instalaţi?</string> +</resources> diff --git a/MinistroConfigurationTool/res/values/strings.xml b/MinistroConfigurationTool/res/values/strings.xml index 6f84e54..67016f5 100644 --- a/MinistroConfigurationTool/res/values/strings.xml +++ b/MinistroConfigurationTool/res/values/strings.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Ministro configuration tool</string> + <string name="install_ministro_msg">This tool needs latest Ministro service. Would you like to install it?</string> </resources> diff --git a/MinistroConfigurationTool/src/eu/licentia/ministro/config/MinistroConfigurationToolActivity.java b/MinistroConfigurationTool/src/eu/licentia/ministro/config/MinistroConfigurationToolActivity.java deleted file mode 100644 index 3989cc9..0000000 --- a/MinistroConfigurationTool/src/eu/licentia/ministro/config/MinistroConfigurationToolActivity.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright (c) 2011, BogDan Vatra <bog_dan_ro@yahoo.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package eu.licentia.ministro.config; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ComponentName; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; - -public class MinistroConfigurationToolActivity extends Activity { - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - try - { - Intent intent = new Intent(); - intent.setComponent(new ComponentName("eu.licentia.necessitas.ministro", "eu.licentia.necessitas.ministro.MinistroConfigActivity")); - startActivity(intent); - finish(); - } - catch (Exception e) { - AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this); - downloadDialog.setMessage("This tool needs latest Ministro service. Would you like to install it?"); - downloadDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialogInterface, int i) { - try - { - Uri uri = Uri.parse("market://search?q=pname:eu.licentia.necessitas.ministro"); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - finish(); - } - catch (Exception e) { - e.printStackTrace(); - finish(); - } - } - }); - - downloadDialog.setNegativeButton("No", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialogInterface, int i) { - finish(); - } - }); - downloadDialog.show(); - } - super.onCreate(savedInstanceState); - } -} diff --git a/Necessitas_SDK/ministrorepogen/main.cpp b/Necessitas_SDK/ministrorepogen/main.cpp index 23f7abc..ce8395e 100644 --- a/Necessitas_SDK/ministrorepogen/main.cpp +++ b/Necessitas_SDK/ministrorepogen/main.cpp @@ -93,6 +93,7 @@ int main(int argc, char *argv[]) return 1; QStringList excludePaths=element.attribute("excludePaths").split(';'); + QString loaderClassName=element.attribute("loaderClassName"); QString applicationParameters=element.attribute("applicationParameters"); QString environmentVariables=element.attribute("environmentVariables"); @@ -137,6 +138,8 @@ int main(int argc, char *argv[]) NeedsStruct needed; needed.name=childs.attribute("name"); needed.relativePath=childs.attribute("file"); + if (childs.hasAttribute("type")) + needed.type=childs.attribute("type"); libs[libraryName].needs<<needed; childs=childs.nextSiblingElement(); } @@ -160,7 +163,7 @@ int main(int argc, char *argv[]) QFile::link(QString("android-%1").arg(androdPlatform), QString("android-%1").arg(symLink)); QFile outXmlFile(xmlPath); outXmlFile.open(QIODevice::WriteOnly); - outXmlFile.write(QString("<libs version=\"%1\" applicationParameters=\"%2\" environmentVariables=\"%3\">\n").arg(version).arg(applicationParameters).arg(environmentVariables).toUtf8()); + outXmlFile.write(QString("<libs version=\"%1\" applicationParameters=\"%2\" environmentVariables=\"%3\" loaderClassName=\"%4\">\n").arg(version).arg(applicationParameters).arg(environmentVariables).arg(loaderClassName).toUtf8()); foreach (const QString & key, libs.keys()) { if (libs[key].platform && libs[key].platform != androdPlatform) @@ -204,8 +207,13 @@ int main(int argc, char *argv[]) qWarning()<<"Warning : Can't find \""<<libsPath+"/"+needed.relativePath<<"\" item will be skipped"; continue; } - outXmlFile.write(QString("\t\t\t<item name=\"%1\" url=\"http://files.kde.org/necessitas/qt/android/%2/objects/%3/%4\" file=\"%4\" size=\"%5\" sha1=\"%6\" />\n") - .arg(needed.name).arg(abiVersion).arg(version).arg(needed.relativePath).arg(fileSize).arg(sha1Hash).toUtf8()); + + QString type; + if (needed.type.length()) + type=QString(" type=\"%1\" ").arg(needed.type); + + outXmlFile.write(QString("\t\t\t<item name=\"%1\" url=\"http://files.kde.org/necessitas/qt/android/%2/objects/%3/%4\" file=\"%4\" size=\"%5\" sha1=\"%6\"%7/>\n") + .arg(needed.name).arg(abiVersion).arg(version).arg(needed.relativePath).arg(fileSize).arg(sha1Hash).arg(type).toUtf8()); } outXmlFile.write("\t\t</needs>\n"); } diff --git a/Necessitas_SDK/ministrorepogen/rules.xml b/Necessitas_SDK/ministrorepogen/rules.xml index ea75126..2a440dc 100644 --- a/Necessitas_SDK/ministrorepogen/rules.xml +++ b/Necessitas_SDK/ministrorepogen/rules.xml @@ -5,13 +5,13 @@ <version value="6" symlink="5"/> <version value="7" symlink="5"/> <version value="8"/> - <version value="9" symlink="8"/> - <version value="10" symlink="8"/> - <version value="11" symlink="8"/> - <version value="12" symlink="8"/> + <version value="9"/> + <version value="10" symlink="9"/> + <version value="11" symlink="9"/> + <version value="12" symlink="9"/> </platforms> - <libs excludePaths="imports;plugins" applicationParameters="-platform android" environmentVariables="MINISTRO_SSL_CERTS_PATH=MINISTRO_PATH/qt/ssl QML_IMPORT_PATH=MINISTRO_PATH/qt/imports QT_PLUGIN_PATH=MINISTRO_PATH/qt/plugins"> + <libs excludePaths="imports;plugins" loaderClassName="org.kde.necessitas.industrius.QtLoader" applicationParameters="-platform android" environmentVariables="MINISTRO_SSL_CERTS_PATH=MINISTRO_PATH/qt/ssl QML_IMPORT_PATH=MINISTRO_PATH/qt/imports QT_PLUGIN_PATH=MINISTRO_PATH/qt/plugins"> <lib file="lib/libQtNetwork.so" > <needs> <item name="GenericBearerPlugin" file="plugins/bearer/libqgenericbearer.so"/> diff --git a/Necessitas_SDK/ministrorepogen/sortlibs.h b/Necessitas_SDK/ministrorepogen/sortlibs.h index 8181c21..14c3885 100644 --- a/Necessitas_SDK/ministrorepogen/sortlibs.h +++ b/Necessitas_SDK/ministrorepogen/sortlibs.h @@ -30,6 +30,7 @@ struct NeedsStruct { QString name; QString relativePath; + QString type; }; struct Library |