Google Glass: Can't swipe between cards in immersion - java

My problem is I've created an immersion activity with several cards in it. When I try and swipe between the cards, nothing happens. I can swipe down to end the activity, but I can't swipe between cards. The funny thing is if I let the glass go to sleep and then wake it up again, I can then swipe between cards. Because of this oddity, I'm pretty sure I'm missing one line of code that gives the cards focus or something, but I don't know what it is.
I've found a workaround using a gesture detector, but it doesn't look like normal swiping, so I'd like to avoid that. My code is below:
package com.akqa.glass.recipie;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.TextView;
import com.google.android.glass.media.Sounds;
import com.google.android.glass.view.WindowUtils;
import com.google.android.glass.widget.CardBuilder;
import com.google.android.glass.widget.CardScrollAdapter;
import com.google.android.glass.widget.CardScrollView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.List;
/**
* Created by torti_000 on 11/29/2014.
*/
public class PairingsActivity extends Activity {
private CardAdapter mAdapter;
private CardScrollView mCardScroller;
private int mTapPosition;
private final Handler handler = new Handler();
private boolean mVoiceMenuEnabled = true;
private String ingredientUrl = null;
private static final String TAG = "Ingredients";
private static final String URL_BASE = "http://www.ingredientpairings.com/?i=";
private ArrayList<String> iList;
//Number of ingredients to display per card.
private static final int ITEMS_PER_CARD = 4;
private int numCards;
String object = null;
Context context;
private View mView;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//Loading
mView = buildView();
mCardScroller = new CardScrollView(this);
mCardScroller.setAdapter(new CardScrollAdapter() {
#Override
public int getCount() {
return 1;
}
#Override
public Object getItem(int position) {
return mView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return mView;
}
#Override
public int getPosition(Object item) {
if (mView.equals(item)) {
return 0;
}
return AdapterView.INVALID_POSITION;
}
});
setContentView(mCardScroller);
Log.d(TAG, "View has been set");
mCardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Plays sound.
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.playSoundEffect(Sounds.TAP);
}
});
//Recipes
iList = new ArrayList<String>();
context = this;
Intent pairings = getIntent();
object = pairings.getStringExtra("Object");
Log.i(TAG, "Pairings thinks object is: " + object);
new GetIngredients().execute(object);
}
/**
* Create Loding Page
*/
private View buildView() {
Log.d(TAG, "Creating Loading Card");
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
card.setText("Loading");
return card.getView();
}
/**
* Creates list of cards that showcase different type of {#link com.google.android.glass.widget.CardBuilder} API.
*/
private List<CardBuilder> createCards(Context context) {
ArrayList<CardBuilder> cards = new ArrayList<CardBuilder>();
Log.i(TAG, "Creating Cards");
/*
* One ingredient per card...
*/
for(int i = 0; i < iList.size(); i++){
cards.add(new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText(iList.get(i)));
Log.d(TAG, "Ingredient is: " + iList.get(i));
}
Log.d(TAG, "Done adding pairings?");
return cards;
}
#Override
protected void onResume() {
super.onResume();
mCardScroller.activate();
}
#Override
protected void onPause() {
mCardScroller.deactivate();
super.onPause();
}
public class GetIngredients extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... strings) {
StringBuffer buffer = new StringBuffer();
try {
ingredientUrl = object.replaceAll(" ", "+");
Log.d(TAG, ingredientUrl);
// strings[0].replaceAll(" ", "+");
Log.d(TAG, "Finding matches for " + object);
Document doc = Jsoup.connect(URL_BASE + ingredientUrl).get();
Log.d(TAG, "Matches found for " + object);
Elements ingredients = doc.select("div.main p b");
// Log.d(TAG, "Ingredients are: " + ingredients.toString());
for (Element ingredient : ingredients) {
String data = ingredient.text();
iList.add(data);
buffer.append("Data [" + data + "] \r\n");
Log.d(TAG, "Ingredient is: " + data);
}
}
catch(Throwable t) {
t.printStackTrace();
}
return buffer.toString();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
// Compute the number of cards needed to display the items with 4 per card (rounding up to
// capture the remainder).
numCards = (int) Math.ceil((double) iList.size() / ITEMS_PER_CARD);
startCards();
}
}
private void startCards(){
mAdapter = new CardAdapter(createCards(this));
// mCardScroller = new CardScrollView(this);
mCardScroller.setAdapter(mAdapter);
setContentView(mCardScroller);
}
}

