Mobile Vision Searching cameraSource detections for items in a list - ocr

I am currently trying to write an android app in which a user can blacklist any food ingredients he or she wants to avoid. The user should then be able to scan a label and instantly be told whether or not any blacklisted ingredients are found via text recognition.
I am using a cameraSource to detect the text in real time which appears to somewhat work, but only when very few words are present on screen. When there are too many words on screen, it cannot find anything.
What is going wrong when larger amounts of words are present?
private SurfaceView cameraView;
private TextView textView;
private CameraSource cameraSource;
private const int RequestCameraPermissionID = 1001;
public JavaList<string> userIngredients;
public ISharedPreferences pref;
public ISharedPreferencesEditor edit;
public Bitmap imageBitmap;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.ScanLayout);
cameraView = FindViewById<SurfaceView>(Resource.Id.surface_view);
textView = FindViewById<TextView>(Resource.Id.text_view);
pref = Application.Context.GetSharedPreferences("UserPrefs", FileCreationMode.Private);
edit = pref.Edit();
var preferences = pref.GetStringSet("UserPrefs", new JavaList<string>());
userIngredients = new JavaList<string>(preferences);
var bitmapOptions = new BitmapFactory.Options();
TextRecognizer textRecognizer = new TextRecognizer.Builder(ApplicationContext).Build();
if (!textRecognizer.IsOperational)
{
Log.Error("Main Activity", "Detector dependancies are not yet available");
}
else
{
cameraSource = new CameraSource.Builder(ApplicationContext, textRecognizer)
.SetFacing(CameraFacing.Back)
.SetRequestedFps(2.0f)
.SetAutoFocusEnabled(true)
.Build();
cameraView.Holder.AddCallback(this);
textRecognizer.SetProcessor(this);
}
}
public void SurfaceCreated(ISurfaceHolder holder)
{
if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
{
//Request Permission
ActivityCompat.RequestPermissions(this, new string[] {
Android.Manifest.Permission.Camera
}, RequestCameraPermissionID);
return;
}
cameraSource.Start(cameraView.Holder);
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
cameraSource.Stop();
}
public void ReceiveDetections(Detections detections)
{
bool blackListedFound = false;
SparseArray items = detections.DetectedItems;
if (items.Size() != 0)
{
textView.Post(() =>
{
for (int i = 0; i < items.Size(); ++i)
{
for (int j = 0; j < userIngredients.Size(); j++)
{
if (((TextBlock)items.ValueAt(i)).Value.Equals(userIngredients[j]))
{
blackListedFound = true;
textView.Text = "Not reccomended\nIngredient Found: " + userIngredients[j];
}
}
}
});
}
else if (blackListedFound == false)
textView.Post(() =>
{
textView.Text = "No Ingredients found";
});
}
}
}
Here are some example images of my current problem;
Here is an example of the app failing to find a blacklisted ingredient (Water);

Related

GeoDataApi.getAutocompletePredictions not working

I am building an android application that shows autocomplete feature and fetches autocomplete predictions in google maps using - GeoDataApi.getAutocompletePredictions. I followed this tutorial - https://github.com/googlesamples/android-play-places/blob/master/PlaceComplete/Application/src/main/java/com/example/google/playservices/placecomplete/PlaceAutocompleteAdapter.java
But somehow this is not working fine for me.
My class is this -
public class GooglePlacesAutoCompleteAdapter extends ArrayAdapter implements Filterable {
private ArrayList<PlaceAutocomplete> mResultList;
GoogleApiClient mGoogleApiClient;
private LatLngBounds mBounds;
private AutocompleteFilter mPlaceFilter;
int radius = 500;
public GooglePlacesAutoCompleteAdapter(Context context, int textViewResourceId, GoogleApiClient googleApiClient,
Location lastLocation, AutocompleteFilter filter) {
super(context, textViewResourceId);
LatLng currentLatLng = new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude());
mBounds = Utility.boundsWithCenterAndLatLngDistance(currentLatLng, 500, 500);
mGoogleApiClient = googleApiClient;
mPlaceFilter = filter;
}
#Override
public int getCount() {
return mResultList.size();
}
#Override
public PlaceAutocomplete getItem(int index) {
return mResultList.get(index);
}
#Override
public android.widget.Filter getFilter() {
Filter filter = new Filter() {
#Override
public FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null && constraint.length() > 3 && constraint.length()%3 == 1) {
// Retrieve the autocomplete results.
mResultList = autocomplete(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = mResultList;
filterResults.count = mResultList.size();
}
return filterResults;
}
#Override
public void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
public ArrayList<PlaceAutocomplete> autocomplete(String input) {
if (mGoogleApiClient.isConnected()) {
// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
PendingResult results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, input.toString(),
mBounds, mPlaceFilter);
// This method should have been called off the main UI thread. Block and wait for at most 60s
// for a result from the API.
AutocompletePredictionBuffer autocompletePredictions = (AutocompletePredictionBuffer)results.await(60, TimeUnit.SECONDS);
// Confirm that the query completed successfully, otherwise return null
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
//Toast.makeText(getContext(), "Error contacting API: " + status.toString(),Toast.LENGTH_SHORT).show();
//Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString());
autocompletePredictions.release();
return null;
}
// Copy the results into our own data structure, because we can't hold onto the buffer.
// AutocompletePrediction objects encapsulate the API response (place ID and description).
Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
// Get the details of this prediction and copy it into a new PlaceAutocomplete object.
resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getDescription()));
}
// Release the buffer now that all data has been copied.
autocompletePredictions.release();
return resultList;
}
//Log.e(TAG, "Google API client is not connected for autocomplete query.");
return null;
}
class PlaceAutocomplete {
public CharSequence placeId;
public CharSequence description;
PlaceAutocomplete(CharSequence placeId, CharSequence description) {
this.placeId = placeId;
this.description = description;
}
#Override
public String toString() {
return description.toString();
}
}
}
The line on which GeoDataApi.getAutocompletePredictions is called, goes into an internal classes called - Filter.java, Log.java, handler.java and then Looper.java and loops there indefinetly on line 121 of Looper.java (I am sure studio sdk will show the code for Looper.java).
It is not even throwing an error, or going to the next line, it just does not work. Plus, I am not able to see the stack trace of an error.
This is the code snippet which is calling this -
if (mLastLocation != null) {
GooglePlacesAutoCompleteAdapter placesAdapter = new GooglePlacesAutoCompleteAdapter(this, R.layout.item_list, mGoogleApiClient, mLastLocation, null);
autoCompView.setAdapter(placesAdapter);
autoCompView.setOnItemClickListener(this);
}
Can someone please tell me what I am doing wrong here? Please any help will be greatly appreciated. I need to get this working as soon as I could.
PS - I am passing mPlaceFilter as null here.
Enable the Google Places API for Android in developers console

