diff --git a/android/jni/and_storage.cpp b/android/jni/and_storage.cpp index de96106..101d867 100644 --- a/android/jni/and_storage.cpp +++ b/android/jni/and_storage.cpp @@ -8,7 +8,6 @@ #include - class AndStorage { class AssetReader : public rd::Reader @@ -33,16 +32,15 @@ class AndStorage }; public: + + AndStorage() + : m_isInited(false) {} + void Init(JNIEnv * env, jobject manager) { AssetReader reader("index.dat", AAssetManager_fromJava(env, manager)); m_storage.Load(reader); - } - - static AndStorage & Instance() - { - static AndStorage storage; - return storage; + m_isInited = true; } void Query(string const & query, bool useLocation, double lat, double lon) @@ -73,8 +71,14 @@ public: return m_storage.GetArticleInfoFromUrl(url); } + bool IsInited() + { + return m_isInited; + } + private: Storage m_storage; + bool m_isInited; }; #ifdef __cplusplus @@ -82,31 +86,13 @@ extern "C" { #endif -// TODO: *problem -//#define DECLARE_FN(retType, suffix) +AndStorage m_andStorage; +#define STORAGE m_andStorage -#define STORAGE AndStorage::Instance() - -/* - * Class: com_example_travelguide_cpp_Storage - * Method: query - * Signature: (Ljava/lang/String;DD)V - */ -JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_query(JNIEnv * env, jclass clazz, jstring query, - jboolean useLocation, jdouble lat, jdouble lon) +void InitStorage(JNIEnv * env, jobject jAssetManager) { - STORAGE.Query(JString2StdString(env, query), useLocation, lat, lon); -} - -/* - * Class: com_example_travelguide_cpp_Storage - * Method: getResultSize - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_example_travelguide_cpp_Storage_getResultSize - (JNIEnv * env, jclass clazz) -{ - return STORAGE.GetResultSize(); + if (!STORAGE.IsInited()) + m_andStorage.Init(env, jAssetManager); } jobject NativeArticle2JavaArticle(JNIEnv * env, ArticleInfo const * p) @@ -126,25 +112,41 @@ jobject NativeArticle2JavaArticle(JNIEnv * env, ArticleInfo const * p) p->m_lon); } +/* + * Class: com_example_travelguide_cpp_Storage + * Method: query + * Signature: (Ljava/lang/String;DD)V + */ +JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_query(JNIEnv * env, jobject thiz, jstring query, + jboolean useLocation, jdouble lat, jdouble lon) +{ + STORAGE.Query(JString2StdString(env, query), useLocation, lat, lon); +} + +/* + * Class: com_example_travelguide_cpp_Storage + * Method: getResultSize + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_example_travelguide_cpp_Storage_getResultSize + (JNIEnv * env, jobject thiz) +{ + return STORAGE.GetResultSize(); +} + /* * Class: com_example_travelguide_cpp_Storage * Method: getArticleInfoByIndex * Signature: (I)Lcom/example/travelguide/article/ArticleInfo; */ JNIEXPORT jobject JNICALL Java_com_example_travelguide_cpp_Storage_getArticleInfoByIndex - (JNIEnv * env, jclass clazz, jint index) + (JNIEnv * env, jobject thiz, jint index) { return NativeArticle2JavaArticle(env, &STORAGE.GetArticleInfoByIndex(index)); } -JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_nativeInitIndex - (JNIEnv * env, jclass clazz, jobject assetManager) -{ - STORAGE.Init(env, assetManager); -} - JNIEXPORT jobject JNICALL Java_com_example_travelguide_cpp_Storage_getArticleInfoByUrl - (JNIEnv * env, jclass clazz, jstring url) + (JNIEnv * env, jobject thiz, jstring url) { return NativeArticle2JavaArticle(env, STORAGE.GetArticleInfoByUrl(JString2StdString(env, url))); } @@ -155,6 +157,16 @@ JNIEXPORT jboolean JNICALL Java_com_example_travelguide_cpp_Storage_isValidLatLo return ll::ValidLat(lat) && ll::ValidLon(lon) ? JNI_TRUE : JNI_FALSE; } +/* + * Class: com_example_travelguide_cpp_Storage + * Method: nativeCreate + * Signature: (Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_nativeInit + (JNIEnv * env, jobject thiz, jobject jAssetManager) +{ + InitStorage(env, jAssetManager); +} #ifdef __cplusplus } diff --git a/android/jni/and_storage.hpp b/android/jni/and_storage.hpp index 0efc2de..72bce17 100644 --- a/android/jni/and_storage.hpp +++ b/android/jni/and_storage.hpp @@ -9,11 +9,19 @@ extern "C" { #endif /* * Class: com_example_travelguide_cpp_Storage - * Method: getTitleByUrl - * Signature: (Ljava/lang/String;)Ljava/lang/String; + * Method: nativeCreate + * Signature: (Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_nativeInit + (JNIEnv *, jobject, jobject); + +/* + * Class: com_example_travelguide_cpp_Storage + * Method: getArticleInfoByUrl + * Signature: (Ljava/lang/String;)Lcom/example/travelguide/article/ArticleInfo; */ JNIEXPORT jobject JNICALL Java_com_example_travelguide_cpp_Storage_getArticleInfoByUrl - (JNIEnv *, jclass, jstring); + (JNIEnv *, jobject, jstring); /* * Class: com_example_travelguide_cpp_Storage @@ -21,7 +29,7 @@ JNIEXPORT jobject JNICALL Java_com_example_travelguide_cpp_Storage_getArticleInf * Signature: (Ljava/lang/String;ZDD)V */ JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_query - (JNIEnv *, jclass, jstring, jboolean, jdouble, jdouble); + (JNIEnv *, jobject, jstring, jboolean, jdouble, jdouble); /* * Class: com_example_travelguide_cpp_Storage @@ -29,7 +37,7 @@ JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_query * Signature: ()I */ JNIEXPORT jint JNICALL Java_com_example_travelguide_cpp_Storage_getResultSize - (JNIEnv *, jclass); + (JNIEnv *, jobject); /* * Class: com_example_travelguide_cpp_Storage @@ -37,15 +45,15 @@ JNIEXPORT jint JNICALL Java_com_example_travelguide_cpp_Storage_getResultSize * Signature: (I)Lcom/example/travelguide/article/ArticleInfo; */ JNIEXPORT jobject JNICALL Java_com_example_travelguide_cpp_Storage_getArticleInfoByIndex - (JNIEnv *, jclass, jint); + (JNIEnv *, jobject, jint); /* * Class: com_example_travelguide_cpp_Storage - * Method: nativeInitIndex - * Signature: (Ljava/lang/Object;)V + * Method: isValidLatLon + * Signature: (DD)Z */ -JNIEXPORT void JNICALL Java_com_example_travelguide_cpp_Storage_nativeInitIndex - (JNIEnv *, jclass, jobject); +JNIEXPORT jboolean JNICALL Java_com_example_travelguide_cpp_Storage_isValidLatLon + (JNIEnv *, jclass, jdouble, jdouble); #ifdef __cplusplus } diff --git a/android/src/com/example/travelguide/ArticleInfoDetailActivity.java b/android/src/com/example/travelguide/ArticleInfoDetailActivity.java index c976752..4fbeab8 100644 --- a/android/src/com/example/travelguide/ArticleInfoDetailActivity.java +++ b/android/src/com/example/travelguide/ArticleInfoDetailActivity.java @@ -27,23 +27,11 @@ public class ArticleInfoDetailActivity extends FragmentActivity super.onCreate(savedInstanceState); setContentView(R.layout.activity_articleinfo_detail); - // Show the Up button in the action bar. - // getActionBar().setDisplayHomeAsUpEnabled(true); - - // savedInstanceState is non-null when there is fragment state - // saved from previous configurations of this activity - // (e.g. when rotating the screen from portrait to landscape). - // In this case, the fragment will automatically be re-added - // to its container so we don't need to manually add it. - // For more information, see the Fragments API guide at: - // - // http://developer.android.com/guide/components/fragments.html - // if (savedInstanceState == null) { // Create the detail fragment and add it to the activity // using a fragment transaction. - Bundle arguments = new Bundle(); + final Bundle arguments = new Bundle(); arguments.putSerializable(ArticleInfoDetailFragment.ARTICLE_INFO, getIntent().getSerializableExtra(ArticleInfoDetailFragment.ARTICLE_INFO)); diff --git a/android/src/com/example/travelguide/ArticleInfoDetailFragment.java b/android/src/com/example/travelguide/ArticleInfoDetailFragment.java index 1bbf94e..f01d336 100644 --- a/android/src/com/example/travelguide/ArticleInfoDetailFragment.java +++ b/android/src/com/example/travelguide/ArticleInfoDetailFragment.java @@ -14,6 +14,7 @@ import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.TextView; + import com.example.travelguide.ArticleInfoListFragment.OnListIconClickedListener; import com.example.travelguide.article.ArticleInfo; import com.example.travelguide.article.ArticlePathFinder; @@ -27,7 +28,8 @@ import com.susanin.travelguide.R; * either contained in a {@link ArticleInfoListActivity} in two-pane mode (on * tablets) or a {@link ArticleInfoDetailActivity} on handsets. */ -public class ArticleInfoDetailFragment extends Fragment implements OnClickListener +public class ArticleInfoDetailFragment extends Fragment + implements OnClickListener { public static final String ARTICLE_INFO = "article_info"; @@ -41,6 +43,7 @@ public class ArticleInfoDetailFragment extends Fragment implements OnClickListen private View mProgressContainer; private ArticlePathFinder mFinder; +// private Storage mStorage; private OnListIconClickedListener mIconClickedListener; @@ -129,7 +132,7 @@ public class ArticleInfoDetailFragment extends Fragment implements OnClickListen if (!Utils.isExternalUrl(url) && url.endsWith(".html")) { final String strippedUrl = url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.')); - mTitle.setText(Storage.getArticleInfoByUrl(strippedUrl).getName()); + mTitle.setText(getStorage().getArticleInfoByUrl(strippedUrl).getName()); } } @@ -179,4 +182,9 @@ public class ArticleInfoDetailFragment extends Fragment implements OnClickListen mWebView.goBack(); } + public Storage getStorage() + { + return Storage.get(getActivity()); + } + } diff --git a/android/src/com/example/travelguide/ArticleInfoListActivity.java b/android/src/com/example/travelguide/ArticleInfoListActivity.java index 4a4c2f0..5859eee 100644 --- a/android/src/com/example/travelguide/ArticleInfoListActivity.java +++ b/android/src/com/example/travelguide/ArticleInfoListActivity.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.util.Log; + import com.example.travelguide.article.ArticleInfo; import com.example.travelguide.cpp.Storage; import com.mapswithme.maps.api.MWMPoint; @@ -28,8 +29,10 @@ import com.susanin.travelguide.R; * {@link ArticleInfoListFragment.Callbacks} interface to listen for item * selections. */ -public class ArticleInfoListActivity extends FragmentActivity implements ArticleInfoListFragment.Callbacks, - ArticleInfoListFragment.OnListIconClickedListener, ArticleInfoListFragment.OnFirstLoadListener +public class ArticleInfoListActivity extends FragmentActivity + implements ArticleInfoListFragment.Callbacks, + ArticleInfoListFragment.OnListIconClickedListener, + ArticleInfoListFragment.OnFirstLoadListener { private static final String TAG = ArticleInfoListActivity.class.getSimpleName(); @@ -48,11 +51,14 @@ public class ArticleInfoListActivity extends FragmentActivity implements Article super.onCreate(savedInstanceState); setContentView(R.layout.activity_articleinfo_list); + + mArtInfoListFragment = (ArticleInfoListFragment) getSupportFragmentManager() + .findFragmentById(R.id.articleinfo_list); + if (findViewById(R.id.articleinfo_detail_container) != null) { mTwoPane = true; - mArtInfoListFragment = (ArticleInfoListFragment) getSupportFragmentManager().findFragmentById(R.id.articleinfo_list); mArtInfoListFragment.setActivateOnItemClick(true); mArtInfoListFragment.setOnFirstLoadListener(this); mArtInfoListFragment.setHeaderVisible(false); @@ -88,7 +94,9 @@ public class ArticleInfoListActivity extends FragmentActivity implements Article { final String id = point.getId(); Log.d(TAG, id); - onItemSelected(Storage.getArticleInfoByUrl(id)); +// final Storage storage = new Storage(getAssets()); +// storage.create(); + onItemSelected(Storage.get(this).getArticleInfoByUrl(id)); } } diff --git a/android/src/com/example/travelguide/ArticleInfoListFragment.java b/android/src/com/example/travelguide/ArticleInfoListFragment.java index 662ad6b..f0b9fc2 100644 --- a/android/src/com/example/travelguide/ArticleInfoListFragment.java +++ b/android/src/com/example/travelguide/ArticleInfoListFragment.java @@ -3,7 +3,9 @@ package com.example.travelguide; import static com.example.travelguide.util.Utils.hideIf; import static com.example.travelguide.util.Utils.hideView; import static com.example.travelguide.util.Utils.showView; + import java.util.ArrayList; + import android.app.Activity; import android.content.Context; import android.location.Location; @@ -22,6 +24,7 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ListView; import android.widget.TextView; + import com.example.travelguide.article.ArticleInfo; import com.example.travelguide.async.QueryResultLoader; import com.example.travelguide.cpp.Storage; @@ -40,10 +43,10 @@ import com.susanin.travelguide.R; * Activities containing this fragment MUST implement the {@link Callbacks} * interface. */ -public class ArticleInfoListFragment extends ListFragment implements LoaderCallbacks, TextWatcher, - OnClickListener, LocationListener +public class ArticleInfoListFragment extends ListFragment + implements LoaderCallbacks, TextWatcher, + OnClickListener, LocationListener { - private static final String TAG = ArticleInfoListFragment.class.getSimpleName(); public interface OnListIconClickedListener { @@ -63,7 +66,6 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb { mOnFirstLoad = listener; } - // !First load private View mRootView; @@ -82,6 +84,8 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb private final static long LOCATION_UPDATE_INTERVAL = 30 * 60 * 1000; // !Location +// private Storage mStorage; + private static final String STATE_ACTIVATED_POSITION = "activated_position"; private Callbacks mCallbacks = sDummyCallbacks; @@ -126,9 +130,17 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb Utils.hideKeyboard(getActivity()); checkLocation(); + search(mSearchText.getText().toString()); } + @Override + public void onPause() + { + super.onPause(); + mLocationManager.removeUpdates(this); + } + private void checkLocation() { if (System.currentTimeMillis() - sLastLocationRequestTime > LOCATION_UPDATE_INTERVAL) @@ -142,12 +154,7 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb } } - @Override - public void onPause() - { - super.onPause(); - mLocationManager.removeUpdates(this); - } + @Override public void onAttach(Activity activity) @@ -253,14 +260,13 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb final Location loc = getLocation(); if (loc != null) - return new QueryResultLoader(getActivity(), query, loc.getLatitude(), loc.getLongitude()); + return new QueryResultLoader(getActivity(), getStorage(), query, loc.getLatitude(), loc.getLongitude()); else - return new QueryResultLoader(getActivity(), query); + return new QueryResultLoader(getActivity(), getStorage(), query); } return null; } - @SuppressWarnings("static-access") @Override public void onLoadFinished(Loader loader, Storage result) { @@ -320,14 +326,14 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb private void openInMwm() { - final int count = Storage.getResultSize(); + final int count = getStorage().getResultSize(); if (count < 1) return; final ArrayList points = new ArrayList(); for (int i = 0; i < count; ++i) { - final ArticleInfo info = Storage.getArticleInfoByIndex(i); + final ArticleInfo info = getStorage().getArticleInfoByIndex(i); if (info.isValidLatLon()) points.add(Utils.articleInfo2MwmPoint(info)); } @@ -368,4 +374,9 @@ public class ArticleInfoListFragment extends ListFragment implements LoaderCallb public void onStatusChanged(String provider, int status, Bundle extras) {} + public Storage getStorage() + { + return Storage.get(getActivity()); + } + } diff --git a/android/src/com/example/travelguide/async/QueryResultLoader.java b/android/src/com/example/travelguide/async/QueryResultLoader.java index 54b1fe6..b0532a2 100644 --- a/android/src/com/example/travelguide/async/QueryResultLoader.java +++ b/android/src/com/example/travelguide/async/QueryResultLoader.java @@ -7,34 +7,36 @@ import com.example.travelguide.cpp.Storage; public class QueryResultLoader extends AsyncTaskLoader { + private final Storage mStorage; private final String mQuery; private final double mLat; private final double mLon; private final boolean mUseLocation; - public QueryResultLoader(Context context, String query) + public QueryResultLoader(Context context, Storage storage, String query) { super(context); mQuery = query; mUseLocation = false; mLat = mLon = 0; + mStorage = storage; } - public QueryResultLoader(Context context, String query, double lat, double lon) + public QueryResultLoader(Context context, Storage storage, String query, double lat, double lon) { super(context); mQuery = query; mUseLocation = true; mLat = lat; mLon = lon; + mStorage = storage; } @Override public Storage loadInBackground() { - Storage.initAssets(getContext()); - Storage.query(mQuery, mUseLocation, mLat, mLon); - return new Storage(); + mStorage.query(mQuery, mUseLocation, mLat, mLon); + return mStorage; } } diff --git a/android/src/com/example/travelguide/cpp/Storage.java b/android/src/com/example/travelguide/cpp/Storage.java index 66702a9..f582e48 100644 --- a/android/src/com/example/travelguide/cpp/Storage.java +++ b/android/src/com/example/travelguide/cpp/Storage.java @@ -7,32 +7,48 @@ import com.example.travelguide.article.ArticleInfo; public class Storage { + private static volatile Storage sInstance; + + public static Storage get(Context context) + { + if (sInstance == null) + synchronized (Storage.class) + { + if (sInstance == null) + { + sInstance = new Storage(context.getAssets()); + sInstance.init(); + } + } + return sInstance; + } + + // We need to store this reference + // in order to prevent garbage collection + // see asset_manager_jni.h + private final AssetManager mAssetManager; + + private Storage(AssetManager assetManager) + { + mAssetManager = assetManager; + } + + private void init() + { + nativeInit(mAssetManager); + } + + private native void nativeInit(Object jAssetManager); + + public native ArticleInfo getArticleInfoByUrl(String url); + public native void query(String query, boolean useLocation, double lat, double lon); + public native int getResultSize(); + public native ArticleInfo getArticleInfoByIndex(int index); + + public native static boolean isValidLatLon(double lat, double lon); static { System.loadLibrary("tguide"); } - - private static boolean sIsAssetsInited = false; - public static void initAssets(Context context) - { - if (sIsAssetsInited) - return; - - final AssetManager am = context.getAssets(); - nativeInitIndex(am); - sIsAssetsInited = true; - } - - public native static ArticleInfo getArticleInfoByUrl(String url); - - public native static void query(String query, boolean useLocation, double lat, double lon); - - public native static int getResultSize(); - - public native static ArticleInfo getArticleInfoByIndex(int index); - - private native static void nativeInitIndex(AssetManager am); - - public native static boolean isValidLatLon(double lat, double lon); }