1

I`m pretty new in Android development and this is my first application.

The issue probably is very simple but I can`t find a solution.

This application is a simple ImageViewer where the app must connect to a server and depending on some data the server will return a particular image. That image is shown on the screen,click on it will get another. That`s it!

As I can see I can`t run a http post query from the UIThread and must do in the background. However the intent is when the user clicks on the image.

I have a AsyncTask where on create the application will be recognized by the server and they will exchange some data. Im using a library SmartImageViewer (making possible load images from a url). At the moment in my code Im loading the images by a counter++ and so far its working. But I need to get a image url every time when the user clicks it and show it on the screen.

public class MainActivity extends Activity implements OnClickListener {
SmartImageView imageSwitcher;
String SERVER_IP;
String APP_ID;
String DEVICE_ID;
Integer counter = 0;

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

    DB_Queries db = new DB_Queries(getApplicationContext());
    Cursor c = db.getServerIPAndAppId();
    StringBuilder app_id = new StringBuilder();
    StringBuilder server_ip = new StringBuilder();
    if (c.moveToFirst()) {
        do {
            server_ip.append(c.getString(c.getColumnIndex("server_ip")));
            app_id.append(c.getString(c.getColumnIndex("app_id")));
        } while (c.moveToNext());
    }
    db.close();

    SERVER_IP = server_ip.toString();
    APP_ID = app_id.toString();

    ServerConnect connect = new ServerConnect();
    connect.execute("http://" + server_ip + "/");

    SmartImageView image = (SmartImageView) this
            .findViewById(R.id.image_switcher);
    image.setImageUrl("http://localhost/public/albums/1/_(99).jpg");

    imageSwitcher = (SmartImageView) findViewById(R.id.image_switcher);
    imageSwitcher.setOnClickListener(this);

}

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

@Override
public void onClick(View v) {
    if (v.getId() == imageSwitcher.getId()) {
        counter++;
        Toast.makeText(getApplicationContext(), "Image is clicked",
                Toast.LENGTH_LONG).show();
        SmartImageView image = (SmartImageView) this
                .findViewById(R.id.image_switcher);
        image.setImageUrl("http://localhost/public/albums/1/_("
                + counter + ").jpg");
    }
}

private class ServerConnect extends AsyncTask<String, Void, Void> {

    @Override
    protected Void doInBackground(String... params) {
        String DEVICE_ID = Secure.getString(getContentResolver(),
                Secure.ANDROID_ID);
        DB_Queries db = new DB_Queries(getApplicationContext());
        Cursor c = db.getSettings();
        String APP_ID = null;
        String INSTALLED_AT = null;
        String TOKEN = null;
        if (c.moveToFirst()) {
            do {
                APP_ID = c.getString(c.getColumnIndex("app_id"));
                INSTALLED_AT = c
                        .getString(c.getColumnIndex("installed_at"));
                TOKEN = c.getString(c.getColumnIndex("token"));
            } while (c.moveToNext());
        }

        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(params[0]);
        post.addHeader("Content-type", "application/x-www-form-urlencoded");
        List<NameValuePair> pair = new ArrayList<NameValuePair>();
        pair.add(new BasicNameValuePair("device_id", DEVICE_ID));
        pair.add(new BasicNameValuePair("app_id", APP_ID.toString()));
        pair.add(new BasicNameValuePair("token", TOKEN.toString()));

        try {
            post.setEntity(new UrlEncodedFormEntity(pair));
            HttpResponse response = client.execute(post);
            InputStream is = response.getEntity().getContent();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuilder str = new StringBuilder();
            String chunk = null;

            while ((chunk = br.readLine()) != null) {
                str.append(chunk);
            }

            final String query_response = str.toString().trim();

            if (query_response.equals("HH@K2i")) {
                Cursor delete = db.updateAuth();
            }

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

        db.close();

        return null;
    }

}

}

ventsi.slav
  • 334
  • 1
  • 4
  • 14
  • all your network related operation should be done on a background thread. you can use asynctask or create a new thread . Do you get any exceptions?. post the logcat – Raghunandan Jun 07 '13 at 08:24
  • possible duplicate of [HTTP doesn't work in Android emulator](http://stackoverflow.com/questions/11277734/http-doesnt-work-in-android-emulator) – Stephen C Jun 07 '13 at 08:27
  • Yeah I know I can`t do it that way.The question is how to realize the idea. I have a database where I can store 10 image urls for example and take them from there. But when they finish I`ll have to get a new 10 images. HTTP POST request are working on the emulator!I`m also using a phone for testing.Connections between the server and the device are ok. – ventsi.slav Jun 07 '13 at 08:28

4 Answers4

2

- Its always a good practice to keep the UI work on UI thread and Non-UI work on Non-UI thread, but from Android version Honey Comb it became a law.

- You can do the Network processing work on the background Non-UI thread.

- Use Thread with Handler to solve this task, or use what is called as PainLess Threading in android known as AsyncTask.

- Handler is used along with Thread in order to put the output from the background Non-UI thread to UI thread, similarly when you are using AsyncTask use the doInBackground() method to do the work in background and post its output on UI thread through onPostExecute() method.

Eg:

new AsyncTask<Params, Progress, Result>() {

            @Override
            protected Result doInBackground(Params... params) {

                                // --- Do your network task here

                return null;
            }

            protected void onPostExecute(Result result) {

                                // --- Show the output on UI thread from here

                       };
        };
nidhi
  • 763
  • 5
  • 17
  • Ok thats great,but where should I call it ? On the create or on click ? – ventsi.slav Jun 07 '13 at 08:47
  • You should call asynctask on the on click event and the logic of loading image should be written in do in background method of asynctask. – nidhi Jun 07 '13 at 09:22
1

it is now impossible to run network operations in the main UIthread. you have to use another thread if you want to be abble to do a HTTP request. as raghunandan said, you should use asynctask for this

wazaminator
  • 245
  • 3
  • 15
0

you may also use WebImageView component for such purpose.
here are sample codes (adapted from different places)
WebImageView >>
WebService >>

and here is example project >>

Yilmaz Guleryuz
  • 9,313
  • 3
  • 32
  • 43
0

From your code it seems like you are already setting a new image in the onClick method.

If you are wanting to fetch a new URL from the server, and then display the image, you will need to use an asynctask. You can use the same one you have there already if it does what you want. Just start it from the onclick, e.g.

onClick(View v){
new MyAsynctask().execute();
}

Asynctasks have an onPostExecute method, which gets run after the doInbackground method gets run. The onPostExecute gets run on the UI thread. This is where you will set your new image from.

From your doInBackground method, you should return a String which is the URL. This gets passed to the onPostExecute method. Then just do a image.setImageUrl(url);.

Also one more thing, in your onClick you are binding the view every time:

  SmartImageView image = (SmartImageView) this
                .findViewById(R.id.image_switcher);

Do this once in your oncreate, and make image a field. Then you can access image from anywhere in your class. findViewById is an expensive call, so you only want to do it once.

athor
  • 6,848
  • 2
  • 34
  • 37