Retrofit报错java.lang.IllegalArgumentException:API声明需为接口的解决问询
问题排查:Retrofit 报错 "API declarations must be interfaces"
错误信息
java.lang.IllegalArgumentException: API declarations must be interfaces.
相关代码
Activity 音频上传代码
private void uploadAudio() { Long date = new Date().getTime(); Date current_time = new Date(Long.valueOf(date)); String file_path = getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() + "/" + current_time + ".3gp"; File audioFile = new File(file_path); RequestBody requestFile = RequestBody.create(MediaType.parse("audio/*"), audioFile); MultipartBody.Part audioPart = MultipartBody.Part.createFormData("audio", audioFile.getName(), requestFile); ApiService apiService = ApiClient.getClient().create(ApiService.class); Call<ResponseBody> call = apiService.uploadAudio(audioPart); call.enqueue(new retrofit2.Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) { if (response.isSuccessful()){ if (response.body().toString().equals("200")){ Toast.makeText(getApplicationContext(), "Audio uploaded Successfully", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(getApplicationContext(),"Audio Upload Failed", Toast.LENGTH_SHORT).show(); } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Toast.makeText(getApplicationContext(), t.toString(), Toast.LENGTH_SHORT).show(); } }); }
ApiService 原代码
public class ApiService { @Multipart @POST("retroapi2.php") Call<ResponseBody> uploadAudio(@Part MultipartBody.Part audio) { return null; } }
ApiClient 代码
public class ApiClient { private static final String BASE_URL = "http://mysite.in/atmedia/ud/"; private static Retrofit retrofit; public static Retrofit getClient() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } }
后端PHP代码
if($_SERVER['REQUEST_METHOD']=='POST'){ //Getting post data $fileName = $_FILES['audio']['name']; $tempPath = $_FILES['audio']['tmp_name']; $fileSize = $_FILES['audio']['size']; $upload_path = 'upload/'; // set upload folder path require_once('retconfig.php'); //Creating an SQL Query to insert into database //Here you may need to change the retrofit_users because it is the table I created //if you have a different table write your table's name //This query is to check whether the username or email is already registered or not $sql = "SELECT * FROM demo WHERE mobile='$mobile'"; //If variable check has some value from mysqli fetch array //That means username or email already exist $check = mysqli_fetch_array(mysqli_query($con,$sql)); //Checking check has some values or not if(isset($check)){ //If check has some value that means username already exist echo 'username or email already exist'; }else{ //If username is not already exist //Creating insert query if($fileSize < 5000000){ move_uploaded_file($tempPath, $upload_path . $fileName); // move file from system temporary path to our upload folder path }
问题原因
Retrofit 框架要求所有API声明必须是接口(interface),不能是普通类(class)。你当前的ApiService用class定义,违反了这个核心规范,因此触发该异常。
解决方案
将ApiService修改为接口,移除方法的具体实现:
public interface ApiService { @Multipart @POST("retroapi2.php") Call<ResponseBody> uploadAudio(@Part MultipartBody.Part audio); }
额外优化建议
- 文件路径优化:直接用
Date对象拼接文件名会生成带空格的路径,建议改用时间戳字符串:String file_path = getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() + "/" + date + ".3gp"; - ResponseBody 正确读取:
response.body().toString()无法获取真实返回内容,需读取流数据:if (response.isSuccessful()) { try { String responseStr = response.body().string(); if ("200".equals(responseStr)) { Toast.makeText(getApplicationContext(), "Audio uploaded Successfully", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(),"Audio Upload Failed", Toast.LENGTH_SHORT).show(); } } catch (IOException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(), "Failed to read response", Toast.LENGTH_SHORT).show(); } } - 后端代码完善:当前存在SQL注入风险,建议用预处理语句;同时需补充上传结果的响应输出:
if($fileSize < 5000000){ if(move_uploaded_file($tempPath, $upload_path . $fileName)){ echo "200"; // 上传成功返回标识 } else { echo "Upload failed"; } } else { echo "File too large"; }
内容的提问来源于stack exchange,提问作者kranthi chevuri
相关产品推荐
相关产品推荐

