Android Java实现ChatGPT API流式响应遇API密钥错误求助
问题
我在Android(Java)中尝试通过AsyncTask结合HttpURLConnection实现ChatGPT API的流式逐词响应,模拟原生界面的效果,但一直收到“未提供API密钥”的错误。该API密钥格式正确且有效,因为在Android Kotlin的Volley库中可以正常使用。以下是我的代码和错误信息:
代码
import androidx.appcompat.app.AppCompatActivity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.facebook.ads.AdView; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; public class gpt extends AppCompatActivity { EditText queryt; TextView question; TextView response1; AdView mAdview; Button queryb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_gpt); response1 = findViewById(R.id.idTVResponse2); question = findViewById(R.id.idTVQuestion2); queryt = findViewById(R.id.edit_query2); queryb = findViewById(R.id.buttonPanel2); queryb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ChatGPTTask GPT = new ChatGPTTask(); GPT.execute(queryt.getText().toString()); queryt.setText(""); } }); } public class ChatGPTTask extends AsyncTask<String, String, Void> { private final String TAG = ChatGPTTask.class.getSimpleName(); private final String API_URL = "https://api.openai.com/v1/completions"; //private final String API_KEY =API_KEY @Override protected void onPostExecute(Void unused) { super.onPostExecute(unused); } @Override protected Void doInBackground(String... strings) { try { String prompt = strings[0]; URL url = new URL(API_URL); Log.d(TAG, "Authorization Header: " +url); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); Log.d(TAG, "Authorization Header: " +conn); conn.setRequestMethod("POST"); String authHeader = "Bearer API_KEY"; conn.setConnectTimeout(5000); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Authorization", authHeader); conn.setDoOutput(true); Log.d(TAG, "Authorization Header: " + authHeader); String requestBody = "{\n" + " \"model\": \"text-davinci-003\",\n" + " \"prompt\": \"" + prompt + "\",\n" + " \"max_tokens\": 1000,\n" + " \"temperature\": 0.0,\n" + " \"top_p\": 1,\n" + " \"frequency_penalty\": 0.0,\n" + " \"presence_penalty\": 0.0,\n" + "}"; conn.getOutputStream().write(requestBody.getBytes(StandardCharsets.UTF_8)); InputStream inputStream = conn.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = bufferedReader.readLine()) != null) { publishProgress(line); } bufferedReader.close(); inputStream.close(); conn.disconnect(); } catch (IOException e) { Log.e(TAG, "Error: " + e.getMessage()); } return null; } @Override protected void onProgressUpdate(String... values) { String response = values[0]; response1.append(response); Log.d(TAG, "Response: " + response); } } }
错误信息
{ "error": { "message": "未提供API密钥。你需要在Authorization头中使用Bearer认证方式提供密钥(格式为Authorization: Bearer YOUR_KEY);如果是在浏览器中访问API并被提示输入用户名密码,可以将密钥填在密码字段,用户名字段留空。你可以从平台获取API密钥。", "type": "invalid_request_error", "param": null, "code": null } }
解决方案
1. 修复API密钥配置问题
代码中注释掉了API_KEY的定义,并且直接硬写了"Bearer API_KEY"作为授权头,导致实际请求没有携带真实密钥。
- 取消
API_KEY的注释,填入你的真实密钥:private final String API_KEY = "你的实际API密钥"; - 正确拼接授权头:
String authHeader = "Bearer " + API_KEY;
2. 修复请求体的JSON格式错误
请求体最后一个键值对"presence_penalty": 0.0,后面多了一个逗号,会导致JSON解析失败,间接引发请求异常。同时要添加流式响应必需的stream参数:
String requestBody = "{\n" + " \"model\": \"text-davinci-003\",\n" + " \"prompt\": \"" + prompt + "\",\n" + " \"max_tokens\": 1000,\n" + " \"temperature\": 0.0,\n" + " \"top_p\": 1,\n" + " \"frequency_penalty\": 0.0,\n" + " \"presence_penalty\": 0.0,\n" + " \"stream\": true\n" + "}";
3. 正确处理流式响应数据
ChatGPT的流式响应每行以data:开头,包含JSON数据,最后以data: [DONE]标记结束,需要过滤无效行并提取实际响应文本:
修改doInBackground中的响应处理逻辑:
String line; while ((line = bufferedReader.readLine()) != null) { // 过滤空行和结束标记 if (line.isEmpty() || line.equals("data: [DONE]")) { continue; } // 去掉前缀"data: " String jsonStr = line.substring(6); // 解析JSON提取text字段(Android默认包含org.json库) try { org.json.JSONObject jsonObj = new org.json.JSONObject(jsonStr); String text = jsonObj.getJSONArray("choices").getJSONObject(0).getString("text"); publishProgress(text); } catch (org.json.JSONException e) { Log.e(TAG, "JSON解析错误: " + e.getMessage()); } }
4. 额外注意事项
- 不要在代码中硬编码API密钥,建议通过
gradle.properties或安全存储方式读取,避免密钥泄露。 AsyncTask在Android 11及以上已被废弃,建议改用Coroutines或ExecutorService替代。
内容的提问来源于stack exchange,提问作者Calt Channel
相关产品推荐
相关产品推荐