In your onCreate(), add this line before the setContentView() like this:
mCardScroller.activate(); //add this line
setContentView(mCardScroller);
You had this line in your onResume() and that's why it is behaving as is.

I had a problem where I was switching the content view between a CardScrollView and a SurfaceView. After I made sure that onPause() and onResume() were both called in the logically correct places, the scroller was fine.
It seems like if the CardScrollView has lost focus then the scroller loses functionality and calling .activate() only works if .deactivate() has been called beforehand, hence why both onPause() and onResume() need to both be called in the logically correct places as .deactivate() is called within onPause() and .activate() is called within onResume(). I tried just calling .deactivate() and .activate() on their own instead of onPause() and onResume() and the behaviour was the same in both instances, supporting what I have written here.
So, in short, if switching between views with setContentView(), be sure to call onPause() before the switch and onResume() after the switch otherwise the scroller will stop responding.

Related

how i can run the onNavigationItemSelected method in background thread

The app crashes when I write mNavigationView.setNavigationItemSelectedListener(this); in the code
and if it is not added it removes the functionality of the item in the navigation bar. Which method I should run in a background thread to reduce the effect on the main thread.
import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.eggheadgames.aboutbox.AboutConfig;
import com.eggheadgames.aboutbox.IAnalytic;
import com.eggheadgames.aboutbox.IDialog;
import com.eggheadgames.aboutbox.activity.AboutActivity;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class EarthquakeActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener, SwipeRefreshLayout.OnRefreshListener, LoaderManager.LoaderCallbacks<List<Earthquake>>, NavigationView.OnNavigationItemSelectedListener {
public static final String MyPrefs = "MyPrefs";
private DrawerLayout mdrawerlayout;
private ActionBarDrawerToggle mToogle;
/** URL for earthquake data from the USGS dataset */
private static final String USGS_REQUEST_URL = "https://earthquake.usgs.gov/fdsnws/event/1/query";
/**
* Constant value for the earthquake loader ID. We can choose any integer.
* This really only comes into play if you're using multiple loaders.
*/
private static final int EARTHQUAKE_LOADER_ID = 1;
/** Adapter for the list of earthquakes */
private EarthquakeAdapter mAdapter;
/** TextView that is displayed when the list is empty */
private TextView mEmptyStateTextView;
SwipeRefreshLayout swipe;
private static final String LOG_TAG = EarthquakeActivity.class.getSimpleName();
private ListView earthquakeListView;
private static final String TWITTER_USER_NAME = "vaibhav_khulbe";
private static final String WEB_HOME_PAGE = "https://about.me/vaibhav_khulbe";
private static final String APP_PUBLISHER = "https://play.google.com/store/apps/developer?id=Vaibhav%20Khulbe&hl=en";
private static final String EMAIL_ADDRESS = "khulbevaibhavdev#gmail.com";
private static final String EMAIL_SUBJECT = "Quake Info app acknowledgements and/or issues";
private static final String EMAIL_BODY = "Please explain your experience with this app here...This may include bugs" +
" or issues you may be facing or what you liked about the app along with improvements. :) (MAKE SURE to clear out these lines before sending the mail to us)";
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake_activity);
mdrawerlayout=(DrawerLayout)findViewById(R.id.drawer);
mToogle=new ActionBarDrawerToggle(this,mdrawerlayout,R.string.open,R.string.close);
mdrawerlayout.addDrawerListener(mToogle);
mToogle.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
NavigationView mNavigationView=(NavigationView)findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(this);
swipe = findViewById(R.id.swiperefresh);
swipe.setOnRefreshListener(this);
swipe.setColorSchemeColors(getResources().getColor(R.color.colorAccent));
/* Start the intro only once */
SharedPreferences sp = getSharedPreferences(MyPrefs, Context.MODE_PRIVATE);
if (!sp.getBoolean("first", false)) {
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("first", true);
editor.apply();
Intent intent = new Intent(this, IntroActivity.class);
startActivity(intent);
}
//Call and launch About activity
initAboutActivity();
// Find a reference to the {#link ListView} in the layout
earthquakeListView = (ListView) findViewById(R.id.list);
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
earthquakeListView.setEmptyView(mEmptyStateTextView);
// Create a new adapter that takes an empty list of earthquakes as input
mAdapter = new EarthquakeAdapter(this, new ArrayList<Earthquake>());
// Set the adapter on the {#link ListView}
// so the list can be populated in the user interface
earthquakeListView.setAdapter(mAdapter);
// Obtain a reference to the SharedPreferences file for this app
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
// And register to be notified of preference changes
// So we know when the user has adjusted the query settings
prefs.registerOnSharedPreferenceChangeListener(this);
// Set an item click listener on the ListView, which sends an intent to a web browser
// to open a website with more information about the selected earthquake.
earthquakeListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Find the current earthquake that was clicked on
Earthquake currentEarthquake = mAdapter.getItem(position);
// Convert the String URL into a URI object (to pass into the Intent constructor)
Uri earthquakeUri = Uri.parse(currentEarthquake.getUrl());
// Create a new intent to view the earthquake URI
Intent websiteIntent = new Intent(Intent.ACTION_VIEW, earthquakeUri);
// Send the intent to launch a new activity
startActivity(websiteIntent);
}
});
getSupportLoaderManager().initLoader(EARTHQUAKE_LOADER_ID, null, this);
}
/*Code to launch About activity */
public void initAboutActivity()
{
/* Create About activity */
AboutConfig aboutConfig = AboutConfig.getInstance();
aboutConfig.appName = getString(R.string.app_name);
aboutConfig.appIcon = R.mipmap.ic_launcher;
aboutConfig.version = "1.0.0";
aboutConfig.author = "Vaibhav Khulbe";
aboutConfig.aboutLabelTitle = "About";
aboutConfig.packageName = getApplicationContext().getPackageName();
aboutConfig.appPublisher = APP_PUBLISHER;
aboutConfig.twitterUserName = TWITTER_USER_NAME;
aboutConfig.webHomePage = WEB_HOME_PAGE;
aboutConfig.dialog = new IDialog() {
#Override
public void open(AppCompatActivity appCompatActivity, String url, String tag) {
// handle custom implementations of WebView. It will be called when user click to web items. (Example: "Privacy", "Acknowledgments" and "About")
}
};
aboutConfig.analytics = new IAnalytic() {
#Override
public void logUiEvent(String s, String s1) {
// handle log events.
}
#Override
public void logException(Exception e, boolean b) {
// handle exception events.
}
};
// set it only if aboutConfig.analytics is defined.
aboutConfig.logUiEventName = "Log";
// Contact Support email details
aboutConfig.emailAddress = EMAIL_ADDRESS;
aboutConfig.emailSubject = EMAIL_SUBJECT;
aboutConfig.emailBody = EMAIL_BODY;
aboutConfig.shareMessage = getString(R.string.share_message);
aboutConfig.sharingTitle = getString(R.string.sharing_title);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(getString(R.string.settings_min_magnitude_key)) ||
key.equals(getString(R.string.settings_order_by_key))){
// Clear the ListView as a new query will be kicked off
mAdapter.clear();
// Hide the empty state text view as the loading indicator will be displayed
mEmptyStateTextView.setVisibility(View.GONE);
// Show the loading indicator while new data is being fetched
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.VISIBLE);
// Restart the loader to requery the USGS as the query settings have been updated
getSupportLoaderManager().restartLoader(EARTHQUAKE_LOADER_ID, null, this);
}
}
#Override
public Loader<List<Earthquake>> onCreateLoader(int i, Bundle bundle) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
String minMagnitude = sharedPrefs.getString(
getString(R.string.settings_min_magnitude_key),
getString(R.string.settings_min_magnitude_default));
String orderBy = sharedPrefs.getString(
getString(R.string.settings_order_by_key),
getString(R.string.settings_order_by_default)
);
String region = sharedPrefs.getString(
getString(R.string.settings_narrow_by_region_key),
getString(R.string.settings_narrow_by_region_default)
);
String radius = sharedPrefs.getString(
getString(R.string.settings_maximum_radius_key),
getString(R.string.settings_maximum_radius_default)
);
List<Country> countries = new ArrayList<>();
try {
countries = Utils.generateCountryList(this);
} catch (IOException e) {
e.printStackTrace();
}
Double latitude = 0.0;
Double longitude = 0.0;
for (Country country : countries) {
if(country.getName().equalsIgnoreCase(region)){
latitude = country.getLatitude();
longitude = country.getLongitude();
}
}
Uri baseUri = Uri.parse(USGS_REQUEST_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendQueryParameter("format", "geojson");
uriBuilder.appendQueryParameter("limit", "100");
uriBuilder.appendQueryParameter("minmag", minMagnitude);
uriBuilder.appendQueryParameter("orderby", orderBy);
if(latitude != 0.0 && longitude != 0.0){
uriBuilder.appendQueryParameter("latitude", String.valueOf(latitude.intValue()));
uriBuilder.appendQueryParameter("longitude", String.valueOf(longitude.intValue()));
uriBuilder.appendQueryParameter("maxradius", radius);
}
String url = uriBuilder.toString();
return new EarthquakeLoader(this, url);
}
#Override
public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes) {
swipe.setRefreshing(false);
// Hide loading indicator because the data has been loaded
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
if (earthquakes != null && !earthquakes.isEmpty()) {
this.showResults(earthquakes);
} else {
this.hideResults();
}
}
#Override
public void onLoaderReset(Loader<List<Earthquake>> loader) {
// Loader reset, so we can clear out our existing data.
mAdapter.clear();
}
/**
* method to show results
*/
private void showResults(List<Earthquake> earthquakeList) {
mAdapter.clear();
earthquakeListView.setVisibility(View.VISIBLE);
mEmptyStateTextView.setVisibility(View.GONE);
mAdapter.setNotifyOnChange(false);
mAdapter.setNotifyOnChange(true);
mAdapter.addAll(earthquakeList);
}
/**
* method to hide results also checks internet connection
*/
private void hideResults() {
earthquakeListView.setVisibility(View.GONE);
mEmptyStateTextView.setVisibility(View.VISIBLE);
// Get a reference to the ConnectivityManager to check state of network connectivity
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
mEmptyStateTextView.setText(R.string.no_earthquakes);
Log.e(LOG_TAG, "no earthquakes data");
} else {
mEmptyStateTextView.setText(R.string.no_internet_connection);
Log.e(LOG_TAG, "no internet");
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mToogle.onOptionsItemSelected(item)){
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onRefresh() {
getSupportLoaderManager().restartLoader(EARTHQUAKE_LOADER_ID, null, this);
Toast.makeText(this, R.string.list_refreshed, Toast.LENGTH_SHORT).show();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
return true;
}
if (id == R.id.action_about) {
Intent actionIntent = new Intent(this, AboutActivity.class);
startActivity(actionIntent);
return true;
}
if (id == R.id.action_did_you_feel_it){
Intent feelItIntent = new Intent(this, DidYouFeel.class);
startActivity(feelItIntent);
return true;
}
if (id == R.id.action_more_apps){
Uri uri = Uri.parse( "https://play.google.com/store/apps/developer?id=Vaibhav+Khulbe" );
startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
}
if (id == R.id.fork_project){
Uri uri = Uri.parse( "https://github.com/Kvaibhav01/Quake-Info" );
startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
}
if (id == R.id.notification){
Intent notificationIntent = new Intent(this, EarthquakeNotification.class);
startActivity(notificationIntent);
}
return true;
}
}
I think it can be done by running the method in a background thread but I am not sure how to do that. Thanks for helping
you can use sample code like this:
((MainActivity)context).runOnUiThread(new Runnable() {
public void run() {
//run another thread
}
});
or if you are familiar with RxJava you can use it.
consider that most of the time you should perform a function that you will call it after the click, not the click method.

