[android] Fix bug with native nested Java object creation (simply avoid this).

This commit is contained in:
vng 2012-05-18 12:01:43 +03:00 committed by Alex Zolotarev
parent 325fff401e
commit 8a9e9b803e
8 changed files with 96 additions and 46 deletions

View file

@ -35,13 +35,34 @@ namespace jni
{
ASSERT(env, ("JNIEnv can't be 0"));
ASSERT(obj, ("jobject can't be 0"));
jclass cls = env->GetObjectClass(obj);
ASSERT(cls, ("Can't get java class"));
jmethodID mid = env->GetMethodID(cls, fn, sig);
ASSERT(mid, ("Can't find java method", fn, sig));
return mid;
}
/*
jobject CreateJavaObject(JNIEnv * env, char const * klassName, char const * sig, ...)
{
jclass klass = env->FindClass(klassName);
ASSERT(klass, ("Can't find java class", klassName));
jmethodID methodId = env->GetMethodID(klass, "<init>", sig);
ASSERT(methodId, ("Can't find java constructor", sig));
va_list args;
va_start(args, sig);
jobject res = env->NewObject(klass, methodId, args);
ASSERT(res, ());
va_end(args);
return res;
}
*/
string ToString(jstring str)
{
JNIEnv * env = GetEnv();

View file

@ -7,10 +7,16 @@
namespace jni
{
// Some examples of signature:
// "()V" - void function returning void;
// "(Ljava/lang/String;)V" - String function returning void;
/// @name Some examples of signature:
/// "()V" - void function returning void;
/// "(Ljava/lang/String;)V" - String function returning void;
/// "com/mapswithme/maps/MapStorage$Index" - class MapStorage.Index
//@{
jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig);
//jobject CreateJavaObject(JNIEnv * env, char const * klass, char const * sig, ...);
//@}
string ToString(jstring str);
JNIEnv * GetEnv();
JavaVM * GetJVM();

View file

@ -165,21 +165,14 @@ extern "C"
JNIEnv * env = jni::GetEnv();
jmethodID onFinishMethod = env->GetMethodID(env->GetObjectClass(*obj.get()), "onDownloadFinished", "(I)V");
ASSERT(onFinishMethod, ("Not existing method: void onDownloadFinished(int)"));
env->CallVoidMethod(*obj.get(), onFinishMethod, errorCode);
jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onDownloadFinished", "(I)V");
env->CallVoidMethod(*obj.get(), methodID, errorCode);
}
void DownloadFileProgress(shared_ptr<jobject> obj, downloader::HttpRequest & req)
{
LOG(LDEBUG, (req.Progress().first, "bytes for", g_filesToDownload.back().m_fileName, "was downloaded"));
JNIEnv * env = jni::GetEnv();
jmethodID onProgressMethod = env->GetMethodID(env->GetObjectClass(*obj.get()), "onDownloadProgress", "(IIII)V");
ASSERT(onProgressMethod, ("Not existing method: void onDownloadProgress(int, int, int, int)"));
FileToDownload & curFile = g_filesToDownload.back();
jint curTotal = req.Progress().second;
@ -187,7 +180,10 @@ extern "C"
jint glbTotal = g_totalBytesToDownload;
jint glbProgress = g_totalDownloadedBytes + req.Progress().first;
env->CallVoidMethod(*obj.get(), onProgressMethod,
JNIEnv * env = jni::GetEnv();
jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onDownloadProgress", "(IIII)V");
env->CallVoidMethod(*obj.get(), methodID,
curTotal, curProgress,
glbTotal, glbProgress);
}

View file

@ -3,44 +3,46 @@
///////////////////////////////////////////////////////////////////////////////////
#include "Framework.hpp"
#include "../core/jni_helper.hpp"
extern "C"
{
class IndexBinding
{
private:
shared_ptr<jobject> m_self;
jfieldID m_groupID;
jfieldID m_countryID;
jfieldID m_regionID;
public:
jobject object() const { return *m_self.get(); }
public:
IndexBinding(jobject self) : m_self(jni::make_global_ref(self))
{
jclass cls = jni::GetEnv()->GetObjectClass(*m_self.get());
jclass klass = jni::GetEnv()->GetObjectClass(object());
m_groupID = jni::GetEnv()->GetFieldID(cls, "mGroup", "I");
m_countryID = jni::GetEnv()->GetFieldID(cls, "mCountry", "I");
m_regionID = jni::GetEnv()->GetFieldID(cls, "mRegion", "I");
m_groupID = jni::GetEnv()->GetFieldID(klass, "mGroup", "I");
m_countryID = jni::GetEnv()->GetFieldID(klass, "mCountry", "I");
m_regionID = jni::GetEnv()->GetFieldID(klass, "mRegion", "I");
}
int group() const
{
return jni::GetEnv()->GetIntField(*m_self.get(), m_groupID);
return jni::GetEnv()->GetIntField(object(), m_groupID);
}
int country() const
{
return jni::GetEnv()->GetIntField(*m_self.get(), m_countryID);
return jni::GetEnv()->GetIntField(object(), m_countryID);
}
int region() const
{
return jni::GetEnv()->GetIntField(*m_self.get(), m_regionID);
return jni::GetEnv()->GetIntField(object(), m_regionID);
}
storage::TIndex const toNative() const
@ -50,17 +52,16 @@ extern "C"
static jobject toJava(storage::TIndex const & idx)
{
LOG(LDEBUG, ("constructing Java Index object from ", idx.m_group, idx.m_country, idx.m_region));
JNIEnv * env = jni::GetEnv();
jclass klass = env->FindClass("com/mapswithme/maps/MapStorage$Index");
ASSERT(klass, ("Can't find java class com/mapswithme/maps/MapStorage$Index"));
jclass klass = env->FindClass("com/mapswithme/maps/MapStorage");
ASSERT(klass, ());
jmethodID methodId = env->GetMethodID(klass, "<init>", "(III)V");
ASSERT(methodId, ("Can't find java constructor in com/mapswithme/maps/MapStorage$Index"));
jmethodID methodId = env->GetStaticMethodID(klass,
"createIndex", "(III)Lcom/mapswithme/maps/MapStorage$Index;");
ASSERT(methodId, ());
return env->NewObject(klass, methodId, idx.m_group, idx.m_country, idx.m_region);
return env->CallStaticObjectMethod(klass, methodId, idx.m_group, idx.m_country, idx.m_region);
}
};
@ -136,37 +137,35 @@ extern "C"
{
JNIEnv * env = jni::GetEnv();
jclass klass = env->GetObjectClass(*obj.get());
jmethodID methodID = env->GetMethodID(klass, "onCountryStatusChanged", "(Lcom/mapswithme/maps/MapStorage$Index;)V");
jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onCountryStatusChanged", "(Lcom/mapswithme/maps/MapStorage$Index;)V");
env->CallVoidMethod(*obj.get(), methodID, IndexBinding::toJava(idx));
}
void ReportCountryProgress(shared_ptr<jobject> const & obj, storage::TIndex const & idx, pair<int64_t, int64_t> const & p)
{
jlong const current = p.first;
jlong const total = p.second;
JNIEnv * env = jni::GetEnv();
jclass klass = env->GetObjectClass(*obj.get());
jmethodID methodID = env->GetMethodID(klass, "onCountryProgress", "(Lcom/mapswithme/maps/MapStorage$Index;JJ)V");
jlong current = p.first;
jlong total = p.second;
jmethodID methodID = jni::GetJavaMethodID(env, *obj.get(), "onCountryProgress", "(Lcom/mapswithme/maps/MapStorage$Index;JJ)V");
env->CallVoidMethod(*obj.get(), methodID, IndexBinding::toJava(idx), current, total);
}
JNIEXPORT jint JNICALL
Java_com_mapswithme_maps_MapStorage_subscribe(JNIEnv * env, jobject thiz, jobject obs)
Java_com_mapswithme_maps_MapStorage_subscribe(JNIEnv * env, jobject thiz, jobject obj)
{
jint res = g_framework->Storage().Subscribe(bind(&ReportChangeCountryStatus, jni::make_global_ref(obs), _1),
bind(&ReportCountryProgress, jni::make_global_ref(obs), _1, _2));
return res;
LOG(LDEBUG, ("Subscribe on storage"));
return g_framework->Storage().Subscribe(bind(&ReportChangeCountryStatus, jni::make_global_ref(obj), _1),
bind(&ReportCountryProgress, jni::make_global_ref(obj), _1, _2));
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_MapStorage_unsubscribe(JNIEnv * env, jobject thiz, jint slotID)
{
LOG(LDEBUG, ("UnSubscribe from storage"));
g_framework->Storage().Unsubscribe(slotID);
}
}

View file

@ -506,6 +506,8 @@ public class DownloadUI extends ListActivity implements MapStorage.Listener
public void onCountryStatusChanged(Index idx)
{
Log.d(TAG, "onCountryStatusChanged for index: " + idx.toString());
final int position = getItemPosition(idx);
if (position != -1)
{

View file

@ -76,9 +76,14 @@ public class MapStorage
return ret;
}
public boolean isEqual(Index idx)
{
return (mGroup == idx.mGroup && mCountry == idx.mCountry && mRegion == idx.mRegion);
}
public boolean isChild(Index idx)
{
return (idx.getParent().equals(this));
return (idx.getParent().isEqual(this));
}
public int getPosition()
@ -87,6 +92,12 @@ public class MapStorage
else if (mCountry != -1) return mCountry;
else return mGroup;
}
@Override
public String toString()
{
return ("Index(" + mGroup + ", " + mCountry + ", " + mRegion + ")");
}
}
public native int countriesCount(Index idx);
@ -103,6 +114,10 @@ public class MapStorage
public native void showCountry(Index idx);
public native int subscribe(Listener l);
public native void unsubscribe(int slotId);
private MapStorage()
{
}
@ -117,6 +132,8 @@ public class MapStorage
return mInstance;
}
public native int subscribe(Listener l);
public native void unsubscribe(int slotId);
public static Index createIndex(int group, int country, int region)
{
return new Index(group, country, region);
}
}

View file

@ -33,6 +33,13 @@ namespace storage
{
const int TIndex::INVALID = -1;
string DebugPrint(TIndex const & r)
{
ostringstream out;
out << "storage::TIndex(" << r.m_group << ", " << r.m_country << ", " << r.m_region << ")";
return out.str();
}
// static string ErrorString(DownloadResultT res)
// {
// switch (res)

View file

@ -53,6 +53,8 @@ namespace storage
}
};
string DebugPrint(TIndex const & r);
/// Can be used to store local maps and/or maps available for download
class Storage
{