开源 java android app 开发(十)广播机制

Java Android用接口实现广播通知 Android利用Java接口实现广播通知所有界面刷新 立即下载

 文章的目的为了记录使用java 进行android app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

    相关链接:

开源 java android app 开发(一)开发环境的搭建-优快云博客

开源 java android app 开发(二)工程文件结构-优快云博客

开源 java android app 开发(三)GUI界面布局和常用组件-优快云博客

开源 java android app 开发(四)GUI界面重要组件-优快云博客

开源 java android app 开发(五)文件和数据库存储-优快云博客

开源 java android app 开发(六)多媒体使用-优快云博客

开源 java android app 开发(七)通讯之Tcp和Http-优快云博客

开源 java android app 开发(八)通讯之Mqtt和Ble-优快云博客

开源 java android app 开发(九)后台之线程和服务-优快云博客

开源 java android app 开发(十)广播机制-优快云博客

开源 java android app 开发(十一)调试、发布-优快云博客

开源 java android app 开发(十二)封库.aar-优快云博客

开源 java android app 开发(十三)自定义绘图控件--游戏摇杆

开源 java android app 开发(十四)自定义绘图控件--波形图

开源 java android app 开发(十五)自定义绘图控件--仪表盘

开源 java android app 开发(十六)自定义绘图控件--圆环

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-优快云博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-优快云博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-优快云博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-优快云博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-优快云博客

本章节主要内容是广播机制,广播(Broadcast)是Android四大组件之一,用于实现应用程序内部或应用程序之间的消息传递机制。它基于观察者模式,采用发布/订阅模型,能够实现组件间的解耦通信。

广播分为两个主要部分:广播发送者和广播接收者(BroadcastReceiver)。发送者通过Intent发送广播,接收者通过注册监听特定类型的广播来接收消息。

本章内容如下:

1  2个APP之间进行广播通讯。

2  基于服务和广播通讯的网络文件下载。

一、APP之间的广播通讯(APP1和APP2)

1.1 APP1的界面Activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnSendBroadcast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Broadcast"
        android:layout_centerInParent="true"/>
</RelativeLayout>

1.2 APP1的主程序,MainActivity.java

package com.example.Mqtt;


import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;


public class MainActivity extends AppCompatActivity {

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

        Button btnSendBroadcast = findViewById(R.id.btnSendBroadcast);
        btnSendBroadcast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 创建Intent并设置Action
                Intent intent = new Intent("com.example.app1.CUSTOM_BROADCAST");
                // 添加数据
                intent.putExtra("message", "Hello from App1!");
                // 发送广播
                sendBroadcast(intent);
            }
        });
    }
}

1.3  APP2的界面activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tvBroadcastMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Waiting for broadcast..."
        android:layout_centerInParent="true"/>
</RelativeLayout>

1.4  APP2的广播接收类CustomBroadcastReceiver

package com.example.myapplication;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

public class CustomBroadcastReceiver extends BroadcastReceiver {

    private Handler handler;

    public CustomBroadcastReceiver(Handler handler) {
        this.handler = handler;
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        // 获取广播中的消息
        String message = intent.getStringExtra("message");
        // 显示Toast消息
        //Toast.makeText(context, "Received: " + message, Toast.LENGTH_LONG).show();
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 子线程操作
                final String result = message;

                // 通过 Handler 发送消息到主线程
                Message msg = handler.obtainMessage();
                msg.obj = result;
                handler.sendMessage(msg);
            }
        }).start();
    }
}

1.5  APP2的主程序,MainActivity.java

package com.example.myapplication;


import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private CustomBroadcastReceiver receiver;
    TextView textView;
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            String data = (String) msg.obj;
            updateUI(data);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.tvBroadcastMessage);
        // 初始化BroadcastReceiver
        receiver = new CustomBroadcastReceiver(handler);

        // 创建IntentFilter并设置Action
        IntentFilter filter = new IntentFilter("com.example.app1.CUSTOM_BROADCAST");

        // 注册BroadcastReceiver
        registerReceiver(receiver, filter);
    }
    public void updateUI(String data) {
        textView.setText(data);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 注销BroadcastReceiver
        unregisterReceiver(receiver);
    }
}

1.6  2个APP运行的效果,点击APP1的按钮,APP2收到消息。

