0

I am trying to make a feature of upload image to server.For that i am using hostinger server and WinScp as file manager and a php Api for upload.To make this service i have used retrofit2 library.

My code works perfectly when user chooses small sized image from gallery.But app gets crashed and gives error of NullPointerException when user chooses large sized image from gallery.Why this is happening i don't understand.Please help me to solve.

Stack trace:(when user selects large sized image and clicks upload)

06-25 01:03:28.589 23155-23155/h.safmical.swipe I/Choreographer: Skipped 1122 frames!  The application may be doing too much work on its main thread.
06-25 01:03:33.451 23155-23162/h.safmical.swipe W/art: Suspending all threads took: 5.917ms
06-25 01:03:47.595 23155-23155/h.safmical.swipe E/saf: in onresponse
06-25 01:03:47.597 23155-23155/h.safmical.swipe D/AndroidRuntime: Shutting down VM
06-25 01:03:47.601 23155-23155/h.safmical.swipe E/AndroidRuntime: FATAL EXCEPTION: main
                                                                  Process: h.safmical.swipe, PID: 23155
                                                                  java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String h.safmical.swipe.ImageClass.getResponse()' on a null object reference
                                                                      at h.safmical.swipe.retrofit_img_upload$3.onResponse(retrofit_img_upload.java:94)
                                                                      at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
                                                                      at android.os.Handler.handleCallback(Handler.java:746)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                      at android.os.Looper.loop(Looper.java:148)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5443)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

My coding files:

MainActivity:

retrofit_img_upload.java:

