与小尺寸图像完美配合,#34;但在将大尺寸图像上传到服务器时会出现NullPointerException错误。#34。

时间:2017-06-24 19:57:13

标签: php android retrofit image-uploading retrofit2

我正在尝试将上传图像的功能发送到服务器。为此我使用hostinger服务器和WinScp作为文件管理器和php Api进行上传。为了使这项服务我使用了 retrofit2库

当用户从gallery.But中选择小尺寸图像时,我的代码非常有效 当用户从图库中选择大尺寸图像时,应用程序崩溃并出现NullPointerException错误。为什么会发生这种情况我不明白。请帮我解决。

堆栈跟踪:(当用户选择大尺寸图片并点击上传时)

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)

我的编码文件:

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);
    }
}

创建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;
    }
}

将参数传递给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);

}

响应类:

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;
    }
}

retro_img_upload(MainActivity)的Xml文件:

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文件图片:

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);

  }
?>

我列出了我的所有编码文件,包括我的应用程序的这个功能。请帮我解决这个问题。谢谢。

2 个答案:

答案 0 :(得分:0)

  

你的imageclass对象是null因此你得到了你   获得“尝试在ImageClass.getResponse()上调用虚方法”   在空对象引用上“。确保你的网址有效,使用邮递员或其他一些api测试软件。

ImageClass imageclass = response.body();

答案 1 :(得分:0)

这是因为您需要在上传之前调整图片大小。由于您尝试上传的图片太大,导致您的Android消耗大量内存。首先使用一个线程,正如您在错误中看到的那样,它在主线程上工作太多,这就是为什么你在日志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. 下获取null并使用此

的原因
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

这样你就不会在内存中加载大位图了