二、基于服务和广播通讯的网络文件下载。该程序稍微复杂,通过服务实现了用户名和密码登录指定的网站登录,成功后跳转到相应页面下载apk程序。在下载过程中计算下载的文件大小,通过广播,更新主界面的文件下载进度条。下载后可以在文件管理中设置安装。在android studio的 device file Explorer中可以看到下载的文件。(注意下载后需要将文件删除,才能再次下载)

2.1  添加库,build.gradle

implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'com.google.code.gson:gson:2.8.8'

2.2  配置文件中添加权限和服务,

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication" >
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity"
            android:exported="true"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MyService" />
    </application>

</manifest>

2.3  界面文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/messageText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Press buttons to interact with the service"
        android:textSize="18sp"
        android:layout_marginBottom="16dp" />

    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Service"
        android:layout_marginBottom="16dp" />

    <Button
        android:id="@+id/stopButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Service"
        android:layout_marginBottom="16dp" />

    <Button
        android:id="@+id/getMessageButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get Message from Service" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

2.4  服务MyService

package com.example.myapplication;


import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MyService extends Service {

    private static final String TAG = "MyService";
    private final IBinder binder = new LocalBinder(); // Binder 用于通信


    private static final String LOGIN_URL   = "https://www.xxx.com/";
    private static final String exe_URL = "https://xxx.apk";
    private OkHttpClient client;
    long fileSize;
    // 自定义 Binder 类
    public class LocalBinder extends Binder {
        MyService getService() {
            return MyService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "Service bound");
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Service created");

        this.client = new OkHttpClient.Builder()
                .cookieJar(new CookieJar() {
                    private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

                    @Override
                    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                        cookieStore.put(url.host(), cookies);
                    }

                    @Override
                    public List<Cookie> loadForRequest(HttpUrl url) {
                        List<Cookie> cookies = cookieStore.get(url.host());
                        return cookies != null ? cookies : new ArrayList<>();
                    }
                })
                .build();
    }

    public void login() {
        FormBody formBody = new FormBody.Builder()
                .add("inputEmail3", "")
                .add("inputPassword3","")
                .build();

        Request loginRequest = new Request.Builder()
                .url(LOGIN_URL)
                .post(formBody)
                .build();

        client.newCall(loginRequest).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "登录请求失败: " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    Log.d(TAG, "登录成功");
                    String responseData = response.body().string();
                    Log.d(TAG, "登录成功,响应数据: " + responseData);

                    // 登录成功后,跳转到目标网址

                    //redirectToTarget();Login

                    downLoad();
                    /*
                    if (mainActivity != null) {
                        mainActivity.enableDownloadButton();
                        mainActivity.showLoginComplete();
                    }
                    */

                } else {
                    Log.e(TAG, "登录失败,状态码: " + response.code());
                }
            }
        });
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "Service started");
        login();
        return START_NOT_STICKY;
    }

    public void downLoad() {
        Request targetRequest = new Request.Builder()
                //.url(IMG_URL)
                //.url(IMG_URL)
                .url(exe_URL)
                .build();

        client.newCall(targetRequest).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "下载请求失败: " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    fileSize = response.body().contentLength();

                    InputStream inputStream = response.body().byteStream();
                    saveFile(inputStream, "new.apk"); // 保存文件
                    Log.d(TAG, "文件下载成功");

                    //readAndPrintBinaryFile("downloaded_file.zip");
                } else {
                    Log.e(TAG, "下载失败,状态码: " + response.code());
                }
            }
        });
    }


    private void saveFile(InputStream inputStream, String fileName) throws IOException {
        //FileOutputStream outputStream = new FileOutputStream(new File(context.getFilesDir(), fileName));


// 获取 Downloads 目录
        File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
// 创建目标文件
        File outputFile = new File(downloadsDir, fileName);
        // 确保目录存在
        if (!downloadsDir.exists()) {
            downloadsDir.mkdirs();
        }

        // 如果文件已存在,先删除
        if (outputFile.exists()) {
            boolean deleted = outputFile.delete();
            if (!deleted) {
                throw new IOException("无法删除已存在的文件: " + outputFile.getAbsolutePath());
            }
        }


        // 写入文件
        FileOutputStream outputStream = new FileOutputStream(outputFile);

        byte[] buffer = new byte[1024];

        int bytesRead;
        long totalBytesRead = 0;
        int lastProgress = 0;

        while ((bytesRead = inputStream.read(buffer)) != -1) {

            //Log.d(TAG, "写入数据");
            outputStream.write(buffer, 0, bytesRead); // 将文件写入本地
            // 计算并更新进度
            totalBytesRead += bytesRead;
            int progress = (int) ((totalBytesRead * 100) / fileSize);
            if (progress > lastProgress) {
                Log.d(TAG, "进度条:"+ progress);
                lastProgress = progress;
                Intent progressIntent = new Intent(MainActivity.DOWNLOAD_PROGRESS_ACTION);
                progressIntent.putExtra(MainActivity.PROGRESS_KEY, progress);
                sendBroadcast(progressIntent);
            }

        }
        outputStream.close();
        inputStream.close();
        Log.d(TAG, "文件保存成功: " + fileName);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Service destroyed");
    }

    // 服务提供的公共方法
    public String getMessage() {
        return "Hello from Service!";
    }
}