Facebook SDK Integration - LoadPicture Method ERROR

So hi to #ll this is my fist post/question on stackoverflow :D
I need help # following :
So i integrated the Facebook SDk sucessfully in my game but i´dont get the profile picture working ...
So i tryied it oldshool on Facebooks "Tutotial" Way and followed all steps to implement login functions and so on ...
I´ve downloaded the "friendsmash_start" Sample and implemented that Stuff ...
My Main Problem is i don´t get ahead with this problem and can´t figure out what i´m doing wrong so i´m hoping for help.
Here´s the complete Code from the MainMenu Script from the sample which is the only i´ve changed ... like in the tutorial ...
Unity shows me this Error -> "The name 'LoadPicture' does not exist in the current context ... so the errors are on these two parts of code :
"LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);" in the "OnLoggedIn" function
"LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);" in the "MyPictureCallback" function
I don´t understand it cause i searched myself in the script for this function "LoadPicture" and find nothing that was ... according to the "Tutorial" of facebook here :
https://developers.facebook.com/docs/games/unity/unity-tutorial?locale=de_DE
the function should be there cause they wrote there :
"Take a look at the LoadPicture method also in MainMenu.cs to see how we use the Unity WWW class to load the image returned by the graph API."
But i can´t find it :(
HOPE SOMEONE CAN HELP ME I DON´T GET IT ...
Have that problem unfortunately very long time ... thats enoying. :(
HERE`S THE FULL CODE OF MAINMENU.CS :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Facebook.MiniJSON;
using System;
public class MainMenu : MonoBehaviour
{
// Inspector tunable members //
public Texture ButtonTexture;
public Texture PlayTexture; // Texture for main menu button icons
public Texture BragTexture;
public Texture ChallengeTexture;
public Texture StoreTexture;
public Texture FullScreenTexture;
public Texture FullScreenActiveTexture;
public Texture ResourcesTexture;
public Vector2 CanvasSize; // size of window on canvas
public Rect LoginButtonRect; // Position of login button
public Vector2 ResourcePos; // position of resource indicators (not used yet)
public Vector2 ButtonStartPos; // position of first button in main menu
public float ButtonScale; // size of main menu buttons
public float ButtonYGap; // gap between buttons in main menu
public float ChallengeDisplayTime; // Number of seconds the request sent message is displayed for
public Vector2 ButtonLogoOffset; // Offset determining positioning of logo on buttons
public float TournamentStep; // Spacing between tournament entries
public float MouseScrollStep = 40; // Amount score table moves with each step of the mouse wheel
public PaymentDialog paymentDialog;
public GUISkin MenuSkin;
public int CoinBalance;
public int NumLives;
public int NumBombs;
public Texture[] CelebTextures;
public string [] CelebNames;
// Private members //
private static MainMenu instance;
private static List<object> friends = null;
private static Dictionary<string, string> profile = null;
private static List<object> scores = null;
private static Dictionary<string, Texture> friendImages = new Dictionary<string, Texture>();
private Vector2 scrollPosition = Vector2.zero;
private bool haveUserPicture = false;
private float tournamentLength = 0;
private int tournamentWidth = 512;
private int mainMenuLevel = 0; // Level index of main menu
private string popupMessage;
private float popupTime;
private float popupDuration;
void Awake()
{
Util.Log("Awake");
paymentDialog = ((PaymentDialog)(GetComponent("PaymentDialog")));
// allow only one instance of the Main Menu
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
#if UNITY_WEBPLAYER
// Execute javascript in iframe to keep the player centred
string javaScript = #"
window.onresize = function() {
var unity = UnityObject2.instances[0].getUnity();
var unityDiv = document.getElementById(""unityPlayerEmbed"");
var width = window.innerWidth;
var height = window.innerHeight;
var appWidth = " + CanvasSize.x + #";
var appHeight = " + CanvasSize.y + #";
unity.style.width = appWidth + ""px"";
unity.style.height = appHeight + ""px"";
unityDiv.style.marginLeft = (width - appWidth)/2 + ""px"";
unityDiv.style.marginTop = (height - appHeight)/2 + ""px"";
unityDiv.style.marginRight = (width - appWidth)/2 + ""px"";
unityDiv.style.marginBottom = (height - appHeight)/2 + ""px"";
}
window.onresize(); // force it to resize now";
Application.ExternalCall(javaScript);
#endif
DontDestroyOnLoad(gameObject);
instance = this;
// Initialize FB SDK
FB.Init(SetInit, OnHideUnity);
}
private void SetInit()
{
Util.Log("SetInit");
enabled = true; // "enabled" is a property inherited from MonoBehaviour
if (FB.IsLoggedIn)
{
Util.Log("Already logged in");
OnLoggedIn();
}
}
private void OnHideUnity(bool isGameShown)
{
Util.Log("OnHideUnity");
if (!isGameShown)
{
// pause the game - we will need to hide
Time.timeScale = 0;
}
else
{
// start the game back up - we're getting focus again
Time.timeScale = 1;
}
}
private void QueryScores()
{
FB.API("/app/scores?fields=score,user.limit(20)", Facebook.HttpMethod.GET, ScoresCallback);
}
private int getScoreFromEntry(object obj)
{
Dictionary<string,object> entry = (Dictionary<string,object>) obj;
return Convert.ToInt32(entry["score"]);
}
void ScoresCallback(FBResult result)
{
Util.Log("ScoresCallback");
if (result.Error != null)
{
Util.LogError(result.Error);
return;
}
scores = new List<object>();
List<object> scoresList = Util.DeserializeScores(result.Text);
foreach(object score in scoresList)
{
var entry = (Dictionary<string,object>) score;
var user = (Dictionary<string,object>) entry["user"];
string userId = (string)user["id"];
if (string.Equals(userId,FB.UserId))
{
// This entry is the current player
int playerHighScore = getScoreFromEntry(entry);
Util.Log("Local players score on server is " + playerHighScore);
if (playerHighScore < GameStateManager.Score)
{
Util.Log("Locally overriding with just acquired score: " + GameStateManager.Score);
playerHighScore = GameStateManager.Score;
}
entry["score"] = playerHighScore.ToString();
GameStateManager.HighScore = playerHighScore;
}
scores.Add(entry);
if (!friendImages.ContainsKey(userId))
{
// We don't have this players image yet, request it now
LoadPictureAPI(Util.GetPictureURL(userId, 128, 128),pictureTexture =>
{
if (pictureTexture != null)
{
friendImages.Add(userId, pictureTexture);
}
});
}
}
// Now sort the entries based on score
scores.Sort(delegate(object firstObj,
object secondObj)
{
return -getScoreFromEntry(firstObj).CompareTo(getScoreFromEntry(secondObj));
}
);
}
void OnApplicationFocus( bool hasFocus )
{
Util.Log ("hasFocus " + (hasFocus ? "Y" : "N"));
}
// Convenience function to check if mouse/touch is the tournament area
private bool IsInTournamentArea (Vector2 p)
{
return p.x > Screen.width-tournamentWidth;
}
// Scroll the tournament view by some delta
private void ScrollTournament(float delta)
{
scrollPosition.y += delta;
if (scrollPosition.y > tournamentLength - Screen.height)
scrollPosition.y = tournamentLength - Screen.height;
if (scrollPosition.y < 0)
scrollPosition.y = 0;
}
// variables for keeping track of scrolling
private Vector2 mouseLastPos;
private bool mouseDragging = false;
void Update()
{
if(Input.touches.Length > 0)
{
Touch touch = Input.touches[0];
if (IsInTournamentArea (touch.position) && touch.phase == TouchPhase.Moved)
{
// dragging
ScrollTournament (touch.deltaPosition.y*3);
}
}
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
ScrollTournament (MouseScrollStep);
}
else if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
ScrollTournament (-MouseScrollStep);
}
if (Input.GetMouseButton(0) && IsInTournamentArea(Input.mousePosition))
{
if (mouseDragging)
{
ScrollTournament (Input.mousePosition.y - mouseLastPos.y);
}
mouseLastPos = Input.mousePosition;
mouseDragging = true;
}
else
mouseDragging = false;
}
// Button drawing logic //
private Vector2 buttonPos; // Keeps track of where we've got to on the screen as we draw buttons
private void BeginButtons()
{
// start drawing buttons at the chosen start position
buttonPos = ButtonStartPos;
}
private bool DrawButton(string text, Texture texture)
{
// draw a single button and update our position
bool result = GUI.Button(new Rect (buttonPos.x,buttonPos.y, ButtonTexture.width * ButtonScale, ButtonTexture.height * ButtonScale),text,MenuSkin.GetStyle("menu_button"));
Util.DrawActualSizeTexture(ButtonLogoOffset*ButtonScale+buttonPos,texture,ButtonScale);
buttonPos.y += ButtonTexture.height*ButtonScale + ButtonYGap;
if (paymentDialog.DialogEnabled)
result = false;
return result;
}
void OnGUI()
{
GUI.skin = MenuSkin;
if (Application.loadedLevel != mainMenuLevel) return; // don't display anything except when in main menu
GUILayout.Box("", MenuSkin.GetStyle("panel_welcome"));
if (!FB.IsLoggedIn)
{
GUI.Label((new Rect(179, 11, 287, 160)), "Login to Facebook", MenuSkin.GetStyle("text_only"));
if (GUI.Button(LoginButtonRect, "", MenuSkin.GetStyle("button_login")))
{
FB.Login("email,publish_actions", LoginCallback);
}
}
if (FB.IsLoggedIn)
{
string panelText = "Welcome ";
panelText += (!string.IsNullOrEmpty(GameStateManager.Username)) ? string.Format("{0}!", GameStateManager.Username) : "Smasher!";
if (GameStateManager.UserTexture != null)
GUI.DrawTexture( (new Rect(8,10, 150, 150)), GameStateManager.UserTexture);
GUI.Label( (new Rect(179 , 11, 287, 160)), panelText, MenuSkin.GetStyle("text_only"));
}
string subTitle = "Let's smash some friends!";
if (GameStateManager.Score > 0)
{
subTitle = "Score: " + GameStateManager.Score.ToString();
}
if (!string.IsNullOrEmpty(subTitle))
{
GUI.Label( (new Rect(132, 28, 400, 160)), subTitle, MenuSkin.GetStyle("sub_title"));
}
BeginButtons();
if (DrawButton("Play",PlayTexture))
{
onPlayClicked();
}
if (FB.IsLoggedIn)
{
// Draw resources bar
Util.DrawActualSizeTexture(ResourcePos,ResourcesTexture);
Util.DrawSimpleText(ResourcePos + new Vector2(47,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",CoinBalance));
Util.DrawSimpleText(ResourcePos + new Vector2(137,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",NumBombs));
Util.DrawSimpleText(ResourcePos + new Vector2(227,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",NumLives));
}
#if UNITY_WEBPLAYER
if (Screen.fullScreen)
{
if (DrawButton("Full Screen",FullScreenActiveTexture))
SetFullscreenMode(false);
}
else
{
if (DrawButton("Full Screen",FullScreenTexture))
SetFullscreenMode(true);
}
#endif
DrawPopupMessage();
}
public void AddPopupMessage(string message, float duration)
{
popupMessage = message;
popupTime = Time.realtimeSinceStartup;
popupDuration = duration;
}
public void DrawPopupMessage()
{
if (popupTime != 0 && popupTime + popupDuration > Time.realtimeSinceStartup)
{
// Show message that we sent a request
Rect PopupRect = new Rect();
PopupRect.width = 800;
PopupRect.height = 100;
PopupRect.x = Screen.width / 2 - PopupRect.width / 2;
PopupRect.y = Screen.height / 2 - PopupRect.height / 2;
GUI.Box(PopupRect,"",MenuSkin.GetStyle("box"));
GUI.Label(PopupRect, popupMessage, MenuSkin.GetStyle("centred_text"));
}
}
void TournamentGui()
{
GUILayout.BeginArea(new Rect((Screen.width - 450),0,450,Screen.height));
// Title box
GUI.Box (new Rect(0, - scrollPosition.y, 100,200), "", MenuSkin.GetStyle("tournament_bar"));
GUI.Label (new Rect(121 , - scrollPosition.y, 100,200), "Tournament", MenuSkin.GetStyle("heading"));
Rect boxRect = new Rect();
if(scores != null)
{
var x = 0;
foreach(object scoreEntry in scores)
{
Dictionary<string,object> entry = (Dictionary<string,object>) scoreEntry;
Dictionary<string,object> user = (Dictionary<string,object>) entry["user"];
string name = ((string) user["name"]).Split(new char[]{' '})[0] + "\n";
string score = "Smashed: " + entry["score"];
boxRect = new Rect(0, 121+(TournamentStep*x)-scrollPosition.y , 100,128);
// Background box
GUI.Box(boxRect,"",MenuSkin.GetStyle("tournament_entry"));
// Text
GUI.Label (new Rect(24, 136 + (TournamentStep * x) - scrollPosition.y, 100,128), (x+1)+".", MenuSkin.GetStyle("tournament_position")); // Rank e.g. "1.""
GUI.Label (new Rect(250,145 + (TournamentStep * x) - scrollPosition.y, 300,100), name, MenuSkin.GetStyle("tournament_name")); // name
GUI.Label (new Rect(250,193 + (TournamentStep * x) - scrollPosition.y, 300,50), score, MenuSkin.GetStyle("tournament_score")); // score
Texture picture;
if (friendImages.TryGetValue((string) user["id"], out picture))
{
GUI.DrawTexture(new Rect(118,128+(TournamentStep*x)-scrollPosition.y,115,115), picture); // Profile picture
}
x++;
}
}
else GUI.Label (new Rect(180,270,512,200), "Loading...", MenuSkin.GetStyle("text_only"));
// Record length so we know how far we can scroll to
tournamentLength = boxRect.y + boxRect.height + scrollPosition.y;
GUILayout.EndArea();
}
// React to menu buttons //
private void onPlayClicked()
{
Util.Log("onPlayClicked");
if (friends != null && friends.Count > 0)
{
// Select a random friend and get their picture
Dictionary<string, string> friend = Util.RandomFriend(friends);
GameStateManager.FriendName = friend["first_name"];
GameStateManager.FriendID = friend["id"];
GameStateManager.CelebFriend = -1;
LoadPictureURL(friend["image_url"],FriendPictureCallback);
}
else
{
//We can't access friends
GameStateManager.CelebFriend = UnityEngine.Random.Range(0,CelebTextures.Length - 1);
GameStateManager.FriendName = CelebNames[GameStateManager.CelebFriend];
}
// Start the main game
Application.LoadLevel("GameStage");
GameStateManager.Instance.StartGame();
}
public void SetFullscreenMode (bool on)
{
if (on)
{
Screen.SetResolution (Screen.currentResolution.width, Screen.currentResolution.height, true);
}
else
{
Screen.SetResolution ((int)CanvasSize.x, (int)CanvasSize.y, false);
}
}
public static void FriendPictureCallback(Texture texture)
{
GameStateManager.FriendTexture = texture;
}
delegate void LoadPictureCallback (Texture texture);
IEnumerator LoadPictureEnumerator(string url, LoadPictureCallback callback)
{
WWW www = new WWW(url);
yield return www;
callback(www.texture);
}
void LoadPictureAPI (string url, LoadPictureCallback callback)
{
FB.API(url,Facebook.HttpMethod.GET,result =>
{
if (result.Error != null)
{
Util.LogError(result.Error);
return;
}
var imageUrl = Util.DeserializePictureURLString(result.Text);
StartCoroutine(LoadPictureEnumerator(imageUrl,callback));
});
}
void LoadPictureURL (string url, LoadPictureCallback callback)
{
StartCoroutine(LoadPictureEnumerator(url,callback));
}
void LoginCallback(FBResult result)
{
Util.Log("LoginCallback");
if (FB.IsLoggedIn)
{
OnLoggedIn();
}
}
void OnLoggedIn()
{
Util.Log("Logged in. ID: " + FB.UserId);
// Reqest player info and profile picture
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, APICallback);
LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);
}
void APICallback(FBResult result)
{
Util.Log("APICallback");
if (result.Error != null)
{
Util.LogError(result.Error);
// Let's just try again
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, APICallback);
return;
}
profile = Util.DeserializeJSONProfile(result.Text);
GameStateManager.Username = profile["first_name"];
friends = Util.DeserializeJSONFriends(result.Text);
}
void MyPictureCallback(Texture texture)
{
Util.Log("MyPictureCallback");
if (texture == null)
{
// Let's just try again
LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);
return;`
}
GameStateManager.UserTexture = texture;
}
}
change the word "LoadPicture" for "LoadPictureAPI".
For reference see:
https://github.com/fbsamples/friendsmash-unity/blob/master/friendsmash_payments_start/Assets/Scripts/MainMenu.cs

