Skip to content

Commit

Permalink
Implemented feature #3124846 - Allow suppressing unused permissions o…
Browse files Browse the repository at this point in the history
…n Android
  • Loading branch information
Dmitry Moskalchuk committed Apr 14, 2010
1 parent bdaa9de commit 5429649
Show file tree
Hide file tree
Showing 13 changed files with 265 additions and 54 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -74,7 +74,8 @@ platform/android/bin
platform/android/target
platform/shared/*/bin
platform/android/**/default.properties
gapikey.h
genconfig.h
rhocaps.inc

#*.jar
*.cod
Expand Down
2 changes: 1 addition & 1 deletion platform/android/Rhodes/jni/include/JNIRhodes.h
Expand Up @@ -13,7 +13,7 @@
#include <logging/RhoLogConf.h>
#include <logging/RhoLog.h>

#include "gapikey.h"
#include "genconfig.h"

JavaVM *jvm();
void store_thr_jnienv(JNIEnv *env);
Expand Down
43 changes: 22 additions & 21 deletions platform/android/Rhodes/jni/include/details/rhojava.inc
@@ -1,28 +1,29 @@
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_INTEGER, "java/lang/Integer")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_ALERT, "com/rhomobile/rhodes/alert/Alert")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_BOOLEAN, "java/lang/Boolean")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_FLOAT, "java/lang/Float")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CAMERA, "com/rhomobile/rhodes/camera/Camera")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CAPABILITIES, "com/rhomobile/rhodes/Capabilities")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CONTACT, "com/rhomobile/rhodes/phonebook/Contact")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CONTACT_FIELD, "com/rhomobile/rhodes/phonebook/ContactField")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_DATE_TIME_PICKER, "com/rhomobile/rhodes/datetime/DateTimePicker")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_DOUBLE, "java/lang/Double")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_STRING, "java/lang/String")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_ITERATOR, "java/util/Iterator")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_SET, "java/util/Set")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_MAP, "java/util/Map")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_HASHMAP, "java/util/HashMap")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_VECTOR, "java/util/Vector")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_INET4ADDRESS, "java/net/Inet4Address")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_FILEDESCRIPTOR, "java/io/FileDescriptor")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_RHODES, "com/rhomobile/rhodes/Rhodes")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_WEB_VIEW, "com/rhomobile/rhodes/WebView")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_FLOAT, "java/lang/Float")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_GEO_LOCATION, "com/rhomobile/rhodes/geolocation/GeoLocation")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CAMERA, "com/rhomobile/rhodes/camera/Camera")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_DATE_TIME_PICKER, "com/rhomobile/rhodes/datetime/DateTimePicker")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_HASHMAP, "java/util/HashMap")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_INET4ADDRESS, "java/net/Inet4Address")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_INTEGER, "java/lang/Integer")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_ITERATOR, "java/util/Iterator")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_MAP, "java/util/Map")
#ifdef RHO_GOOGLE_API_KEY
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_MAPVIEW, "com/rhomobile/rhodes/mapview/MapView")
#endif // RHO_GOOGLE_API_KEY
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_NATIVEBAR, "com/rhomobile/rhodes/NativeBar")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_PHONEBOOK, "com/rhomobile/rhodes/phonebook/Phonebook")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CONTACT, "com/rhomobile/rhodes/phonebook/Contact")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_CONTACT_FIELD, "com/rhomobile/rhodes/phonebook/ContactField")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_ALERT, "com/rhomobile/rhodes/alert/Alert")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_RHODES, "com/rhomobile/rhodes/Rhodes")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_RHOSOCKADDR, "com/rhomobile/rhodes/socket/RhoSockAddr")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_RINGTONE_MANAGER, "com/rhomobile/rhodes/RingtoneManager")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_NATIVEBAR, "com/rhomobile/rhodes/NativeBar")
#ifdef GOOGLE_API_KEY
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_MAPVIEW, "com/rhomobile/rhodes/mapview/MapView")
#endif
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_SET, "java/util/Set")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_SSLIMPL, "com/rhomobile/rhodes/socket/SSLImpl")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_RHOSOCKADDR, "com/rhomobile/rhodes/socket/RhoSockAddr")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_STRING, "java/lang/String")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_VECTOR, "java/util/Vector")
RHODES_DEFINE_JAVA_CLASS(RHODES_JAVA_CLASS_WEB_VIEW, "com/rhomobile/rhodes/WebView")
11 changes: 3 additions & 8 deletions platform/android/Rhodes/jni/src/mapview.cpp
@@ -1,17 +1,13 @@
#include "JNIRhodes.h"

#include "gapikey.h"

#include <common/rhoparams.h>

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "MapView"

extern "C" void alert_show_popup(char *);