2.5  主程序 MainActivity.java

package com.example.myapplication;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private MyService myService;
    private boolean isBound = false;

    private TextView messageText;
    private Button startButton, stopButton, getMessageButton;


    private ProgressBar progressBar;

    // 定义广播Action
    public static final String DOWNLOAD_PROGRESS_ACTION = "com.example.myapplication.DOWNLOAD_PROGRESS";
    public static final String PROGRESS_KEY = "progress";

    // 广播接收器
    private BroadcastReceiver progressReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction() != null && intent.getAction().equals(DOWNLOAD_PROGRESS_ACTION)) {
                int progress = intent.getIntExtra(PROGRESS_KEY, 0);
                progressBar.setProgress(progress);
                messageText.setText("下载进度: " + progress + "%");
            }
        }
    };



    // ServiceConnection 用于绑定服务
    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "Service connected");
            MyService.LocalBinder binder = (MyService.LocalBinder) service;
            myService = binder.getService();
            isBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "Service disconnected");
            isBound = false;
        }
    };

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

        messageText = findViewById(R.id.messageText);
        startButton = findViewById(R.id.startButton);
        stopButton = findViewById(R.id.stopButton);
        getMessageButton = findViewById(R.id.getMessageButton);

        progressBar = findViewById(R.id.progressBar);

// 注册广播接收器
        IntentFilter filter = new IntentFilter(DOWNLOAD_PROGRESS_ACTION);
        registerReceiver(progressReceiver, filter);


        // 启动服务
        startButton.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, MyService.class);
            startService(intent); // 启动服务
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); // 绑定服务
        });

        // 停止服务
        stopButton.setOnClickListener(v -> {
            if (isBound) {
                unbindService(serviceConnection); // 解绑服务
                isBound = false;
            }
            Intent intent = new Intent(MainActivity.this, MyService.class);
            stopService(intent); // 停止服务
        });

        // 与服务通信
        getMessageButton.setOnClickListener(v -> {
            if (isBound) {
                String message = myService.getMessage();
                messageText.setText(message);
            } else {
                messageText.setText("Service not bound");
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isBound) {
            unbindService(serviceConnection); // 解绑服务
            isBound = false;
        }
    }
}

2.6  APP效果图和文件下载位置

文件下载位置

别再让信号‘撞墙’了!手把手教你用嘉立创阻抗计算器搞定PCB高速线(附免费压层结构选择) 本文详细介绍了如何使用嘉立创阻抗计算器解决PCB高速线设计中的阻抗匹配问题,避免信号反射和传输损耗。通过免费压层结构选择和五步计算法,帮助工程师快速掌握USB3.0差分线等高速信号的设计技巧,提升PCB设计效率和信号质量。 阅读详情

相关推荐

设备树实践:从零构建一个嵌入式板级的设备树描述

本文详细介绍了如何从零开始为嵌入式Linux系统构建设备树(Device Tree),以i.MX6ULL处理器为例,涵盖硬件分析、设备树语法、外设配置及调试技巧。通过实践指导,帮助开发者掌握设备树编写,实现硬件与软件的高效对接,提升嵌入式开发效率。

plum99的博客 305

android java广播,[原]Android应用程序发送广播(sendBroadcast)的过程分析

前面我们分析了Android应用程序注册广播接收器的过程,这个过程只完成了万里长征的第一步,接下来它还要等待ActivityManagerService将广播分发过来。ActivityManagerService是如何得到广播并把它分发出去的呢?这就是本文要介绍的广播发送过程了。广播的发送过程比广播接收器的注册过程要复杂得多了,不过这个过程仍然是以ActivityManagerService为中心...

weixin_33273250的博客 581

【比较器仿真】

比较器tran noise、pnoise仿真、噪声仿真、MC失调仿真