How to create my own arrayAdapter for listView - Android [duplicate]

This question already has answers here:
BaseAdapter class wont setAdapter inside Asynctask - Android
(4 answers)
Closed 9 years ago.
I am trying to create my own arrayAdapter so I can place multiple textviews inside of a listview. I have searched everywhere and can not find a way to do it. I am new to this and not so sure how to handle it. So far I have an asynctask that gathers 3 strings in a JSON method. These strings are what I want placed in the textViews but I have no idea how to do so, here is my current code.
class loadComments extends AsyncTask<JSONObject, String, JSONObject> {
private ArrayAdapter<String> mAdapter = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
protected JSONObject doInBackground(JSONObject... params) {
JSONObject json2 = CollectComments.collectComments(usernameforcomments, offsetNumber);
return json2;
}
#Override
protected void onPostExecute(JSONObject json2) {
try {
if (json2.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res2 = json2.getString(KEY_SUCCESS);
if(Integer.parseInt(res2) == 1){
JSONArray commentArray = json2.getJSONArray(KEY_COMMENT);
final String comments[] = new String[commentArray.length()];
for ( int i=0; i<commentArray.length(); i++ ) {
comments[i] = commentArray.getString(i);
}
JSONArray numberArray = json2.getJSONArray(KEY_NUMBER);
String numbers[] = new String[numberArray.length()];
for ( int i=0; i<numberArray.length(); i++ ) {
numbers[i] = numberArray.getString(i);
}
JSONArray usernameArray = json2.getJSONArray(KEY_USERNAME);
String usernames[] = new String[usernameArray.length()];
for ( int i=0; i<usernameArray.length(); i++ ) {
usernames[i] = usernameArray.getString(i);
}
ArrayList<String> myList = new ArrayList<String>();
class MyClassAdapter extends ArrayAdapter<String> {
private Context context;
public MyClassAdapter(Context context, int textViewResourceId, ArrayList<String> items) {
super(context, textViewResourceId, items);
this.context = context;
}
public View getView(int position, View convertView) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
String item = getItem(position);
if (item!= null) {
// My layout has only one TextView
TextView commentView = (TextView) view.findViewById(R.id.listComment);
TextView usernameView = (TextView) view.findViewById(R.id.listPostedBy);
TextView NumberView = (TextView) view.findViewById(R.id.listNumber);
// do whatever you want with your string and long
commentView.setText(comments);
NumberView.setText(numbers);
usernameView.setText(usernames);
}
return view;
}
}
}//end if key is == 1
else{
// Error in registration
registerErrorMsg.setText(json2.getString(KEY_ERROR_MSG));
}//end else
}//end if
} //end try
catch (JSONException e) {
e.printStackTrace();
}//end catch
}
}
new loadComments().execute();
This code does not work but I think I am on the right track.
Let us say, you create a class that hold your information about the comments instead of creating three related Arrays :
class Commentary
{
public String username;
public String comment;
public int commentaryIndex;
}
The BaseAdapter can take a List as a parameter whereas the ArrayAdapter wouldn't.
class MyRealAdapter extends BaseAdapter
{
private List<Commentary> comments;
public MyRealAdapter(List<Commentary> comments )
{
this.comments = comments;
}
#Override
public int getCount() {
return comments.size();
}
#Override
public Object getItem(int index) {
return comments.get(index);
}
#Override
public long getItemId(int index) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Commentary c = (Commentary) getItem(position);
//c.username, c.comment, c.commentaryIndex
// create the view and stuff
return null;
}
}
As you can see, you again have the getView method but now you can retrieve your complete objet and not just a String.
There is a couple more method to override, but as you can see it's very simple.
You might need to pass other argument like a Context or a LayoutInflater to the constructor, but it's not mandatory.
EDIt :
JSONArray commentArray = json2.getJSONArray(KEY_COMMENT);
JSONArray numberArray = json2.getJSONArray(KEY_NUMBER);
JSONArray usernameArray = json2.getJSONArray(KEY_USERNAME);
ArrayList<Commentary> comments = new ArrayList<commentary>();
for ( int i=0; i<commentArray.length(); i++ ) {
Commentary c = new Commentary();
c.username = usernameArray.getString(i);
c.comment = commentArray.getString(i);
c.commentaryIndex = Integer.parseInt(numberArray.getString(i));
comments.add(c);
}
MyRealAdapter adapter = new MyRealAdapter(comments);