Recycler View Showing Only One Item

Ok, so I was recently working on a small project for my own personal preference, and along the way I implemented a small bit of code that did not work. So, as most people would do, I deleted it. But later, I experienced the same glitch that the code prior was causing, but when I checked, it was not there! I may just be plain stupid, blind, or maybe both, but I keep getting only one card in the recyclerView to show up! Feel free to call me stupid if you can find an answer, and I thank you very much in advance.
P.S. Yes, I am very new to Java, so remember this before you decide to roast me.
My MainActivity:
package com.example.whateverthefuckyouwant;
//Imports, in case you couldn't tell
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.api.GoogleApiClient;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.*;
import android.Manifest;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
GoogleAccountCredential mCredential;
ProgressDialog mProgress;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = {SheetsScopes.SPREADSHEETS_READONLY };
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
//ArrayList holding data from the Google Sheets API
ArrayList<Team> teamAF;
//Number of cards that the user has cycled through
int cardNumber = 1;
//Integers for direction of swipe. 8 = Right, 4 = Left
int RIGHT = 8;
int LEFT = 4;
boolean first = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize credentials and service object.
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
//Create Recycler View
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
//Specific size of Cards
mRecyclerView.setHasFixedSize(true);
//Design choices using LinearLayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//Create teamAF array list
teamAF = new ArrayList<>();
//Ads another card, so as to make an infinite number of cards
teamAF.add(new Team());
//Creating and setting mAdapter with teamAF
mAdapter = new MyAdapter(teamAF);
mRecyclerView.setAdapter(mAdapter);
//Swipe code for cardView
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
//Don't know what onMove does
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Toast.makeText(MainActivity.this, "on Move", Toast.LENGTH_SHORT).show();
return false;
}
// Direction 4 = left, Direction 8 = right
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
//Prints swipeDir integer into console
Log.e(".", swipeDir + "");
//Sets variables to null, so they can be reset later
Team t = null;
//String s is reset to a string of code that enables it to check the string in the API with your answer.
String s = "";
//Code for answer. swipeDir == Left(4); Right(8).
if (swipeDir == LEFT) {
//Sets s
s = ((TextView) viewHolder.itemView.findViewById(R.id.left)).getText().toString();
} else if (swipeDir == RIGHT) {
//checks the answer swiped with he API
s = ((TextView) viewHolder.itemView.findViewById(R.id.right)).getText().toString();
}
//Removes card from array
t = teamAF.remove(mRecyclerView.getChildAdapterPosition(viewHolder.itemView));
//Adds some nice animation effect
mAdapter.notifyItemRemoved(mRecyclerView.getChildAdapterPosition(viewHolder.itemView));
//Sends a toast message saying "correct" or "incorrect"
if(t.checkAnswer(s)) {
Toast.makeText(MainActivity.this, "Correct!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Incorrect!", Toast.LENGTH_SHORT).show();
}
if(first) {
//This make the recyclerView shuffle
Collections.shuffle(teamAF, new Random());
first = false;
}
//Adding one, so the cards can go on forever
cardNumber++;
//Calls the methods
mAdapter = new MyAdapter(teamAF);
mRecyclerView.setAdapter(mAdapter);
//This is a 'benchmark' type 'achievement'
if (cardNumber == 50) {
Toast.makeText(getApplicationContext(), "You Reached 50 Points Without Losing! You're Doing Great!", Toast.LENGTH_SHORT).show();
} else if (cardNumber == 100) {
Toast.makeText(getApplicationContext(), "You Reached 100 Points Without Losing! You're A Genius!", Toast.LENGTH_SHORT).show();
}
}
};
//Allows the swiping inside the recyclerView
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
//Calls the google API
mProgress = new ProgressDialog(this);
mProgress.setMessage("Loading...");
getResultsFromApi();
}
//The green was commented from the site
/**
* Attempt to call the API, after verifying that all the preconditions are
* satisfied. The preconditions are: Google Play Services installed, an
* account was selected and the device currently has online access. If any
* of the preconditions are not satisfied, the app will prompt the user as
* appropriate.
*/
private void getResultsFromApi() {
if (! isGooglePlayServicesAvailable()) {
acquireGooglePlayServices();
} else if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else if (! isDeviceOnline()) {
System.out.println("No network connection available.");
} else {
new MakeRequestTask(mCredential).execute();
}
}
/**
* Attempts to set the account used with the API credentials. If an account
* name was previously saved it will use that one; otherwise an account
* picker dialog will be shown to the user. Note that the setting the
* account to use with the credentials object requires the app to have the
* GET_ACCOUNTS permission, which is requested here if it is not already
* present. The AfterPermissionGranted annotation indicates that this
* function will be rerun automatically whenever the GET_ACCOUNTS permission
* is granted.
*/
#AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void chooseAccount() {
if (EasyPermissions.hasPermissions(
this, Manifest.permission.GET_ACCOUNTS)) {
String accountName = getPreferences(Context.MODE_PRIVATE)
.getString(PREF_ACCOUNT_NAME, null);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
} else {
// Start a dialog from which the user can choose an account
startActivityForResult(
mCredential.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
} else {
// Request the GET_ACCOUNTS permission via a user dialog
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account (via Contacts).",
REQUEST_PERMISSION_GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS);
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* #param requestCode code indicating which activity result is incoming.
* #param resultCode code indicating the result of the incoming
* activity result.
* #param data Intent (containing result data) returned by incoming
* activity result.
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
} else {
getResultsFromApi();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == RESULT_OK) {
getResultsFromApi();
}
break;
}
}
/**
* Respond to requests for permissions at runtime for API 23 and above.
* #param requestCode The request code passed in
* requestPermissions(android.app.Activity, String, int, String[])
* #param permissions The requested permissions. Never null.
* #param grantResults The grant results for the corresponding permissions
* which is either PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
*/
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(
requestCode, permissions, grantResults, this);
}
/**
* Callback for when a permission is granted using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Callback for when a permission is denied using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Checks whether the device currently has a network connection.
* #return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date.
* #return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
return connectionStatusCode == ConnectionResult.SUCCESS;
}
/**
* Attempt to resolve a missing, out-of-date, invalid or disabled Google
* Play Services installation via a user dialog, if possible.
*/
private void acquireGooglePlayServices() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
}
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* #param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
Dialog dialog = apiAvailability.getErrorDialog(
MainActivity.this,
connectionStatusCode,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Google Sheets API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.sheets.v4.Sheets mService = null;
private Exception mLastError = null;
MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.sheets.v4.Sheets.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Sheets API Android Quickstart")
.build();
}
/**
* Background task to call Google Sheets API.
* #param params no parameters needed for this task.
*/
#Override
protected List<String> doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of names and majors of students in a sample spreadsheet:
* https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
* #return List of names and majors
*/
private List<String> getDataFromApi() throws IOException {
String spreadsheetId = "1KlflsDsBn0lhGT87OuRuy_RGOuBP2jBU5zpqn_UIYT0";
String range = "Sheet1!A2:B";
List<String> results = new ArrayList<String>();
ValueRange response = this.mService.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
for (List row : values) {
//Obtains the row from the Google Sheet
teamAF.add(new Team(row.get(0).toString(), row.get(1).toString()));
}
//Shuffle the cards with the data on them.
Collections.shuffle(teamAF, new Random());
/*for(String s : results) {
Log.e("HERE", s);
}*/
return results;
}
#Override
protected void onPreExecute() {
//mOutputText.setText("");
mProgress.show();
}
#Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
//mOutputText.setText("No results returned.");
} else {
output.add(0, "Data retrieved using the Google Sheets API:");
//mOutputText.setText(TextUtils.join("\n", output));
}
}
#Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
MainActivity.REQUEST_AUTHORIZATION);
} else {
//mOutputText.setText("The following error occurred:\n"
//+ mLastError.getMessage());
}
} else {
//mOutputText.setText("Request cancelled.");
}
}
}
}
My Adapter:
package com.example.whateverthefuckyouwant;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
/**
* Created by ebuttikofer20 on 1/20/17.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<Team> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public TextView left;
public TextView right;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.info_text);
left = (TextView) v.findViewById(R.id.left);
right = (TextView) v.findViewById(R.id.right);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<Team> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your data at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset.get(position).getTeamName());
Random gen = new Random();
if(gen.nextBoolean()) {
lefter = mDataset.get(position).getTeamNumber();
righter = mDataset.get(gen.nextInt(mDataset.size())).getTeamNumber();
holder.left.setText(lefter);
holder.right.setText(righter);
} else {
righter = mDataset.get(
position).getTeamNumber();
lefter = mDataset.get(gen.nextInt(mDataset.size())).getTeamNumber();
holder.right.setText(righter);
holder.left.setText(lefter);
}
}
String righter;
String lefter;
public String getLeft() {
return lefter;
}
public String getRighter() {
return righter;
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
set your parent layout's height in your R.layout.my_text_view file to wrap_content
I had the same challenge but i had to set my parent layout height to android:layout_height="wrap_content"
That worked for me so well

Remove Duplicate Contacts in custom listview

I am using https://trinitytuts.com/get-contact-list-and-show-in-custom-listview-android/# tutorial to get contact list in list view. It is working fine but giving duplicate contacts. Can some one guide over this to resolve and get contact once only in the listview.
Code for Mainactivity is as below:
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
// ArrayList
ArrayList<SelectUser> selectUsers;
List<SelectUser> temp;
// Contact List
ListView listView;
// Cursor to load contacts list
Cursor phones, email;
// Pop up
ContentResolver resolver;
SearchView search;
SelectUserAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
selectUsers = new ArrayList<SelectUser>();
resolver = this.getContentResolver();
listView = (ListView) findViewById(R.id.contacts_list);
phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
LoadContact loadContact = new LoadContact();
loadContact.execute();
search = (SearchView) findViewById(R.id.searchView);
//*** setOnQueryTextListener ***
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
adapter.filter(newText);
return false;
}
});
}
// Load data on background
class LoadContact extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
// Get Contact list from Phone
if (phones != null) {
Log.e("count", "" + phones.getCount());
if (phones.getCount() == 0) {
Toast.makeText(MainActivity.this, "No contacts in your contact list.", Toast.LENGTH_LONG).show();
}
while (phones.moveToNext()) {
Bitmap bit_thumb = null;
String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String EmailAddr = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA2));
String image_thumb = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI));
try {
if (image_thumb != null) {
bit_thumb = MediaStore.Images.Media.getBitmap(resolver, Uri.parse(image_thumb));
} else {
Log.e("No Image Thumb", "--------------");
}
} catch (IOException e) {
e.printStackTrace();
}
SelectUser selectUser = new SelectUser();
selectUser.setThumb(bit_thumb);
selectUser.setName(name);
selectUser.setPhone(phoneNumber);
selectUser.setEmail(id);
selectUser.setCheckedBox(false);
selectUsers.add(selectUser);
}
} else {
Log.e("Cursor close 1", "----------------");
}
//phones.close();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
adapter = new SelectUserAdapter(selectUsers, MainActivity.this);
listView.setAdapter(adapter);
// Select item on listclick
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.e("search", "here---------------- listener");
SelectUser data = selectUsers.get(i);
}
});
listView.setFastScrollEnabled(true);
}
}
#Override
protected void onStop() {
super.onStop();
phones.close();
}
}
Why not use a Set?Try storing your contacts in a an Object and that Object in a Set. Remember to override the equals method of that Object based on which you need to eliminate duplicates.
More reading here
http://www.java2novice.com/java-collections-and-util/hashset/duplicate/
You're seeing duplicate contacts because you're querying over a list of phones, not contacts, if a contact has more then one phone, you'll get the same contact multiple times - one for each phone number.
You need to decide how you want to handle contacts with multiple phones, and also contacts without any phone (currently you're not displaying contacts that don't have any phone).
Assuming you want one line per contact, displaying only contacts that have phones, and displaying all phones for that contact on the same row, you'll need to revise your code a bit:
The SelectUser object should accept a list of phones, not just one.
the selectUsers field should be HashMap<Long, SelectUser> and not ArrayList<SelectUser>
String id = ... should actually be Long id = ...
Then in your cursor iterator do this:
if (selectUsers.containsKey(id)) {
SelectUser selectUser = selectUsers.get(id);
selectUser.addPhone(phoneNumber); // new method you need to implement
} else {
SelectUser selectUser = new SelectUser();
selectUser.setThumb(bit_thumb);
selectUser.setName(name);
selectUser.setPhone(phoneNumber);
selectUser.setEmail(id); // Email can't be retrieved from the phones table, see below
selectUser.setCheckedBox(false);
selectUsers.add(selectUser);
}
P.S.
You can't read CommonDataKinds.Email fields when querying the CommonDataKinds.Phone table, if you want to read both phones and emails on the same query, you need to query over the ContactsContract.Data table, and select for Data.MIMETYPE + ' = ' + Phone.CONTENT_TYPE + ' OR ' + Data.MIMETYPE + ' = ' + Email.CONTENT_TYPE.
This will give you a cursor over lines that are either phone or email (you can use the Data.MIMETYPE to check which one is it.
See more info here: https://developer.android.com/reference/android/provider/ContactsContract.Data.html
https://stackoverflow.com/a/31864811/819355

Google recognizer and pocketsphinx in two different classes, how to loop them?

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.

Android String reference to shared preferences cannot be iterated?

So I have an ArrayList named locationsList. I also have SharedPreferences that hold a city name which was set in the previous activity which i want to add onto my ArrayList. BUT I want to add it with a ">" at the end of it. So for example
SharedPreferences prefs = getActivity().getSharedPreferences("prefs", 0);
locationsList.add(0, prefs.getString("city", "no city") + ">");
However it does not change!!!. the ">" Isn't added. I even tried adding it when i set the text of the textView.
TextView tv...;
tv.setText(locationsList.get(0) + ">");
I dont understand why it cant change. Obviously the array list is holding a reference to the preferences and that cannot change. But I even tried assigning the preferences to a string variable and then iterating it, it doesn't budge. Can anyone help me
Async in activity
class getLocationsUrl extends AsyncTask<String, String, String> {
ArrayList<String> tempList = new ArrayList<String>();
#Override
protected String doInBackground(String... arg0) {
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("city", prefs.getString("city", "durban")));
JSONParser parser = new JSONParser();
JSONObject json = parser.makeHttpRequest(IMAGE_URL + "fetchlocations.php", "POST",
params);
try {
list = json.getJSONArray("posts");
for(int i = 0; i < list.length(); i++) {
JSONObject c = list.getJSONObject(i);
String location = c.getString("location");
tempList.add(location);
Log.d("async trend", trendList.get(0));
}
Log.d("Got list", imageUrl.get(0) + " " + trendList.get(0));
} catch(JSONException je) {
Log.d("json exception", "json exception");
je.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
locationsList = tempList;
locationsFragment.updateAdapter();
feedFragment.updateHeadingAdapter();
}
}
FeedFragment set up in onCreateView
headingPager = (ViewPager) view.findViewById(R.id.headingPager);
headingList = (ArrayList<String>) NightWatch.locationsList.clone();
added = prefs.getString("city", "makaka");
headingList.add(0, added + ">");
headingAdapter = new CustomHeadingPagerAdapter(getChildFragmentManager());
headingPager.setAdapter(headingAdapter);
FeedFragments CustomHeadingAdapter
public class CustomHeadingPagerAdapter extends FragmentPagerAdapter {
public CustomHeadingPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
#Override
public Fragment getItem(int arg0) {
return HeadingFragment.newInstance(arg0, headingList);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return headingList.size();
}
}
FeedFragment's updateHeadingAdapter() called from the Async
public void updateHeadingAdapter() {
headingList = (ArrayList<String>) NightWatch.locationsList.clone();
headingList.add(0, (prefs.getString("city", "null") + ">"));
headingAdapter = new CustomHeadingPagerAdapter(getChildFragmentManager());
headingPager.setAdapter(headingAdapter);
}
And finally the HeadingFragment that I return in the adapter.
package info.nightowl.nightowl;
import java.util.ArrayList;
import com.example.nightowl.R;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class HeadingFragment extends Fragment{
int position;
Typeface font;
ArrayList<String> list;
SharedPreferences prefs;
static HeadingFragment newInstance(int position, ArrayList<String> list) {
final HeadingFragment f = new HeadingFragment();
Bundle args = new Bundle();
args.putInt("position", position);
args.putStringArrayList("list", list);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
position = getArguments().getInt("position");
list = getArguments().getStringArrayList("list");
prefs = getActivity().getSharedPreferences("prefs", 0);
font = Typeface.createFromAsset(getActivity().getAssets(),
"NotCourierSans.ttf");
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.heading_viewpage_layout, null);
TextView tv = (TextView) v.findViewById(R.id.headingText);
if(position == 0) tv.setText(">" + list.get(position) + ">");
else tv.setText(list.get(position) + ">");
tv.setTypeface(font);
tv.setTextColor(Color.YELLOW);
tv.setTextSize(30);
return v;
}
}
I got it. Always remember when iterating to a string text vi you set it to be a single line in the xml so...
android:singleLine="true"
Kind of a dumb mistake really

Categories