pickweb的博客 1万+

安卓广播防Java单例模式,synchronized关键字的使用。

public final class NotificationReceiver extends BroadcastReceiver { private static final String LOGTAG = LogUtil .makeLogTag(NotificationReceiver.class); private final static Object syncLoc

小单的博客专栏 6万+

深入解析SAP F4帮助函数F4IF_INT_TABLE_VALUE_REQUEST的回调机制

本文深入解析了SAP ABAP开发中F4IF_INT_TABLE_VALUE_REQUEST函数的回调机制。通过剖析其工作原理与核心参数,详细阐述了如何利用回调函数实现F4帮助的多值返回、动态数据过滤及选择后校验等高级定制功能,并提供了实用的代码示例与调试技巧,帮助开发者高效应对复杂的屏幕交互需求。

weixin_29213827的博客 198

NSFC结题报告下载脚本失效?3步教你手动修复下载按钮问题(2024最新版)

针对NSFC官网域名变更导致结题报告下载脚本失效的问题,本文提供了详细的手动修复指南。通过三步操作,教你如何修改用户脚本的域名匹配规则,恢复下载按钮功能,确保NSFC结题报告下载器能继续高效工作。

vscode6remote的博客 751

细说android广播机制(java)

文章目录关于系统广播系统广播所发生的更改(系统升级变化)接收广播清单声明的接收器上下文注册的接收器发送广播安全注意事项和最佳做法举例 Android 应用与 Android 系统和其他 Android 应用之间可以相互收发广播消息,这与发布-订阅设计模式相似。这些广播会在所关注的事件发生时发送。举例来说,Android 系统会在发生各种系统事件时发送广播,例如系统启动或设备开始充电时。再比如,应用可以发送自定义广播来通知其他应用它们可能感兴趣的事件(例如,一些新数据已下载)。 应用可以注册接收特定的广播。广

性感的小君君 929

Python Trimesh库实战:5分钟搞定STL文件解析与3D模型可视化

本文介绍了如何使用Python的Trimesh库快速解析STL文件并进行3D模型可视化。通过简洁的代码示例,演示了从环境搭建、模型加载、几何数据提取到基础变换和批量处理的核心流程,帮助开发者和工程师在5分钟内高效完成3D数据处理与可视化任务。

weixin_32005771的博客 159

开源 java android app 开发(七)通讯之Tcp和Http

本文记录了作者从嵌入式软件开发转向Android应用开发的经历,重点介绍了使用Java进行Android开发的学习过程。文章详细描述了开发环境的搭建、工程文件结构、GUI界面布局、文件和数据库存储、多媒体使用等关键步骤,并特别强调了网络通讯协议(如TCP和HTTP)在Android应用中的实际应用。作者通过代码示例展示了如何实现TCP客户端与服务器的通信以及HTTP请求的处理,包括权限配置、界面设计和代码实现。此外,文章还探讨了Android网络安全配置的相关问题,并提供了解决方案。通过这些内容,作者希望记

ajassi2000的博客 1307

springboot+vue项目基础开发(12)vue项目的搭建

在src目录下新建 api,utils,views文件夹。删除componets目录下自动生成的所有文件。在utils文件夹下创建request.js。启动项目,记得是要在管理员下启动。

m0_58498702的博客 152

Windows11配置WSL2支持代理上网

说起来本来这个功能我也不需要的,只是最近突然有个需求就顺便研究了下,WSL2默认的网络方式是NAT,即WSL2的网卡本身是虚拟网卡,通过以太网或WIFI的地址转换来上互联网,我试了下是不能直接走代理的,最近比较忙没具体研究,但是我用另一种方式实现了,下面介绍给需要的人。注意:这个方法只能是WIndows11系统,WIndows10系统上的WSL2缺少了一项功能导致不可用。1、方法总体没什么难度,NAT方式暂时没研究透,后续有时间再研究2、WIndows10系统不支持mirrored,暂时需要另辟蹊径。

jiexijihe945的博客 9590

开源 java android app 开发(九)后台之线程和服务

本文记录了Java开发Android App学习经历,重点讲解了后台程序的实现。主要内容包括: 线程与通讯 - 使用Thread、Handler和Looper实现后台线程与主线程通信,通过示例展示了进度条更新功能 服务Service - 详细介绍了Service的创建、绑定及使用方法,包括: Service生命周期管理 Activity与Service的绑定通信 后台任务处理机制 文章提供了完整的代码示例,涵盖XML布局文件、Service实现和Activity交互,适合Android初学者学习后台开发技术

ajassi2000的博客 835

使用 Simulink 进行电力电子系统的效率优化仿真

电力电子系统(Power Electronics System)是现代电力系统和工业自动化中的关键组成部分,广泛应用于可再生能源发电、电动汽车、不间断电源(UPS)、电机驱动等领域。为了提高系统的整体性能和经济性,必须对电力电子系统的效率进行优化。效率优化的目标是最大化系统的能量转换效率,减少损耗,从而提高系统的可靠性和经济效益。Simulink 提供了一个强大的仿真环境,可以用来设计、分析和验证电力电子系统的效率优化策略。本教程将详细介绍如何使用 Simulink 进行电力电子系统的效率优化仿真。

xiaoheshang_123的博客 355

开源 java android app 开发(八)通讯之Mqtt和Ble

本文记录了作者从嵌入式软件开发转向Android应用开发的学习经历,重点介绍了使用Java进行Android开发的关键步骤和技术要点。文章详细描述了开发环境的搭建、工程文件结构、GUI界面布局、常用组件、文件与数据库存储、多媒体使用等内容。特别强调了MQTT和BLE通讯协议的实现,包括MQTT服务器的连接、消息的发送与接收,以及BLE设备的搜索与连接。通过代码示例和配置说明,作者分享了实际开发中的经验与技巧,旨在帮助读者快速掌握Android应用开发的核心技术。

ajassi2000的博客 1047

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

android 广播解绑,【安卓开发系列 -- APP】APP 开发基础技术整理

【安卓开发系列 -- APP】APP 开发基础技术整理【1】Android Studio APP 项目目录布局【2】活动的生命周期活动的状态 :1. 运行状态,一个活动位于返回栈栈顶时,活动处于运行状态;2. 暂停状态,一个活动不再处于栈顶,但仍然可见;3. 停止状态,一个活动完全不处于栈顶并且完全不可见;4. 销毁状态,一个活动从栈顶移除;活动的启动模式1. Standard,在不进行显示指定的...

weixin_30824391的博客 261

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【安卓开发系列 -- APP】APP 开发基础技术整理

【安卓开发系列 -- APP】APP 开发基础技术整理 【1】Android Studio APP 项目目录布局 【2】活动的生命周期 活动的状态 : 1. 运行状态,一个活动位于返回栈栈顶时,活动处于运行状态; 2. 暂停状态,一个活动不再处于栈顶,但仍然可见; 3. 停止状态,一个活动完全不处于栈顶并且完全不可见; 4. 销毁状态,一个活动从...

CopperSun 技术博客 872

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

开源 java android app 开发(十一)调试、发布

本文记录了一个嵌入式开发人员转学Android应用开发的经历,主要介绍了使用手机调试和生成APK安装包的方法。调试部分详细说明了如何开启手机开发者选项和USB调试模式。APK生成部分则讲解了编译流程和输出文件位置。文章还列出了完整的Java Android开发学习系列链接,涵盖环境搭建、GUI设计、数据存储、网络通讯等核心内容,并推荐了相关的C#.NET开发教程。这些技术笔记既是对学习过程的总结,也为其他开发者提供了实用参考。

ajassi2000的博客 682

开源 java android app 开发(四)GUI界面重要组件

本文记录了作者从嵌入式软件开发转向Android应用开发的学习经历,重点介绍了在Java环境下使用Android Studio开发应用时涉及的三个重要GUI组件:TabLayout、RecyclerView和BottomNavigationView。TabLayout用于分页显示,RecyclerView用于列表显示并支持点击事件,BottomNavigationView用于底部导航栏。文章详细描述了每个组件的实现步骤,包括创建布局文件、活动代码、适配器以及如何在主活动中集成这些组件。通过具体的代码示例和操

ajassi2000的博客 911

Android详细开发教程,本文章将带你更深入的学习安卓开发

安卓开发是一项充满挑战和乐趣的技能,它可以让你创建各种类型的移动应用,从简单的工具到复杂的游戏,本文章将为你提供一个详细的学习路线,参考内容,应用场景,实用案例及代码示例,以及一些优秀的GitHub开源项目,帮助你深入掌握安卓开发!

HSX的博客 4719

开源 java android app 开发(一)开发环境的搭建

本文记录了作者从嵌入式软件开发转向Android应用开发的学习经历,重点介绍了Android Studio开发环境的安装与配置过程。文章详细描述了IDE的安装、SDK的安装与配置、环境设置以及Gradle的配置,特别是解决了由于jcenter网站关闭导致的证书错误问题,通过添加阿里云等国内镜像库来确保依赖库的正常拉取。此外,还提到了使用国内镜像加速Gradle的下载,以提高开发效率。本文旨在为遇到类似问题的开发者提供参考和解决方案。

ajassi2000的博客 703

开源 java android app 开发(六)多媒体使用

本文记录了作者从嵌入式软件开发转向Android应用开发的经历,重点介绍了使用Java进行Android应用开发的学习过程。文章详细描述了开发环境的搭建、工程文件结构、GUI界面布局及常用组件的使用,以及文件和数据库存储的实现。此外,文章还涵盖了多媒体功能的使用,包括访问手机相册、播放音频和视频的具体实现步骤。通过代码示例和详细说明,作者旨在帮助读者快速掌握Android应用开发的关键技术,并提供了相关开发资源的链接以供参考。

ajassi2000的博客 1039

开源 java android app 开发(十八)最新编译器Android Studio 2025.1.3.7

本文记录了从嵌入式开发转向Android应用开发的学习过程,重点讲解了最新版Android Studio 2025.1.3.7的使用经验。主要内容包括:1)创建Java工程时的语言选择注意事项;2)新版gradle面板设置及混淆封装aar的方法;3)aar库的使用步骤。文中特别强调了新版IDE的配置变化,如gradle面板默认不显示封装库栏目等问题,并提供了解决方案。文章还列出了作者完整的Android开发学习系列文章链接,涵盖环境搭建、UI设计、数据存储、网络通信等全方位内容。

