You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:57:10