RHO_GLOBAL void mapview_create(rho_param *p)
{
#ifdef GOOGLE_API_KEY
#ifdef RHO_GOOGLE_API_KEY
JNIEnv *env = jnienv();
jclass clsMapView = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
if (!clsMapView) return;
Expand All @@ -24,10 +20,9 @@ RHO_GLOBAL void mapview_create(rho_param *p)
}

jobject paramsObj = RhoValueConverter(env).createObject(p);
env->CallStaticVoidMethod(clsMapView, midCreate, rho_cast<jstring>(GOOGLE_API_KEY), paramsObj);
env->CallStaticVoidMethod(clsMapView, midCreate, rho_cast<jstring>(RHO_GOOGLE_API_KEY), paramsObj);
#else
const char *message = "MapView disabled";
alert_show_popup((char*)message);
RAWLOG_ERROR("MapView disabled at build time");
#endif
}

25 changes: 25 additions & 0 deletions platform/android/Rhodes/jni/src/rhodes.cpp
Expand Up @@ -284,9 +284,34 @@ RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_Rhodes_makeLink
env->ThrowNew(env->FindClass("java/lang/RuntimeException"), "Can not create symlink");
}

static void set_capabilities(JNIEnv *env)
{
char const *caps[] = {
#define RHO_DEFINE_CAP(x) #x,
#include <details/rhocaps.inc>
#undef RHO_DEFINE_CAP
};
std::map<std::string, bool> actual_caps;
#define RHO_DEFINE_CAP(x) actual_caps[#x] = RHO_CAP_ ## x ## _ENABLED;
#include <details/rhocaps.inc>
#undef RHO_DEFINE_CAP

jclass cls = getJNIClass(RHODES_JAVA_CLASS_CAPABILITIES);
if (!cls) return;
for (size_t i = 0, lim = sizeof(caps)/sizeof(caps[0]); i < lim; ++i)
{
std::string field_name = std::string(caps[i]) + "_ENABLED";
jfieldID fid = getJNIClassStaticField(env, cls, field_name.c_str(), "Z");
if (!fid) return;
env->SetStaticBooleanField(cls, fid, actual_caps[caps[i]]);
}
}

RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_Rhodes_createRhodesApp
(JNIEnv *env, jobject, jstring path)
{
set_capabilities(env);

g_rootPath = rho_cast<std::string>(path);

// Init SQLite temp directory
Expand Down
12 changes: 12 additions & 0 deletions platform/android/Rhodes/src/com/rhomobile/rhodes/Capabilities.java
@@ -0,0 +1,12 @@
package com.rhomobile.rhodes;

public class Capabilities {

public static boolean CAMERA_ENABLED = true;
public static boolean GPS_ENABLED = true;
public static boolean NETWORK_STATE_ENABLED = true;
public static boolean PHONE_ENABLED = true;
public static boolean PIM_ENABLED = true;
public static boolean VIBRATE_ENABLED = true;

}
5 changes: 5 additions & 0 deletions platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java
Expand Up @@ -610,6 +610,11 @@ public static void showNetworkIndicator(boolean v) {
}

private static boolean hasNetwork() {
if (!Capabilities.NETWORK_STATE_ENABLED) {
Logger.E(TAG, "Capability NETWORK_STATE disabled");
return false;
}

Context ctx = RhodesInstance.getInstance();
ConnectivityManager conn = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
if (conn == null)
Expand Down
Expand Up @@ -43,6 +43,7 @@
import android.widget.TextView;

import com.rhomobile.rhodes.AndroidR;
import com.rhomobile.rhodes.Capabilities;
import com.rhomobile.rhodes.Logger;
import com.rhomobile.rhodes.Rhodes;
import com.rhomobile.rhodes.RhodesInstance;
Expand Down Expand Up @@ -252,6 +253,8 @@ public static void showPopup(Object params) {

public static void vibrate(int duration) {
try {
if (!Capabilities.VIBRATE_ENABLED)
throw new IllegalAccessException("VIBRATE disabled");
Logger.T(TAG, "vibrate: " + duration);
Rhodes instance = RhodesInstance.getInstance();
Vibrator vibrator = (Vibrator)instance.getSystemService(Context.VIBRATOR_SERVICE);
Expand Down
Expand Up @@ -23,6 +23,8 @@
import java.io.File;

import android.content.Intent;

import com.rhomobile.rhodes.Capabilities;
import com.rhomobile.rhodes.Logger;
import com.rhomobile.rhodes.Rhodes;
import com.rhomobile.rhodes.RhodesInstance;
Expand All @@ -45,6 +47,20 @@ private static void init() {
f.mkdirs();
}

private static class CameraDisabled implements Runnable {

private String url;

public CameraDisabled(String u) {
url = u;
}

public void run() {
callback(url, "", "Camera disabled", false);
}

};

private static class Runner implements Runnable {

private String url;
Expand All @@ -64,18 +80,20 @@ public void run() {
}
};

public static void takePicture(String sourceUrl) {
public static void takePicture(String url) {
try {
Rhodes.performOnUiThread(new Runner(sourceUrl, ImageCapture.class), false);
Runnable runnable = Capabilities.CAMERA_ENABLED ? new Runner(url, ImageCapture.class) :
new CameraDisabled(url);
Rhodes.performOnUiThread(runnable, false);
}
catch (Exception e) {
reportFail("takePicture", e);
}
}

public static void choosePicture(String sourceUrl) {
public static void choosePicture(String url) {
try {
Rhodes.performOnUiThread(new Runner(sourceUrl, FileList.class), false);
Rhodes.performOnUiThread(new Runner(url, FileList.class), false);
}
catch (Exception e) {
reportFail("choosePicture", e);
Expand Down
Expand Up @@ -20,6 +20,7 @@
*/
package com.rhomobile.rhodes.geolocation;

import com.rhomobile.rhodes.Capabilities;
import com.rhomobile.rhodes.Logger;

public class GeoLocation {
Expand All @@ -31,6 +32,11 @@ private static void reportFail(String name, Exception e) {
Logger.E(TAG, "Call of \"" + name + "\" failed: " + e.getMessage());
}

private static void checkState() throws IllegalAccessException {
if (!Capabilities.GPS_ENABLED)
throw new IllegalAccessException("GPS disabled");
}

private static void init() {
if (locImpl != null)
return;
Expand All @@ -43,6 +49,7 @@ private static void init() {

public static boolean isAvailable() {
try {
checkState();
Logger.T(TAG, "isAvailable");
init();
return locImpl.isAvailable();
Expand All @@ -56,6 +63,7 @@ public static boolean isAvailable() {

public static double getLatitude() {
try {
checkState();
Logger.T(TAG, "getLatitude");
init();
return locImpl.GetLatitude();
Expand All @@ -69,6 +77,7 @@ public static double getLatitude() {

public static double getLongitude() {
try {
checkState();
Logger.T(TAG, "getLongitude");
init();
return locImpl.GetLongitude();
Expand All @@ -82,6 +91,7 @@ public static double getLongitude() {

public static boolean isKnownPosition() {
try {
checkState();
Logger.T(TAG, "isKnownPosition");
init();
return locImpl.isKnownPosition();
Expand Down
Expand Up @@ -37,11 +37,15 @@
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;

import com.rhomobile.rhodes.Capabilities;
import com.rhomobile.rhodes.Logger;
import com.rhomobile.rhodes.RhodesInstance;

//@RubyLevelClass(name="Phonebook")
public class Phonebook {

private static final String TAG = "Phonebook";

private Map<String, Contact> contactList = new HashMap<String, Contact>();
private Activity activity;
private ContentResolver cr;
Expand All @@ -63,7 +67,20 @@ private String getId(Contact contact) {
return m.find() ? m.group(1) : "";
}

private boolean checkState() {
if (!Capabilities.PIM_ENABLED)
Logger.E(TAG, "Can not execute: PIM disabled");
return Capabilities.PIM_ENABLED;
}

public Phonebook() {
if (!checkState())
return;

fill();
}

private void fill() {

idPattern = Pattern.compile("\\{([0-9]+)\\}");
activity = RhodesInstance.getInstance();
Expand Down Expand Up @@ -194,44 +211,71 @@ else if (names.length > 1) {
}

public void close() {
if (!checkState())
return;

this.contactList.clear();
}

public void moveToBegin() {
if (!checkState())
return;

iter = contactList.values().iterator();
}

public boolean hasNext() {
if (!checkState())
return false;

return iter.hasNext();
}

public Object next() {
if (!checkState())
return null;

return iter.next();
}

public Contact getFirstRecord() {
if (!checkState())
return null;

moveToBegin();
if (!iter.hasNext())
return null;
return iter.next();
}

public Contact getNextRecord() {
if (!checkState())
return null;

return iter.next();
}

public Contact getRecord(String id) {
if (!checkState())
return null;

return contactList.get(id);
}

public void removeContact(Contact contact) throws Exception {
if (!checkState())
return;

Uri uri = People.CONTENT_URI;

String id = getId(contact);
cr.delete(uri, People._ID + "=" + id, null);
}

public void saveContact(Contact contact) throws Exception {
if (!checkState())
return;

String rbID = getId(contact);
Uri uri = null;

Expand Down

0 comments on commit 5429649

Please sign in to comment.