ajassi2000的博客 4618

开源 java android app 开发(十二)封库.aar

本文记录了Java Android开发中打包封库的过程,主要解决两种情况:1)简化编译流程时封装不需修改的代码;2)提供SDK时保护源码。通过创建Library模块(包含AddFun和MulFun两个计算类),修改build.gradle开启代码混淆生成.aar库文件。测试工程通过修改gradle配置引入该库,在MainActivity成功调用库中的加减法功能并输出结果,验证了.aar库的有效性。该方案既能提高开发效率,又能实现代码保护。(149字)

ajassi2000的博客 1254

开源 java android app 开发(十三)自定义绘图控件--游戏摇杆

摘要:本文记录了嵌入式开发者临时转战Android应用开发的经历,重点讲解了如何通过Java自定义摇杆控件。文章详细阐述了使用Canvas和Paint类进行绘图的基础知识,并完整展示了摇杆控件的实现过程,包括:1)继承View类创建自定义控件;2)处理触摸事件实现拖动效果;3)添加属性文件支持XML参数配置;4)设计回调接口供外部使用。该摇杆控件可用于机器人/无人机控制等场景,文中还提供了完整的代码实现和效果展示。作为系列教程的第13篇,本文帮助开发者快速掌握Android自定义控件的开发技巧。

