YQL クエリ言語を使用して Yahoo 金融から通貨データを解析する単純なアプリを実行しようとしています。Google の Finance API でデータを解析しようとしましたが、問題なく動作しますが、Yahoo の URL で試してみると、非常に奇妙な解析アルゴリズムに到達する前にフリーズします。
package com.sfc.watcher;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.Xml;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
public class ForexActivity extends Activity {
String temp1;
String temp2;
TableLayout tl1;
View temp3;
private static final String URL1 ="http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(\"" ;
private static final String URL2="\")&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
// This TAG is used for logging
private static final String TAG = "ForexWatcherActivity";
// These String constants refer to the XML elements we will be displaying
private static final String NAME = "Name";
private static final String RATE = "Rate";
private static final String DATE = "Date";
private static final String TIME = "Time";
private static final String ASK = "Ask";
private static final String BID = "Bid";
// This String refers to the attribute we are collecting for each element in
// our XML
private static final String DATA = "data";
// This HashMap will store, in key-value pairs, the currency data we receive.
private HashMap<String, String> hmCurrencyData = new HashMap<String, String>();
// This is the edit control that users will key into
private EditText edittext1 = null;
// This is the button that, when pressed, will request currency price data.
private Button button1 = null;
// This variable will hold the currency symbol value the user has keyed in.
private String symbol = "";
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
temp3=v;
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
return true;
case R.id.delete:
tl1.removeView(temp3);
return true;
case R.id.save:
return true;
default:
return super.onContextItemSelected(item);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.forex);
tl1 = (TableLayout) findViewById(R.id.myTableLayout);
button1 = (Button)findViewById(R.id.bn_retrieve);
edittext1 = (EditText) findViewById(R.id.edit_symbol1);
edittext1.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable arg0) {
}
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
// here we respond to users key input events
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// collect the text from the edit control, and trim off spaces.
symbol = edittext1.getText().toString().trim();
// if the user has entered at least one character, enable the
// bnRetrieve button.
// otherwise, disable it.
button1.setEnabled(symbol.length() > 0);
}
});
final EditText edittext2 = (EditText) findViewById(R.id.edit_symbol2);
//First spinner for input forex
Spinner spinner1 = (Spinner) findViewById(R.id1.spinner);
ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(
this, R.array.forex_array, android.R.layout.simple_spinner_item);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(adapter1);
spinner1.setOnItemSelectedListener(new SellListener());
//Second spinner for Output forex
Spinner spinner2 = (Spinner) findViewById(R.id2.spinner);
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(
this, R.array.forex_array, android.R.layout.simple_spinner_item);
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner2.setAdapter(adapter2);
spinner2.setOnItemSelectedListener(new BuyListener());
// Capture our button from layout
Button button2 = (Button)findViewById(R.id.bn_convert);
// Register the onClick listener with the implementation above
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText( getApplicationContext(),"Selling "+ "$"+ edittext2.getText().toString()+ " "+ temp1 + " Buying "+ "$"+ temp2, Toast.LENGTH_LONG).show();
}
});
}
public class SellListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
temp1=parent.getItemAtPosition(pos).toString();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
public class BuyListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
temp2=parent.getItemAtPosition(pos).toString();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
public void retrieveQuote(View vw) {
// our "symbol" variable already has the text from the edSymbol view via
// the onTextChanged() event capture.
String request = URL1 + symbol + URL2;
CurrencyRetrieveTask task = new CurrencyRetrieveTask();
task.execute(new String[] { request });
}
private class CurrencyRetrieveTask extends AsyncTask<String, Void, String> {
private static final String TAG = "CurrencyRetrieveTask";
private ProgressDialog pDlg = null;
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
hideKeyboard();
pDlg = createProgressDialog(ForexActivity.this,
getString(R.string.retrieving));
super.onPreExecute();
}
@Override
protected String doInBackground(String... urls) {
Log.i(TAG, "doInBackground");
StringBuilder sb = new StringBuilder();
// Remember that the array will only have one String
String url = urls[0];
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
sb.append(s);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
return sb.toString();
}
@Override
protected void onPostExecute(String response) {
readResponse(response);
displayResponse();
pDlg.dismiss();
}
}
private void hideKeyboard() {
// hide the soft keyboard, if it is currently visible.
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edittext1.getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
private ProgressDialog createProgressDialog(final Context context,
final String message) {
Log.i(TAG, "createProgressDialog");
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage(message);
progressDialog.setProgressDrawable(getWallpaper());
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(false);
progressDialog.show();
return progressDialog;
}
private void readResponse(String response) {
Log.i(TAG, "displayResponse");
// initialize our HashMap, resetting it if it was previously used.
hmCurrencyData = new HashMap<String, String>();
try {
String elementName = "";
String elementValue = "";
String nameSpace = "";
StringReader xmlReader = new StringReader(response);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(xmlReader);
elementName = parser.getName();
while (!elementName.equals("rate"))
{
parser.nextTag();
elementName = parser.getName();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
e.printStackTrace();
}
}
private void updateTextView(String name, TableRow Row) {
if(hmCurrencyData.containsKey(name))
{
TextView TV1= new TextView(getApplicationContext());
TV1.setText(hmCurrencyData.containsKey(name) ? hmCurrencyData.get(name) : "");
TV1.setLayoutParams(new TableRow.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
Row.addView(TV1);
}
}
private void displayResponse() {
Log.i(TAG, "displayResponse");
TableRow tr = new TableRow(getApplicationContext());
tr.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.setPadding(0, 10, 0, 10);
updateTextView(NAME, tr);
updateTextView(RATE, tr);
updateTextView(DATE, tr);
updateTextView(TIME, tr);
updateTextView(ASK, tr);
updateTextView(BID, tr);
registerForContextMenu(tr);
tl1.addView(tr,new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
}