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

基于Pi4j的树莓派图像传输至Android应用技术求助

我来帮你梳理下Android端的实现步骤,刚好之前做过类似的图像传输场景,应该能解决你的问题:

Android端核心实现方案

1. 搭建本地HTTP服务器接收图片

Android端要接收树莓派的POST请求,用轻量的NanoHTTPD库最方便,它是纯Java实现的,集成简单不用依赖复杂框架。

步骤1:添加依赖

在你的app/build.gradle里加入依赖:

implementation 'org.nanohttpd:nanohttpd:2.3.1'

步骤2:实现自定义服务器类

创建一个继承NanoHTTPD的类,专门处理图片上传请求:

public class ImageUploadServer extends NanoHTTPD {
    private Context mAppContext;

    public ImageUploadServer(Context context, int port) {
        super(port);
        mAppContext = context.getApplicationContext();
    }

    @Override
    public Response serve(IHTTPSession session) {
        // 只处理POST请求
        if (!Method.POST.equals(session.getMethod())) {
            return newFixedLengthResponse(Response.Status.METHOD_NOT_ALLOWED, "text/plain", "仅支持POST请求");
        }

        try {
            // 解析上传的表单数据
            Map<String, String> fileParams = new HashMap<>();
            session.parseBody(fileParams);
            
            // 这里的"raspberry_image"是树莓派上传时的参数名,两边要保持一致
            String tempImagePath = fileParams.get("raspberry_image");
            if (tempImagePath == null) {
                return newFixedLengthResponse(Response.Status.BAD_REQUEST, "text/plain", "未检测到上传的图片");
            }

            // 把临时文件复制到APP私有目录(避免权限问题)
            File tempFile = new File(tempImagePath);
            String saveFileName = System.currentTimeMillis() + ".jpg";
            File saveFile = new File(mAppContext.getFilesDir(), saveFileName);
            FileUtils.copyFile(tempFile, saveFile);

            // 触发通知显示图片
            showImageNotification(saveFile.getAbsolutePath());

            return newFixedLengthResponse(Response.Status.OK, "text/plain", "图片上传成功");
        } catch (IOException | ResponseException e) {
            e.printStackTrace();
            return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "上传失败:" + e.getMessage());
        }
    }

    // 显示带图片的系统通知
    private void showImageNotification(String imagePath) {
        NotificationManager notificationManager = (NotificationManager) mAppContext.getSystemService(Context.NOTIFICATION_SERVICE);
        String channelId = "image_upload_channel";

        // Android 8.0+必须创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    channelId,
                    "树莓派图像通知",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
        }

        // 加载图片为Bitmap作为通知大图标
        Bitmap imageBitmap = BitmapFactory.decodeFile(imagePath);
        Notification notification = new NotificationCompat.Builder(mAppContext, channelId)
                .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知小图标
                .setLargeIcon(imageBitmap)
                .setContentTitle("收到树莓派图像")
                .setContentText("点击查看详情")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .build();

        // 发送通知(ID用1保证每次新通知覆盖旧的,或者用不同ID保留历史)
        notificationManager.notify(1, notification);
    }
}

步骤3:启动服务器

在Activity或者后台Service里启动服务器,比如在MainActivity的onCreate中:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    try {
        // 选择一个端口,比如8080,树莓派要能通过局域网访问这个端口
        ImageUploadServer server = new ImageUploadServer(this, 8080);
        server.start();
        Toast.makeText(this, "图像服务器已启动,端口:8080", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "服务器启动失败,请检查端口占用", Toast.LENGTH_SHORT).show();
    }
}

步骤4:添加必要权限

在AndroidManifest.xml中加入网络权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

2. 树莓派端POST请求配合(补充参考)

你已经有生成图片的代码,这里给你一段Java环境下的上传示例(用OkHttp,和Pi4J兼容):

依赖添加(Maven示例)

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.3</version>
</dependency>

上传代码

public void uploadImageToAndroid(String localImagePath, String androidDeviceIp) {
    OkHttpClient client = new OkHttpClient();
    File imageFile = new File(localImagePath);

    // 构建表单请求体
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart(
                    "raspberry_image", // 和Android端接收的参数名一致
                    imageFile.getName(),
                    RequestBody.create(MediaType.parse("image/jpeg"), imageFile)
            )
            .build();

    // 构建请求(替换成你的Android设备局域网IP)
    Request request = new Request.Builder()
            .url("http://" + androidDeviceIp + ":8080")
            .post(requestBody)
            .build();

    try (Response response = client.newCall(request).execute()) {
        if (response.isSuccessful()) {
            System.out.println("图像上传成功!");
        } else {
            System.out.println("上传失败,响应码:" + response.code());
        }
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("网络请求失败,请检查Android设备是否在线");
    }
}

3. 关键注意事项

  • 局域网连通性:确保树莓派和Android手机在同一个WiFi网络下,并且Android设备的防火墙没有阻挡8080端口。
  • 服务器生命周期:如果需要后台持续接收图片,建议把服务器放到Service中,避免Activity销毁后服务器停止。
  • 图片压缩:如果生成的图片过大,建议在树莓派端压缩后再上传,避免传输超时或Android端内存溢出。
  • 权限适配:Android 10+如果需要访问外部存储,可能需要额外权限,但我们把图片存到APP私有目录,所以不需要额外申请外部存储权限。

内容的提问来源于stack exchange,提问作者taviP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:02:28