ajassi2000的博客 1024

开源 java android app 开发(三)GUI界面布局和常用组件

本文记录了作者从嵌入式软件开发转向Java Android应用开发的学习经历。主要内容集中在GUI界面的布局设计和常用组件的使用,如LinearLayout和TableLayout等布局方法,以及TextView、Button等组件。文章详细描述了如何使用设计器进行界面布局,包括组件的拖放和属性设置,如layout_width和layout_height的配置。此外,还介绍了如何通过代码实现组件间的交互,如按钮点击后修改文本框内容。整体上,文章旨在为初学者提供Android应用开发的基础知识和实用技巧。

ajassi2000的博客 603

开源 java android app 开发(二)工程文件结构

本文记录了作者从嵌入式软件开发转向Android应用开发的经历,重点介绍了Android应用开发中的主要文件和文件夹结构。文章详细描述了权限文件(AndroidManifest.xml)的配置,包括权限管理和界面设置,如横屏显示和隐藏标题栏。此外,还介绍了界面文件夹(XML文件用于GUI设计)、活动文件夹(Java文件,主活动开始执行点)和资源文件夹(包含图片、图标、颜色、字符串等资源)。这些内容旨在帮助开发者快速定位和管理应用开发中的关键组件和资源。

ajassi2000的博客 532
上一篇: 开源 java android app 开发(九)后台之线程和服务
下一篇: 开源 java android app 开发(十一)调试、发布
ajassi2000
博客等级 码龄22年 2033粉丝 191原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值