我正在尝试将上传图像的功能发送到服务器。为此我使用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);
}
?>
我列出了我的所有编码文件,包括我的应用程序的这个功能。请帮我解决这个问题。谢谢。
答案 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;
这样你就不会在内存中加载大位图了