package h.safmical.swipe;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class retrofit_img_upload extends AppCompatActivity {
    private EditText img_title;
    private Button choose, upload;
    private ImageView img;
    private static final int IMG_REQUEST = 777;
    private Bitmap bitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_retrofit_img_upload);
        Log.e("saf", "in oncrate of main");
        img_title = (EditText) findViewById(R.id.image_title);
        choose = (Button) findViewById(R.id.choose);
        upload = (Button) findViewById(R.id.upload);
        img = (ImageView) findViewById(R.id.imageview);
        choose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectImage();

            }
        });
        upload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                uploadimg();
            }
        });
    }

    private void selectImage() {
        Log.e("saf", "in inselectimg");
        Intent i = new Intent();
        i.setType("image/*");
        i.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(i, IMG_REQUEST);

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.e("saf", "in onactivityresult");
        if (requestCode == IMG_REQUEST && resultCode == RESULT_OK && data != null) {
            Uri path = data.getData();
            try {
                bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), path);
                img.setImageBitmap(bitmap);
                img.setVisibility(View.VISIBLE);
                img_title.setVisibility(View.VISIBLE);
                choose.setEnabled(false);
                upload.setEnabled(true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void uploadimg() {
        String Image = imageToString();
        String Title = img_title.getText().toString();
        Image_ApiInterface apiInterface = Image_ApiClient.getApiclient().create(Image_ApiInterface.class);
        Call<ImageClass> call = apiInterface.uploadImage(Title, Image);
        call.enqueue(new Callback<ImageClass>() {
            @Override
            public void onResponse(Call<ImageClass> call, Response<ImageClass> response) {
                Log.e("saf", "in onresponse");
                ImageClass imageclass = response.body();
               Toast.makeText(retrofit_img_upload.this, "server response:" + imageclass.getResponse(), Toast.LENGTH_LONG).show();
                img.setVisibility(View.GONE);
                img_title.setVisibility(View.GONE);
                choose.setEnabled(true);
                upload.setEnabled(false);
                img_title.setText("");
            }

            @Override
            public void onFailure(Call<ImageClass> call, Throwable t) {
                Log.e("saf", "in onfailure");
                Log.e("saf", t.toString());

            }
        });
    }


    private String imageToString() {
        Log.e("saf", "in imagetostring");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
        byte[] imgByte = byteArrayOutputStream.toByteArray();
        //Log.e("saf",Base64.encodeToString(imgByte,Base64.DEFAULT));
        return Base64.encodeToString(imgByte, Base64.DEFAULT);
    }
}

Class to create an instance of Retrofit:

Image_ApiClient.java:

package h.safmical.swipe;

import android.util.Log;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by hadvani on 6/24/2017.
 */

public class Image_ApiClient {
    private static final String BaseUrl= "****************";
    private  static Retrofit retrofit;

    public static Retrofit getApiclient(){
        Log.e("saf","in getapiclient");
        if(retrofit==null){
            Log.e("saf","in if of get apiclient");
            retrofit=new Retrofit.Builder().baseUrl(BaseUrl).addConverterFactory(GsonConverterFactory.create()).build();
        }
        return retrofit;
    }
}

Interface to pass parameters to api:

Image_ApiInterface.java:

package h.safmical.swipe;

import android.util.Log;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
import retrofit2.http.Query;

/**
 * Created by hadvani on 6/24/2017.
 */

public interface Image_ApiInterface {

    @FormUrlEncoded
    @POST("upload.php")
    Call<ImageClass> uploadImage(@Field("title") String title, @Field("image") String image);

}

Class for Response:

ImageClass.java:

package h.safmical.swipe;

import com.google.gson.annotations.SerializedName;

/**
 * Created by hadvani on 6/24/2017.
 */

public class ImageClass {

    @SerializedName("title")
    private String Title;

    @SerializedName("image")
    private String Image;

    @SerializedName("response")
    private String Response;

    public String getResponse() {
        return Response;
    }
}

Xml file of retro_img_upload(MainActivity):

activity_retrofit_img_upload.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="h.safmical.swipe.retrofit_img_upload">
    <ImageView
        android:layout_width="300dp"
        android:layout_height="250dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="15dp"
        android:id="@+id/imageview"
        android:visibility="gone"/>
<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/imageview"
    android:hint="Enter image title"
    android:layout_marginTop="20dp"
    android:id="@+id/image_title"
    android:visibility="gone"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/image_title"
        android:text="Choose image"
        android:layout_marginTop="25dp"
        android:id="@+id/choose"
        android:layout_marginLeft="50dp"
        android:layout_marginRight="50dp"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/choose"
        android:text="upload image"
        android:layout_marginTop="25dp"
        android:id="@+id/upload"
        android:enabled="false"
        android:layout_marginLeft="50dp"
        android:layout_marginRight="50dp"/>
</RelativeLayout>

PHP file to upload Image:

upload.php:

<?php
include 'confi.php';
  if($conn)
  {
   $title=$_POST['title'];
   $image=$_POST['image'];
  $upload_pathh = "uploads/$title.jpg";
   $upload_path = "***********/uploads/$title.jpg";

   $sql = "insert into imageinfo(title,path) values('$title','$upload_path');";
   if(mysqli_query($conn,$sql))
   {
   file_put_contents($upload_pathh,base64_decode($image));
   echo json_encode(array('response'=>"image uploaded successfully...."));
   }
   else
   {
       echo json_encode(array('response'=>"image upload failed...."));
   }   

   mysqli_close($conn);

  }
?>

I have listed all my coding files includes this feature of my application.Please help me to solve this.Thank you.

user8209191
  • 37
  • 1
  • 7

2 Answers2

0

Your imageclass object is null hence you are getting hence you are getting "attempt to invoke virtual method at ImageClass.getResponse()' on a null object reference". Make sure your url works, use postman or some other api test software.

ImageClass imageclass = response.body();
HaroldSer
  • 2,025
  • 2
  • 12
  • 23
0

That is because you need to resize your image before uploading. Since the image you are trying to upload is too big and that is causing your android to consume a lot of memory. Use a thread first of all as you can see in your error that is working too much on its main thread and that is the reason why you are getting null by the log 06-25 01:03:28.589 23155-23155/h.safmical.swipe I/Choreographer: Skipped 1122 frames! The application may be doing too much work on its main thread. and also use this

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

so that you donot end up loading the big bitmap in your memory

Siva agarwal
  • 97
  • 1
  • 8
  • Where should i add this ? – user8209191 Jun 24 '17 at 20:37
  • in the onActivityResults () and also check out the offical documentation for better understanding of how it works [here](https://developer.android.com/topic/performance/graphics/load-bitmap.html) For logic you can check out [this](https://stackoverflow.com/questions/3331527/android-resize-a-large-bitmap-file-to-scaled-output-file) – Siva agarwal Jun 24 '17 at 20:40