I have a problem with my first real android project. I need to start a new activity from this one down there, when the client tracker does recognize a target. It would mean the world to me if someone could help me.
The things I already tried, ended always in a disaster... probably because I have no idea what I’m doing (thats also the reason I'm not posting what I have tried)
P.S. I used the Wikitude native Api libary
package com.ia.grafp.maturapp2_2;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.ia.grafp.maturapp2_2.rendering.external.CustomSurfaceView;
import com.ia.grafp.maturapp2_2.rendering.external.Driver;
import com.ia.grafp.maturapp2_2.rendering.external.GLRenderer;
import com.wikitude.WikitudeSDK;
import com.wikitude.WikitudeSDKStartupConfiguration;
import com.wikitude.common.camera.CameraSettings;
import com.wikitude.common.rendering.RenderExtension;
import com.wikitude.common.tracking.RecognizedTarget;
import com.wikitude.rendering.ExternalRendering;
import com.wikitude.tracker.ClientTracker;
import com.wikitude.tracker.ClientTrackerEventListener;
import com.wikitude.tracker.Tracker;
/**
*/
public class ArchitectView extends AppCompatActivity implements ClientTrackerEventListener, ExternalRendering {
private static final String TAG = "ArchitectView";
private WikitudeSDK _wikitudeSDK;
private CustomSurfaceView _view;
private Driver _driver;
private GLRenderer _glRenderer;
private boolean tracking;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_wikitudeSDK = new WikitudeSDK(this);
WikitudeSDKStartupConfiguration startupConfiguration
= new WikitudeSDKStartupConfiguration
(WikitudeSDKConstants.WIKITUDE_SDK_KEY,
CameraSettings.CameraPosition.BACK,
CameraSettings.CameraFocusMode.CONTINUOUS);
_wikitudeSDK.onCreate(getApplicationContext(), this, startupConfiguration);
ClientTracker tracker
= _wikitudeSDK.getTrackerManager().create2dClientTracker
("file:///android_asset/magazine.wtc");
tracker.registerTrackerEventListener(this);
}
#Override
protected void onResume() {
super.onResume();
_wikitudeSDK.onResume();
_view.onResume();
_driver.start();
}
#Override
protected void onPause() {
super.onPause();
_wikitudeSDK.onPause();
_view.onPause();
_driver.stop();
}
#Override
protected void onDestroy() {
super.onDestroy();
_wikitudeSDK.onDestroy();
}
#Override
public void onRenderExtensionCreated(final RenderExtension renderExtension_) {
_glRenderer = new GLRenderer(renderExtension_);
_view = new CustomSurfaceView(getApplicationContext(), _glRenderer);
_driver = new Driver(_view, 30);
setContentView(_view);
}
#Override
public void onExtendedTrackingQualityUpdate(final Tracker tracker_, final String targetName_, final int oldTrackingQuality_, final int newTrackingQuality_) {
}
#Override
public void onErrorLoading(final ClientTracker clientTracker_, final String errorMessage_) {
Log.v(TAG, "onErrorLoading: " + errorMessage_);
}
#Override
public void onTrackerFinishedLoading(final ClientTracker clientTracker_, final String trackerFilePath_) {
}
#Override
public void onTargetRecognized(final Tracker tracker_, final String targetName_) {
}
#Override
public void onTracking(final Tracker tracker_, final RecognizedTarget recognizedTarget_) {
_glRenderer.setCurrentlyRecognizedTarget(recognizedTarget_);
}
#Override
public void onTargetLost(final Tracker tracker_, final String targetName_) {
_glRenderer.setCurrentlyRecognizedTarget(null);
}
}
#Override
public void onTargetRecognized(final Tracker tracker_, final String targetName_) {
Intent i = new Intent(ArchitectView.this, yourActivityClass.class);
startactivity(i);
}
I don't know if this answer your question, but that is the way of starting a new activity.
Related
So, I recently learned Retrofit and was trying to create an application that uses an API to download Pokemon details. Here's the code for the MainActivity.java class and the MainActivityViewModel.java class. There are other classes there but they are mostly the Model classes and so I haven't mentioned them:
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.widget.Toast;
import com.arpansircar.java.pokemonapplication.R;
import com.arpansircar.java.pokemonapplication.viewmodel.MainActivityViewModel;
public class MainActivity extends AppCompatActivity {
private MainActivityViewModel mainActivityViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
}
#Override
protected void onResume() {
super.onResume();
observeRetrofitFailures();
mainActivityViewModel.downloadMainPokemonData();
mainActivityViewModel.returnMainDownloadedData().observe(this, resultsPokemonServiceModels ->
mainActivityViewModel.downloadSelectedPokemonData(resultsPokemonServiceModels));
mainActivityViewModel.returnDownloadedPokemonData().observe(this, map -> {
});
}
private void observeRetrofitFailures() {
mainActivityViewModel.returnMainServiceErrorLiveData().observe(this, s ->
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show());
mainActivityViewModel.returnSelectedPokemonServiceErrorLiveData().observe(this, s ->
Toast.makeText(this, s, Toast.LENGTH_SHORT).show());
}
}
MainActivityViewModel.java
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.arpansircar.java.pokemonapplication.model.GetPokemonId;
import com.arpansircar.java.pokemonapplication.model.MainPokemonServiceModel;
import com.arpansircar.java.pokemonapplication.model.ResultsPokemonServiceModel;
import com.arpansircar.java.pokemonapplication.model.SelectedPokemonModel;
import com.arpansircar.java.pokemonapplication.retrofit.MainPokemonRetrofitInstance;
import com.arpansircar.java.pokemonapplication.retrofit.PokemonServiceInterface;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.internal.EverythingIsNonNull;
public class MainActivityViewModel extends ViewModel {
private MainPokemonServiceModel mainPokemonServiceModel;
private final Map<String, String> pokemonHashMap = new HashMap<>();
private final PokemonServiceInterface mainPokemonServiceInterface = MainPokemonRetrofitInstance.getInstance();
private final MutableLiveData<String> mainServiceErrorLiveData = new MutableLiveData<>();
private final MutableLiveData<String> selectedPokemonServiceErrorLiveData = new MutableLiveData<>();
private final MutableLiveData<Map<String, String>> downloadMainPokemonData = new MutableLiveData<>();
private final MutableLiveData<List<ResultsPokemonServiceModel>> resultsPokemonServiceModelListLiveData = new MutableLiveData<>();
public void downloadMainPokemonData() {
Call<MainPokemonServiceModel> mainPokemonServiceModelCall = mainPokemonServiceInterface.getResultsDataFromService();
mainPokemonServiceModelCall.enqueue(new Callback<MainPokemonServiceModel>() {
#Override
#EverythingIsNonNull
public void onResponse(Call<MainPokemonServiceModel> call, Response<MainPokemonServiceModel> response) {
if (!response.isSuccessful()) {
mainServiceErrorLiveData.postValue(String.valueOf(response.code()));
return;
}
mainPokemonServiceModel = response.body();
resultsPokemonServiceModelListLiveData.postValue(Objects.requireNonNull(mainPokemonServiceModel).resultsPokemonServiceModel);
}
#Override
#EverythingIsNonNull
public void onFailure(Call<MainPokemonServiceModel> call, Throwable t) {
mainServiceErrorLiveData.postValue(t.getMessage());
}
});
}
public void downloadSelectedPokemonData(List<ResultsPokemonServiceModel> resultsPokemonServiceModelList) {
for (ResultsPokemonServiceModel resultsPokemonServiceModel : resultsPokemonServiceModelList) {
String pokemonId = GetPokemonId.getId(resultsPokemonServiceModel.url);
Call<SelectedPokemonModel> selectedPokemonModelCall = MainPokemonRetrofitInstance.getInstance().getSelectedPokemonSprite(pokemonId);
selectedPokemonModelCall.enqueue(new Callback<SelectedPokemonModel>() {
#Override
#EverythingIsNonNull
public void onResponse(Call<SelectedPokemonModel> call, Response<SelectedPokemonModel> response) {
if (!response.isSuccessful()) {
selectedPokemonServiceErrorLiveData.postValue(String.valueOf(response.code()));
return;
}
SelectedPokemonModel selectedPokemonModel = response.body();
String pokemonName = Objects.requireNonNull(selectedPokemonModel).pokemonName;
String pokemonSpriteUrl = selectedPokemonModel.pokemonSpriteModel.spriteUrl;
pokemonHashMap.put(pokemonName, pokemonSpriteUrl);
}
#Override
#EverythingIsNonNull
public void onFailure(Call<SelectedPokemonModel> call, Throwable t) {
selectedPokemonServiceErrorLiveData.postValue(t.getMessage());
}
});
}
downloadMainPokemonData.postValue(pokemonHashMap);
}
public LiveData<Map<String, String>> returnDownloadedPokemonData() {
return downloadMainPokemonData;
}
public LiveData<List<ResultsPokemonServiceModel>> returnMainDownloadedData() {
return resultsPokemonServiceModelListLiveData;
}
public LiveData<String> returnMainServiceErrorLiveData() {
return mainServiceErrorLiveData;
}
public LiveData<String> returnSelectedPokemonServiceErrorLiveData() {
return selectedPokemonServiceErrorLiveData;
}
}
My main problem is at the line downloadMainPokemonData.postValue(pokemonHashMap);. When the download finishes, the MutableLiveData object (for some reason) isn't notified about this, i.e., the HashMap isn't returned back to the MainActivity.
I put some log checks and found the method is indeed being triggered. However, the system exits the method even before the download is completed. The download does get completed, yes. But for some reason, it doesn't return the downloaded HashMap back to the MainActivity. I think that this could be because the enqueue method provided by Retrofit is asynchronous and does all the tasks in a background thread.
Could someone provide any hints as to how I can take care of this? Thanks!
selectedPokemonModelCall.enqueue is async request. downloadMainPokemonData.postValue(pokemonHashMap) called before Response<SelectedPokemonModel> data was handled
i'd like to add title and description for each marker on my map. For now i add marker on map taking data from a server with a GET call and creating marker for each object in response.
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
MainActivity.this.mapboxMap = mapboxMap;
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
List<Feature> symbolLayerIconFeatureList = new ArrayList<>();
for(int i = 0; i < jsonArray.length(); i++){
JSONObject crag = jsonArray.getJSONObject(i);
String description = crag.getString("descrizione")
String name = crag.getString("nome");
Double lng = crag.getDouble("longitudine");
Double lat = crag.getDouble("latitudine");
symbolLayerIconFeatureList.add(Feature.fromGeometry(
Point.fromLngLat(lng, lat)));
}
mapboxMap.setStyle(new Style.Builder().fromUri("mapbox://styles/mapbox/cjf4m44iw0uza2spb3q0a7s41")
.withImage(ICON_ID, BitmapFactory.decodeResource(
MainActivity.this.getResources(), R.drawable.icona_falesia))
.withSource(new GeoJsonSource(SOURCE_ID,
FeatureCollection.fromFeatures(symbolLayerIconFeatureList)))
.withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties(
iconImage(ICON_ID),
iconAllowOverlap(true),
iconIgnorePlacement(true)
)
), new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
}
});
} catch (JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mQueue.add(request);
}
This is my function onMapReady where a get data and create marker. How can i add also title and a kind of description for each marker?
You'll also need to use textField(), textOffset(), textIgnorePlacement(), textAllowOverlap(), and textField() if you just want show text along with a SymbolLayer icon. Adding the name and description to each Feature is key to getting this working correctly.
I've modified https://docs.mapbox.com/android/maps/examples/marker-symbol-layer/ to create the GIF seen at https://i.imgur.com/5LzSzRf.mp4. You can look at what's going on in the code and then adjust it to match your implementation within the GET onResponse() callback.
package com.mapbox.mapboxandroiddemo.examples.styles;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import java.util.ArrayList;
import java.util.List;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOffset;
/**
* Display {#link SymbolLayer} icons on the map.
*/
public class BasicSymbolLayerActivity extends AppCompatActivity implements
OnMapReadyCallback {
private static final String SOURCE_ID = "SOURCE_ID";
private static final String ICON_ID = "ICON_ID";
private static final String LAYER_ID = "LAYER_ID";
private MapView mapView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, getString(R.string.access_token));
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_style_basic_symbol_layer);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
#Override
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
List<Feature> symbolLayerIconFeatureList = new ArrayList<>();
Feature singleFeature = Feature.fromGeometry(Point.fromLngLat(-57.225365, -33.213144));
singleFeature.addStringProperty("NAME_PROPERTY_KEY", "descrizione 1");
singleFeature.addStringProperty("DESCRIPTION_PROPERTY_KEY", "nome 1");
Feature secondFeature = Feature.fromGeometry(Point.fromLngLat(-54.14164, -33.981818));
secondFeature.addStringProperty("NAME_PROPERTY_KEY", "descrizione 2");
secondFeature.addStringProperty("DESCRIPTION_PROPERTY_KEY", "nome 2");
Feature thirdFeature = Feature.fromGeometry(Point.fromLngLat(-56.990533, -30.583266));
thirdFeature.addStringProperty("NAME_PROPERTY_KEY", "descrizione 3");
thirdFeature.addStringProperty("DESCRIPTION_PROPERTY_KEY", "nome 3");
symbolLayerIconFeatureList.add(singleFeature);
symbolLayerIconFeatureList.add(secondFeature);
symbolLayerIconFeatureList.add(thirdFeature);
mapboxMap.setStyle(new Style.Builder().fromUri("mapbox://styles/mapbox/cjf4m44iw0uza2spb3q0a7s41")
// Add the SymbolLayer icon image to the map style
.withImage(ICON_ID, BitmapFactory.decodeResource(
BasicSymbolLayerActivity.this.getResources(), R.drawable.mapbox_marker_icon_default))
// Adding a GeoJson source for the SymbolLayer icons.
.withSource(new GeoJsonSource(SOURCE_ID,
FeatureCollection.fromFeatures(symbolLayerIconFeatureList)))
// Adding the actual SymbolLayer to the map style. An offset is added that the bottom of the red
// marker icon gets fixed to the coordinate, rather than the middle of the icon being fixed to
// the coordinate point. This is offset is not always needed and is dependent on the image
// that you use for the SymbolLayer icon.
.withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties(
iconImage(ICON_ID),
iconAllowOverlap(true),
iconIgnorePlacement(true),
textOffset(new Float[]{0f,-2.5f}),
textIgnorePlacement(true),
textAllowOverlap(true),
textField(Expression.concat(get("NAME_PROPERTY_KEY"), Expression.literal("–"), get("DESCRIPTION_PROPERTY_KEY")))
)
), new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// Map is set up and the style has loaded. Now you can add additional data or make other map adjustments.
}
});
}
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
#Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
See https://docs.mapbox.com/android/maps/examples/symbol-layer-info-window/ if you want to create an info window.
Yesterday i ask a simplified question of my problem, but think its too simplified.
What my programm should do, is to hear a keyword and when he hear it, he should listen to what i said. (like if you told to siri or google now, by saying siri or ok google).
I'm using pocketsphinx for the keyword and the google speechrecognizer for the longer parts. It works, but only for one time. The pocketsphinx is in the MainActivity and the google recognizer is in an extra class (Jarvis).
The programm starts with the pocketsphinx listener, when he hear the KEYPHRASE, he starts the google listener by calling jarvis.startListener() (by the next()-method) and there is the problem, when the googlelistener is done, i dont come back from the Jarvis-class to the MainActivity to call the next() method again.
(when the google recognizer is done, the last things he do is in the onResult() in Jarvis-class, but from there i cant call the next()-method from MainActivity-class)
MainActivity
package com.example.superuser.jarvis;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import edu.cmu.pocketsphinx.Assets;
import edu.cmu.pocketsphinx.Hypothesis;
import edu.cmu.pocketsphinx.SpeechRecognizer;
import edu.cmu.pocketsphinx.SpeechRecognizerSetup;
import static android.widget.Toast.makeText;
import static edu.cmu.pocketsphinx.SpeechRecognizerSetup.defaultSetup;
public class MainActivity extends Activity implements edu.cmu.pocketsphinx.RecognitionListener {
private String LOG_TAG = "Jarvis_hears_anything";
private TextView tv;
private Jarvis jarvis;
private boolean wannahearjarvis = false;
/* Named searches allow to quickly reconfigure the decoder */
private static final String KWS_SEARCH = "wakeup";
/* Keyword we are looking for to activate menu */
private static final String KEYPHRASE = "jarvis";
private edu.cmu.pocketsphinx.SpeechRecognizer recognizer;
//private HashMap<String, Integer> captions;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.b1);
tv = (TextView) findViewById(R.id.tv1);
//captions = new HashMap<String, Integer>();
//captions.put(KWS_SEARCH, R.string.kws_caption);
jarvis = new Jarvis(getApplicationContext());
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(MainActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
((TextView) findViewById(R.id.tv1))
.setText("Failed to init recognizer " + result);
} else {
//switchSearch(KWS_SEARCH);
recognizer.startListening(KWS_SEARCH);
}
}
}.execute();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "geht", Toast.LENGTH_SHORT).show();
}
});
}
public void next(){
if (wannahearjarvis){
recognizer.startListening(KWS_SEARCH);
wannahearjarvis = false;
}
else{
jarvis.startListening();
wannahearjarvis = true;
}
}
#Override
public void onDestroy() {
super.onDestroy();
recognizer.cancel();
recognizer.shutdown();
}
/**
* In partial result we get quick updates about current hypothesis. In
* keyword spotting mode we can react here, in other modes we need to wait
* for final result in onResult.
*/
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null)
return;
String text = hypothesis.getHypstr();
if (text.equals(KEYPHRASE)){
tv.append("found");
recognizer.stop();
//switchSearch(KWS_SEARCH);
}
else {
//((TextView) findViewById(R.id.tv1)).append(text+"PR");
//Log.i(LOG_TAG, text+"PR");
}
}
/**
* This callback is called when we stop the recognizer.
*/
#Override
public void onResult(Hypothesis hypothesis) {
//((TextView) findViewById(R.id.tv1)).setText("");
((TextView) findViewById(R.id.tv1)).append("oR");
if (hypothesis != null) {
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
next();
}
#Override
public void onBeginningOfSpeech() {
}
/**
* We stop recognizer here to get a final result
*/
#Override
public void onEndOfSpeech() {
if (!recognizer.getSearchName().equals(KWS_SEARCH)){
tv.append("fuck");
}
//switchSearch(KWS_SEARCH);
}
/*private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(KWS_SEARCH))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
//String caption = getResources().getString(captions.get(searchName));
//((TextView) findViewById(R.id.tv1)).setText(caption);
//((TextView) findViewById(R.id.tv1)).append(caption);
}*/
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
// To disable logging of raw audio comment out this call (takes a lot of space on the device)
.setRawLogDir(assetsDir)
// Threshold to tune for keyphrase to balance between false alarms and misses
.setKeywordThreshold(1e-20f)
// Use context-independent phonetic search, context-dependent is too slow for mobile
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
/** In your application you might not need to add all those searches.
* They are added here for demonstration. You can leave just one.
*/
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
}
#Override
public void onError(Exception error) {
((TextView) findViewById(R.id.tv1)).setText(error.getMessage());
}
#Override
public void onTimeout() {
//switchSearch(KWS_SEARCH);
}
}
Jarvis
package com.example.superuser.jarvis;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.widget.Toast;
import java.util.ArrayList;
public class Jarvis implements RecognitionListener{
private AudioManager audiom;
private SpeechRecognizer speech;
private Intent recogIntent;
private Toast m;
private Context c;
private String text;
public Jarvis(Context context){
speech = SpeechRecognizer.createSpeechRecognizer(context);
speech.setRecognitionListener(this);
recogIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recogIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "de");
//recogIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, context.getPackageName());
m = new Toast(context);
c=context;
}
public void startListening(){
speech.startListening(recogIntent);
}
public void destroy(){
speech.stopListening();
speech.cancel();
speech.destroy();
}
#Override
public void onReadyForSpeech(Bundle params) {
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onRmsChanged(float rmsdB) {
}
#Override
public void onBufferReceived(byte[] buffer) {
}
#Override
public void onEndOfSpeech() {
}
#Override
public void onError(int error) {
}
#Override
public void onResults(Bundle results) {
ArrayList<String> matches = results
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
Toast.makeText(c, matches.get(0), Toast.LENGTH_LONG).show();
speech.cancel();
//tried
//MainActivity m = new MainActivity();
//m.next();
//but got a Nullpointer Exception
}
#Override
public void onPartialResults(Bundle partialResults) {
}
#Override
public void onEvent(int eventType, Bundle params) {
}
}
You can store reference to the main activity in Jarvis object in a field:
class Jarvis {
....
private MainActivity m;
....
public Jarvis(MainActivity m) {
this.m = m;
}
....
public void onResults(Bundle results) {
....
m.next();
}
You can also send intents to the main activity as described here. This might be overkill in your case though.
I generated the below code from the default template SettingsActivity from Eclipse and ADT. I find it overly complicated. I also added some pieces myself. How can I improve the structure?
Currently Activity listener and a Fragment listener -> Better way?
Get rid of the static Preference proxyEmail = null; -> How? Is static OK?
How can I call/use findPreference(getText(R.string.key_proxy_email)) in onPreferenceChange() method (line 123)?
Refactor ideas?
package com.xyz.abc;
import java.util.List;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.widget.Toast;
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
private static final boolean ALWAYS_SIMPLE_PREFS = false;
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setupSimplePreferencesScreen();
// TODO Not used at the moment
//final SharedPreferences sp = new SecureSharedPreferences(this, this.getSharedPreferences(MY_PREFS_FILE_NAME, Context.MODE_PRIVATE) );
SharedPreferences settings = getSharedPreferences(Global.PREFERENCES, 0);
boolean sent = settings.getBoolean(Global.PREF_SETTING_SENT, false);
if (sent) {
Toast.makeText(getApplicationContext(), Global.TOAST_MSG_SENT, Toast.LENGTH_LONG);
} else {
Toast.makeText(getApplicationContext(), Global.TOAST_MSG_ERROR, Toast.LENGTH_LONG);
}
}
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
addPreferencesFromResource(R.xml.pref_dummy); // Be able to display first title
PreferenceCategory fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_settings);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_settings);
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_advanced);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_advanced);
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_general);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_general);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.registerOnSharedPreferenceChangeListener(this);
toggleProxyEmail(findPreference(getText(R.string.key_via)), findPreference(getText(R.string.key_proxy_email)));
}
/** {#inheritDoc} */
#Override
public boolean onIsMultiPane() {
return isXLargeTablet(this) && !isSimplePreferences(this);
}
/**
* Helper method to determine if the device has an extra-large screen. For example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
private static boolean isSimplePreferences(Context context) {
return ALWAYS_SIMPLE_PREFS || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB || !isXLargeTablet(context);
}
/** {#inheritDoc} */
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
private static Preference.OnPreferenceChangeListener bindPrefSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(index >= 0 ? listPreference.getEntries()[index] : null);
} else {
// For all other preferences, set the summary to the value's simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
private static Preference.OnPreferenceChangeListener bindPrefKeyToEditTextListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
((CheckBoxPreference) preference).setChecked((Boolean) value);
toggleProxyEmail(preference, SettingsPreferenceFragment.proxyEmail);
return true;
}
};
private static void bindPreferenceSummaryToValue(Preference preference) {
preference.setOnPreferenceChangeListener(bindPrefSummaryToValueListener);
// Trigger the listener immediately with the preference's current value.
bindPrefSummaryToValueListener.onPreferenceChange(preference, PreferenceManager.getDefaultSharedPreferences(preference.getContext()).getString(preference.getKey(), ""));
}
private static void bindPreferenceKeyToEditText(Preference preference) {
preference.setOnPreferenceChangeListener(bindPrefKeyToEditTextListener);
// Trigger the listener immediately with the preference's current value.
bindPrefKeyToEditTextListener.onPreferenceChange(preference, PreferenceManager.getDefaultSharedPreferences(preference.getContext()).getBoolean(preference.getKey(), false));
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class SettingsPreferenceFragment extends PreferenceFragment {
static Preference proxyEmail = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_settings);
proxyEmail = findPreference(getText(R.string.key_proxy_email));
toggleProxyEmail(findPreference(getText(R.string.key_via)), proxyEmail);
bindPreferenceSummaryToValue(findPreference(getText(R.string.key_dest_email)));
bindPreferenceKeyToEditText(findPreference(getText(R.string.key_via)));
bindPreferenceSummaryToValue(findPreference(getText(R.string.key_proxy_email)));
bindPreferenceSummaryToValue(findPreference(getText(R.string.key_pwd)));
bindPreferenceSummaryToValue(findPreference(getText(R.string.key_provider)));
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class AdvancedPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_advanced);
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
bindPreferenceSummaryToValue(findPreference(getText(R.string.key_help)));
}
}
private static void toggleProxyEmail(Preference prefKey, Preference prefValue) {
if (prefKey instanceof CheckBoxPreference) {
if(((CheckBoxPreference) prefKey).isChecked()) {
prefValue.setEnabled(true);
} else {
prefValue.setEnabled(false);
}
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // Only called in a normal Activity
if(key.equals(findPreference(getString(R.string.key_via)).getKey())) {
toggleProxyEmail(findPreference(getText(R.string.key_via)), findPreference(getText(R.string.key_proxy_email)));
}
}
}
I've made an apache thrift server and I have a service which contains several functions.
I'm trying to figure out what is the best way to make calls to the remote server from my android application.
My problem is that I can't make calls from the MainActivity thread (the main thread) - and I need to use most of the remote functions in my main activity methods.
I tried to make a static class with a static member called "Server" equals to the server object, and I set it in another thread and then I tried to call it in the main thread (the main activity class) - but I had errors because of jumping from one thread to another..
To be more specified I want something like that:
public class MainActivity extends Activity {
private service.Client myService;
#Override
protected void onCreate(Bundle savedInstanceState) {
..
... Some stuff that define myService (In a new thread ofcourse) ...
}
...
private void MyFunc1() {
myService.Method1();
}
private void MyFunc2() {
myService.Method2();
}
private void MyFunc3() {
myService.Method3();
}
}
I've got a library for talking to REST APIs. Feel free to slice, dice, and re-use: https://github.com/nedwidek/Android-Rest-API
The code is BSD or GPL.
Here's how I use what I have (I've trimmed MainActivity a bit, hopefully not too much):
package com.hatterassoftware.voterguide.api;
import java.util.HashMap;
public class GoogleCivicApi {
protected final String baseUrl = "https://www.googleapis.com/civicinfo/us_v1/";
protected String apiKey = "AIzaSyBZIP5uY_fMF35SVVrytpKgHtppBbj8J0I";
public static final String DATE_FORMAT = "yyyy-MM-dd";
protected static HashMap<String, String> headers;
static {
headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
}
public String createUrl(String uri, HashMap<String, String> params) {
String url = baseUrl + uri + "?key=" + apiKey;
if (params != null) {
for (String hashKey: params.keySet()) {
url += hashKey + "=" + params.get(hashKey) + "&";
}
url = url.substring(0, url.length());
}
return url;
}
}
package com.hatterassoftware.voterguide.api;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.hatterassoftware.restapi.GetTask;
import com.hatterassoftware.restapi.HttpReturn;
import com.hatterassoftware.restapi.RestCallback;
import com.hatterassoftware.voterguide.api.callbacks.ElectionCallback;
import com.hatterassoftware.voterguide.api.models.Election;
public class ElectionsQuery extends GoogleCivicApi implements RestCallback {
GetTask getTask;
ElectionCallback callback;
final String TAG = "ElectionQuery";
public ElectionsQuery(ElectionCallback callback) {
String url = this.createUrl("elections", null);
this.callback = callback;
Log.d(TAG, "Creating and executing task for: " + url);
getTask = new GetTask(url, this, null, null, null);
getTask.execute();
}
#Override
public void onPostSuccess() {
Log.d(TAG, "onPostSuccess entered");
}
#Override
public void onTaskComplete(HttpReturn httpReturn) {
Log.d(TAG, "onTaskComplete entered");
Log.d(TAG, "httpReturn.status = " + httpReturn.status);
if (httpReturn.content != null) Log.d(TAG, httpReturn.content);
if (httpReturn.restException != null) Log.d(TAG, "Exception in httpReturn", httpReturn.restException);
JsonParser parser = new JsonParser();
JsonElement electionArrayJson = ((JsonObject)parser.parse(httpReturn.content)).get("elections");
Log.d(TAG, electionArrayJson.toString());
Gson gson = new GsonBuilder().setDateFormat(GoogleCivicApi.DATE_FORMAT).create();
Election[] elections = gson.fromJson(electionArrayJson.toString(), Election[].class);
callback.retrievedElection(elections);
}
}
package com.hatterassoftware.voterguide;
import java.util.Calendar;
import java.util.List;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.hatterassoftware.voterguide.api.ElectionsQuery;
import com.hatterassoftware.voterguide.api.VoterInfoQuery;
import com.hatterassoftware.voterguide.api.callbacks.ElectionCallback;
import com.hatterassoftware.voterguide.api.callbacks.VoterInfoCallback;
import com.hatterassoftware.voterguide.api.models.Election;
import com.hatterassoftware.voterguide.api.models.VoterInfo;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends SherlockFragmentActivity implements ElectionCallback, VoterInfoCallback {
private ProgressBar mProgressBar;
public Button submit;
public Spinner state;
public Spinner election;
public EditText address;
public EditText city;
public EditText zip;
private int count=0;
private Object lock = new Object();
private static final String TAG = "MainActivity";
public static final String VOTER_INFO = "com.hatterassoftware.voterguide.VOTER_INFO";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressBar = (ProgressBar) findViewById(R.id.home_progressBar);
Resources res = getResources();
SharedPreferences mPrefs = getApplicationSharedPreferences();
ImageButton gpsButton = (ImageButton) findViewById(R.id.locate);
try {
LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
if (!manager.isProviderEnabled(Context.LOCATION_SERVICE)) {
gpsButton.setClickable(false);
}
} catch(Exception e) {
Log.d(TAG, e.getMessage(), e);
gpsButton.setClickable(false);
gpsButton.setEnabled(false);
}
submit = (Button) findViewById(R.id.submit);
submit.setClickable(false);
submit.setEnabled(false);
state = (Spinner) findViewById(R.id.state);
election = (Spinner) findViewById(R.id.election);
address = (EditText) findViewById(R.id.streetAdress);
city = (EditText) findViewById(R.id.city);
zip = (EditText) findViewById(R.id.zip);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
doSubmit();
}
});
gpsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
doLocate();
}
});
// Let's check for network connectivity before we get down to business.
if (Utils.isNetworkAvailable(this, true)) {
// Show the disclaimer on first run.
if(mPrefs.getBoolean("firstRun", true)) {
AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setCancelable(false);
alert.setTitle(res.getString(R.string.welcome));
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog, null);
TextView alertContents = (TextView) layout.findViewById(R.id.custom_dialog_text);
alertContents.setMovementMethod(LinkMovementMethod.getInstance());
alertContents.setText(Html.fromHtml(res.getString(R.string.welcome_dialog_text)));
alert.setView(alertContents);
alert.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences mPrefs = getApplicationSharedPreferences();
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean("firstRun", false);
editor.commit();
dialog.dismiss();
retrieveElections();
}
});
alert.show();
} else {
retrieveElections();
}
}
}
#Override
public void onResume() {
super.onResume();
// Let's check for network connectivity before we get down to business.
Utils.isNetworkAvailable(this, true);
LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
if (!(manager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
Toast.makeText(this, "GPS is not available", 2).show();
ImageButton gpsButton = (ImageButton) findViewById(R.id.locate);
gpsButton.setClickable(false);
}
}
public SharedPreferences getApplicationSharedPreferences() {
Context mContext = this.getApplicationContext();
return mContext.getSharedPreferences("com.hatterassoftware.voterguide", MODE_PRIVATE);
}
private void showSpinner() {
synchronized(lock) {
count++;
mProgressBar.setVisibility(View.VISIBLE);
}
}
private void hideSpinner() {
synchronized(lock) {
count--;
if(count < 0) { // Somehow we're trying to hide it more times than we've shown it.
count=0;
}
if (count == 0) {
mProgressBar.setVisibility(View.INVISIBLE);
}
}
}
public void retrieveElections() {
Log.d(TAG, "Retrieving the elections");
showSpinner();
ElectionsQuery query = new ElectionsQuery(this);
}
#Override
public void retrievedElection(Election... elections) {
Log.d(TAG, "Retrieved the elections");
hideSpinner();
for (int i=0; i<elections.length; i++) {
Log.d(TAG, elections[i].toString());
}
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, elections);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner spinner = (Spinner) this.findViewById(R.id.election);
spinner.setAdapter(arrayAdapter);
}
}