HTML Diff tool API [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I'm looking for an api that will visually show html difference for both structure, characters/words, and style. This tool must also support double byte characters and be flexible enough for me to add it to my existing website to show the results of the comparison easily. I'm currently using the Component Software COM implementation which doesn't support double byte characters and hasn't been updated in about six years.
The only two tools I found that can do something like that are http://changedetection.com and http://imnosy.com. Both offer you to specify a url and watch them for changes.
This is what I used:
[http://code.google.com/p/google-diff-match-patch/][1]
I had to write my own methods to do the compare but after a little work it looks fine. This implementation compares test as passed in so it works fine if you are just comparing 2 text strings. My diff_prettyHtml call was changed to:
public string diff_prettyHtml(List<Diff> diffs)
{
StringBuilder html = new StringBuilder();
foreach (Diff aDiff in diffs)
{
string text = aDiff.text.Replace("&", "&").Replace("<", "<")
.Replace(">", ">").Replace("\n", "<br>");
switch (aDiff.operation)
{
case Operation.INSERT:
html.Append("<ins class='diff'>").Append(text)
.Append("</ins>");
break;
case Operation.DELETE:
html.Append("<del class='diff'>").Append(text)
.Append("</del>");
break;
case Operation.EQUAL:
html.Append("<span>").Append(text).Append("</span>");
break;
}
}
return html.ToString();
}
Now if you want to do a compare preview of 2 html strings this is a little different. This is what I did:
DiffMatchPatch.diff_match_patch diff = new DiffMatchPatch.diff_match_patch();
List<DiffMatchPatch.Diff> differences = diff.diff_main(oldHtml,
newHtml);
return diff.diff_previewHtml(differences);
public string diff_previewHtml(List<Diff> diffs) {
StringBuilder html = new StringBuilder();
foreach (Diff aDiff in diffs) {
string text = aDiff.text;
switch (aDiff.operation) {
case Operation.INSERT:
html.Append("<ins class='diff'>").Append(text)
.Append("</ins>");
break;
case Operation.DELETE:
html.Append("<del class='diff'>").Append(text)
.Append("</del>");
break;
case Operation.EQUAL:
html.Append(text);
break;
}
}
return html.ToString();
}
The unicode class is as follows:
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
namespace HtmlCompare
{
class Unicoder
{
private Hashtable _htmlHash = new Hashtable();
private const string _htmlPattern = #"<(S*?)[^>]*>.*?|<.*?\/>";
private List<string> _blockElements = "img,br".Split(',').ToList<string>();
private int _currentHash = 44032;
public string pushHash(string tag)
{
if (_htmlHash[tag] == null)
{
//_htmlHash[tag] = char.Parse("\\u" + Convert.ToString(_currentHash,16));
_htmlHash[tag] = char.ConvertFromUtf32(_currentHash);
_currentHash++;
}
return _htmlHash[tag].ToString();
}
private string tagMatch(Match tag)
{
return pushHash(tag.Value);
}
public string html2plain(string html)
{
MatchEvaluator tagEvaluator = new MatchEvaluator(tagMatch);
return Regex.Replace(html, _htmlPattern, tagEvaluator, RegexOptions.IgnoreCase | RegexOptions.Multiline);
}
private string ProcessDiffTag(string tagStart, string tagEnd, string contents)
{
ArrayList diffTagParts = new ArrayList();
MatchCollection matches = Regex.Matches(contents,
_htmlPattern,
RegexOptions.IgnoreCase | RegexOptions.Multiline);
if (matches.Count > 0)
{
int contentsStringIndex = 0;
int contentsStringEndIndex = 0;
int lastContentStringIndex = 0;
bool lastTag = false;
TagDefinition definition;
foreach (Match currentMatch in matches)
{
contentsStringIndex = currentMatch.Index;
contentsStringEndIndex = contentsStringIndex + currentMatch.Length;
lastTag = (currentMatch == matches[matches.Count - 1]);
// did we miss text that isn't a tag?
if (contentsStringIndex > lastContentStringIndex)
{
definition = new TagDefinition();
definition.Tag = false;
definition.Text = contents.Substring(lastContentStringIndex, contentsStringIndex - lastContentStringIndex);
AddTagDefinition(diffTagParts, definition);
}
else if (lastTag && contents.Length > contentsStringEndIndex) // something after the last tag?
{
definition = new TagDefinition();
definition.Tag = false;
definition.Text = contents.Substring(contentsStringEndIndex, contents.Length - contentsStringEndIndex);
AddTagDefinition(diffTagParts, definition);
}
// work on current tag
definition = new TagDefinition();
definition.Tag = true;
definition.OpeningTag = !IsClosingTag(currentMatch.Value);
definition.TagType = GetTagType(currentMatch.Value);
definition.Text = currentMatch.Value;
AddTagDefinition(diffTagParts, definition);
lastContentStringIndex = contentsStringEndIndex;
}
return GoThroughDiffParts(diffTagParts,
tagStart,
tagEnd);
}
else
return string.Concat(tagStart, contents, tagEnd);
}
private string GetTagType(string tag)
{
int startIndex = 1; // skip <
if (tag.StartsWith("</"))
startIndex = 2; // skip </
int endIndex = tag.IndexOf(" ");
if (endIndex == -1)
endIndex = tag.IndexOf(">");
return tag.Substring(startIndex, endIndex - startIndex);
}
private string GoThroughDiffParts(ArrayList parts, string startTag, string endTag)
{
IEnumerator enumerator = parts.GetEnumerator();
StringBuilder before = new StringBuilder(string.Empty);
StringBuilder middle = new StringBuilder(string.Empty);
StringBuilder after = new StringBuilder(string.Empty);
TagDefinition definition;
while (enumerator.MoveNext())
{
definition = (TagDefinition)enumerator.Current;
if (!definition.Used) // have we already used this part?
{
definition.Used = true;
if (_blockElements.Contains(definition.TagType))
middle.Append(definition.Text);
else if (definition.MatchingIndex == -1) // no matching tag
{
if (definition.Tag) // html tag?
{
if (definition.OpeningTag)
before.Append(definition.Text);
else
after.Append(definition.Text);
}
else
middle.Append(definition.Text);
}
else
{
if (!definition.Tag) // text and has a matching tag
{
TagDefinition matchingTag = (TagDefinition)parts[definition.MatchingIndex];
if (matchingTag.OpeningTag)
matchingTag.Text += definition.Text;
else
matchingTag.Text = string.Concat(definition.Text, matchingTag.Text);
definition.Used = true;
}
else
middle.Append(definition.Text);
}
}
}
bool includeDiffTag = true;
if (string.IsNullOrEmpty(middle.ToString()))
includeDiffTag = false; // we don't want the ins/del tag around nothing
else if (string.IsNullOrWhiteSpace(middle.ToString())) // spacing should be kept
middle = new StringBuilder(" " + middle.Replace("\n", "<br />"));
if(includeDiffTag)
middle.Insert(0, startTag); // <ins>[middle]
middle.Insert(0, before); // [before]<ins>[middle]
if (includeDiffTag)
middle.Append(endTag); // [before]<ins>[middle]</ins>
middle.Append(after); // [before]<ins>[middle]</ins>[end]
return middle.ToString();
}
private string DiffTagMatch(Match tag)
{
string tagStart = tag.Groups[1].Value;
string tagEnd = tag.Groups[5].Value;
string contents = tag.Groups[4].Value;
if (string.IsNullOrEmpty(contents))
return string.Empty; // we don't want the ins/del tag around nothing
else if (string.IsNullOrWhiteSpace(contents)) // spacing should be kept
return string.Concat(tagStart, " ", contents.Replace("\n", "<br />"), tagEnd);
else
return ProcessDiffTag(tagStart,
tagEnd,
contents);
}
private bool IsClosingTag(string tag)
{
return tag.Contains("</") && !tag.ToLower().Contains("<img") && !tag.ToLower().Contains("<br");
}
public string CleanUpMisplacedDiffTags(string html)
{
return Regex.Replace(html, #"(\<((ins|del).*?)\>)(.*?)(\<\/((ins|del).*?)\>)", DiffTagMatch, RegexOptions.IgnoreCase | RegexOptions.Multiline);
}
public string plain2html(string plain)
{
IDictionaryEnumerator enumerator = _htmlHash.GetEnumerator();
while (enumerator.MoveNext())
{
plain = Regex.Replace(plain,
_htmlHash[enumerator.Key].ToString(),
enumerator.Key.ToString(),
RegexOptions.IgnoreCase | RegexOptions.Multiline);
}
return CleanUpMisplacedDiffTags(plain);
}
private void AddTagDefinition(ArrayList list, TagDefinition tag)
{
IEnumerator enumerator = list.GetEnumerator();
TagDefinition currentDefinition;
int index = 0;
int insertingIndex = list.Count;
while (enumerator.MoveNext())
{
currentDefinition = (TagDefinition)enumerator.Current;
//if (!tag.OpeningTag && currentDefinition.MatchingIndex == -1)
// currentDefinition.MatchingIndex = insertingIndex;
if (tag.MatchingIndex == -1 && // matching tag not found yet
(currentDefinition.OpeningTag && !tag.OpeningTag) && // opening & closing
currentDefinition.TagType == currentDefinition.TagType) // same tag type
{
tag.MatchingIndex = index;
currentDefinition.MatchingIndex = insertingIndex;
}
}
list.Add(tag);
}
private class TagDefinition
{
public bool Tag { get; set; }
public string TagType { get; set; }
public string Text { get; set; }
public int MatchingIndex { get; set; }
public bool OpeningTag { get; set; }
public bool Used { get; set; }
public TagDefinition()
{
this.Tag = false;
this.Text = string.Empty;
this.TagType = string.Empty;
this.MatchingIndex = -1;
this.OpeningTag = false;
this.Used = false;
}
}
}
}

SWT JFace: SelectionProvider not working in TabFolder

In a GraphicalEditor I created a tab folder:
private final String[] tabNames = { "Text", "Image" };
private ResourcesTextComposite comText;
private ResourcesImageComposite comImage;
...
public void createPartControl(Composite parent) {
...
tabFolder = new TabFolder(parent, SWT.BORDER);
for (int loopIndex = 0; loopIndex < tabNames.length; loopIndex++) {
TabItem tabItem = new TabItem(tabFolder, SWT.NULL);
tabItem.setText(tabNames[loopIndex]);
if (loopIndex == 0) {
comText = new ResourcesTextComposite(tabFolder, SWT.NONE,
resources);
tabItem.setControl(comText);
} else if (loopIndex == 1) {
comImage = new ResourcesImageComposite(tabFolder, SWT.NONE,
resources);
tabItem.setControl(comImage);
}
}
...
}
it has 2 tab items and each item has a composite in it, and each composite has a TableViewer respectively.
I tried this to make each TableViewer the selection provider when the user selects the corresponding tab item (the same function createPartControl of the editor):
public void createPartControl(Composite parent) {
...
tabFolder.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
int tabIdx = tabFolder.getSelectionIndex();
getSite().setSelectionProvider(null);
if (tabIdx == 0) {
getSite().setSelectionProvider(comText.getViewer());
} else if (tabIdx == 1) {
getSite().setSelectionProvider(comImage.getViewer());
}
System.out.println("widgetSelected" + getSite() + ": "
+ getSite().getSelectionProvider());
}
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
...
}
I hope when I select a row in a TableViewer, the Properties view will show the selected model's properties, I've complete those IPropertySource things and they works well in other editors that has no tab folders, so I think the problem should be in the Selection Provider area.
Any ideas or has anyone encountered the same problem?
If you have multiple selection providers in a view or editor, then you need to use a mediator like org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator. Note that it is unfortunately internal, so you need to copy it to your own project