-2

I'm trying to make an app which downloads stock data from yahoo! and displays it.

this is my code:

MainActivity.java :

package frank.com.myapplication;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.apache.http.util.ByteArrayBuffer;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;


public class MainActivity extends ActionBarActivity {

TextView symbolOut;
TextView priceOut;
TextView changePrecentageOut;
Button getQuote;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    symbolOut = (TextView) findViewById(R.id.stockSymbolOutput);
    priceOut = (TextView) findViewById(R.id.stockPriceOutput);
    changePrecentageOut = (TextView) findViewById(R.id.stockChangePercentageOutput);

    getQuote = (Button) findViewById(R.id.get_quote_button);

    getQuote.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            URL url;

            try {
                url = new URL("http://download.finance.yahoo.com/d/quotes.csv?s=goog&f=sl1p2");

                InputStream stream = url.openStream();
                BufferedInputStream bis = new BufferedInputStream(stream);
                ByteArrayBuffer baf = new ByteArrayBuffer(50);

                int current = 0;

                    while ((current = bis.read()) != -1){
                        baf.append((byte) current);
                    }

                String stockTxt = new String(baf.toByteArray());

                String[] tokens = stockTxt.split(",");

                String stockSymbol =            tokens[0];
                String stockPrice  =            tokens[1];
                String stockChangePercentage =  tokens[2];

                String fstockSymbol = stockSymbol.substring(1, stockSymbol.length( ) -1);
                String fstockChangePercentage = stockChangePercentage.substring(1, stockChangePercentage.length() -3);

                symbolOut.setText(fstockSymbol);
                priceOut.setText(stockPrice);
                changePrecentageOut.setText(fstockChangePercentage);

            } catch (MalformedURLException e) {
                e.printStackTrace();

            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Get Quote"
    android:id="@+id/get_quote_button"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/stockSymbolOutput"
    android:layout_below="@+id/get_quote_button"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/stockPriceOutput"
    android:layout_below="@+id/stockSymbolOutput"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/stockChangePercentageOutput"
    android:layout_below="@+id/stockPriceOutput"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

When i try to click the button in my app it gives the following errors:

01-18 15:20:23.959    1532-1532/frank.com.myapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: frank.com.myapplication, PID: 1532
android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
        at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
        at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
        at java.net.InetAddress.getAllByName(InetAddress.java:215)
        at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
        at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
        at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
        at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)
        at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)
        at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:190)
        at java.net.URL.openStream(URL.java:470)
        at frank.com.myapplication.MainActivity$1.onClick(MainActivity.java:48)
        at android.view.View.performClick(View.java:4756)
        at android.view.View$PerformClick.run(View.java:19749)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Any help would be appreciated, i've been stuck at this for quite a while now.

FrankK
  • 482
  • 8
  • 23
  • 1
    Definite duplicate of [android.os.NetworkOnMainThreadException](http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception). It's surprising that the asker found StackOverflow while googling this exception, without finding the relevant answers. – 323go Jan 18 '15 at 15:08
  • Try AsyncTask or spawn a new Thread to do your job. I am not sure why the answer got downvoted though. – ZakiMak Jan 18 '15 at 15:15

1 Answers1

-1

Your problem is you are downloading(doing network operation) in the UI/Main thread of the Android. This is not permissible as this will cause the UI to hang. Hence Android will not allow you to carry this out.

You will find the details about it over here: NetworkOnMainThreadException

For app responsiveness here is what you should know:

In any situation in which your app performs a potentially lengthy operation, you should not perform the work on the UI thread, but instead create a worker thread and do most of the work there.

If you have any long running task like downloading or any network connectivity, you should do it in a new Thread. A proper way to do this would be to implement your code in AsyncTask.

Check the documentation over here: http://developer.android.com/reference/android/os/AsyncTask.html

To know more about app responsiveness check this link: Keeping Your App Responsive

ZakiMak
  • 2,072
  • 2
  • 17
  • 26