主頁 > 移動端開發 > 安卓學習筆記40:基于套接字網路編程

安卓學習筆記40:基于套接字網路編程

2021-01-03 10:26:17 移動端開發

文章目錄

  • 零、學習目標
  • 一、Socket概述
    • (一)兩種傳輸模式
    • (二)基于Socket網路編程
  • 三、案例演示 - C/S架構聊天室
    • (一)運行效果
    • (二)涉及知識點
    • (三)實作步驟
      • 1、創建聊天服務器端
        • (1)創建Java專案 - ChatServer
        • (2)創建聊天服務視窗類 - ChatServerWindow
        • (3)啟動應用,查看效果
      • 2、創建聊天安卓客戶端
        • (1)創建安卓應用【ChatAndroidClient】
        • (2)將圖片素材拷貝到drawable目錄
        • (3)創建接收按鈕背景選擇器
        • (4)創建發送按鈕背景選擇器
        • (5)主布局資源檔案activity_main.xml
        • (6)字串資源檔案strings.xml
        • (7)在專案清單檔案里授權訪問因特網
        • (8)主界面類 - MainActivity
      • 3、啟動聊天服務器端與安卓客戶端進行測驗
        • (1)啟動聊天服務器端
        • (2)啟動聊天安卓客戶端
        • (3)演示服務器端與安卓客戶端進行聊天

零、學習目標

  1. 了解基于套接字網路有兩種傳輸模式
  2. 掌味訓于TCP/IP協議的套接字網路編程

一、Socket概述

Socket(套接字)是一種通信機制,可以實作單機或跨網路進行通信,其創建需要明確的區分C(客戶端)/S(服務器端),支持多個客戶端連接到同一個服務器,

(一)兩種傳輸模式

  1. 面向連接的傳輸:基于TCP協議,可靠性高,但效率低
  2. 面向無連接的傳輸:基于UDP協議,可靠性低,但效率高

(二)基于Socket網路編程

  • 在安卓中,直接采用Socket通信應該是我們遇到的最低級的網路運用,盡管已經作了很大程度的抽象,但是純粹的Socket通信,仍然給開發者留下很多細節需要處理,尤其在服務器端,開發者需要處理多執行緒以及資料緩沖等的設計問題,相對而言,處于更高抽象層的HTTP等,已經對Socket通信中需要處理的技術細節進行了很好的封裝,開發者無須關心,因此,HTTP在網路開發中通常具有決定性的優勢,

  • ServerSocket(int aport):創建一個系結到本機指定埠的服務端Socket;aport就是指定的本機埠,與上述客戶端Socket對應,通過TCP連接時,ServerSocket創建后需要在aport埠上進行監聽,等待客戶端的連接,

三、案例演示 - C/S架構聊天室

(一)運行效果

在這里插入圖片描述

(二)涉及知識點

  1. Swing視窗(JFrame)
  2. Swing文本區(JTextArea)
  3. Swing按鈕(JButton)
  4. Java事件處理機制
  5. 資料位元組輸入流(DataInputStream)
  6. 資料位元組輸出流(DataOutputStream)
  7. 活動視窗(Activity)
  8. 標簽(TextView)
  9. 按鈕(Button)
  10. 編輯框(EditText)
  11. 服務器套接字(ServerSocket)
  12. 套接字(Socket)
  13. 訊息處理器(Handler)
  14. 執行緒(Thread)

(三)實作步驟

1、創建聊天服務器端

(1)創建Java專案 - ChatServer

在這里插入圖片描述

(2)創建聊天服務視窗類 - ChatServerWindow

在這里插入圖片描述

package net.hw.chat;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 功能:聊天服務視窗類
 * 作者:華衛
 * 日期:2021年01月01日
 */
public class ChatServerWindow extends JFrame {

    /**
     * 定義埠號常量
     */
    static final int PORT = 8888;

    private JButton btnClose;
    private JButton btnSend;
    /**
     * 資料輸入流
     */
    private DataInputStream netIn;
    /**
     * 資料輸出流
     */
    private DataOutputStream netOut;

    private JScrollPane panContent;
    private JScrollPane panInput;
    private JPanel panel1;
    private JPanel panel2;

    /**
     * 服務器端套接字
     */
    private static ServerSocket ss;
    /**
     * 客戶端套接字
     */
    private static Socket socket;

    /**
     * 聊天資訊串列
     */
    private JTextArea txtChatMessageList;
    /**
     * 聊天資訊輸入框
     */
    private JTextArea txtInputMessage;

    /**
     * 來自客戶端的訊息
     */
    private static String clientMsg;
    /**
     * 服務器端的訊息
     */
    private static String serverMsg;
    /**
     * 執行緒回圈控制變數
     */
    private static boolean isRunning;

    public static void main(String[] args) {
        new ChatServerWindow();
    }

    /**
     * 構造方法
     */
    public ChatServerWindow() {

        super("聊天服務器端");

        initUI();

        try {
            // 創建服務器端套接字
            ss = new ServerSocket(PORT);
            txtChatMessageList.append("服務器已啟動...\n");
            txtChatMessageList.append("等待客戶請求...\n");

            isRunning = true;

            new Thread(new Runnable() {

                @Override
                public void run() {

                    while (isRunning) {

                        try {
                            // 監聽其它設備的連接請求,處于阻塞狀態
                            socket = ss.accept();
                            if (!txtChatMessageList.getText().toString()
                                    .contains("連接了一個客戶端,")) {
                                txtChatMessageList.append("連接了一個客戶端,\n");
                            }
                            netIn = new DataInputStream(socket.getInputStream());
                            netOut = new DataOutputStream(socket
                                    .getOutputStream());

                            // 初始化服務器端訊息
                            if (null == serverMsg || serverMsg.equals("")) {
                                serverMsg = "歡迎您,新朋友! ";
                            }

                            // 獲取輸出流(套接字輸出流-->資料輸出流)
                            netOut = new DataOutputStream(socket
                                    .getOutputStream());
                            // 向客戶端輸出資訊
                            netOut.writeUTF(serverMsg);
                            // 清空輸出流緩沖資料
                            netOut.flush();

                            // 獲取客戶端訊息
                            displayClientMsg();
                        } catch (IOException e) {
                        }
                    }
                }

            }).start();
        } catch (IOException e1) {

        }

        /* 給各個控制元件注冊監聽器,撰寫事件代碼 */

        btnSend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    serverMsg = txtInputMessage.getText();
                    if (!serverMsg.trim().equals("")) {
                        txtChatMessageList.append("服務器>>>" + serverMsg + "\n");
                        if (netOut != null) {
                            netOut.writeUTF(serverMsg);
                        }
                    } else {
                        JOptionPane.showMessageDialog(null, "不能發送空資訊!", "服務器",
                                JOptionPane.WARNING_MESSAGE);
                    }

                    txtInputMessage.setText("");
                    txtInputMessage.requestFocus();
                } catch (IOException ie) {
                }
            }
        });

        // 給關閉按鈕注冊監聽器
        btnClose.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                releaseResource();
                System.exit(0);
            }
        });

        // 給視窗注冊監聽器
        addWindowListener(new WindowAdapter() {
            public void windowActivated(WindowEvent e) {
                txtInputMessage.requestFocus();
            }

            public void windowClosing(WindowEvent e) {
                releaseResource();
                System.exit(0);
            }
        });
    }

    /**
     * 釋放資源
     */
    private void releaseResource() {
        isRunning = false;
        try {
            if (netIn != null && netOut != null) {
                netIn.close();
                netOut.close();
            }
            if (socket != null && !socket.isClosed()) {
                socket.close();
            }
            if (ss != null && !ss.isClosed()) {
                ss.close();
            }
        } catch (IOException e) {
        }
    }

    /**
     * 初始化用戶界面
     */
    private void initUI() {
        // 創建組件
        panel1 = new JPanel();
        panel2 = new JPanel();
        txtChatMessageList = new JTextArea(15, 60);
        txtInputMessage = new JTextArea(3, 60);
        panContent = new JScrollPane(txtChatMessageList,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        panInput = new JScrollPane(txtInputMessage,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        btnClose = new JButton("關閉");
        btnSend = new JButton("發送");

        // 添加組件
        getContentPane().add(panContent, "Center");
        getContentPane().add(panel1, "South");
        panel1.setLayout(new GridLayout(0, 1));
        panel1.add(panInput);
        panel1.add(panel2);
        panel2.add(btnSend);
        panel2.add(btnClose);

        // 設定組件屬性
        txtChatMessageList.setEditable(false);
        txtChatMessageList.setFont(new Font("宋體", Font.PLAIN, 13));
        txtInputMessage.setFont(new Font("宋體", Font.PLAIN, 15));
        txtChatMessageList.setLineWrap(true);
        txtInputMessage.setLineWrap(true);
        txtInputMessage.requestFocus();
        setSize(450, 350);
        setLocation(50, 200);
        setResizable(false);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    // 顯示客戶端資訊
    void displayClientMsg() {
        try {
            clientMsg = netIn.readUTF();
            txtChatMessageList.append("客戶端>>>" + clientMsg + "\n");
        } catch (IOException e) {
        }
    }
}

(3)啟動應用,查看效果

在這里插入圖片描述
在這里插入圖片描述

2、創建聊天安卓客戶端

(1)創建安卓應用【ChatAndroidClient】

在這里插入圖片描述
在這里插入圖片描述

(2)將圖片素材拷貝到drawable目錄

在這里插入圖片描述

(3)創建接收按鈕背景選擇器

在這里插入圖片描述

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/receive" android:state_pressed="false"/>
    <item android:drawable="@drawable/receive_pressed" android:state_pressed="true"/>
</selector>

(4)創建發送按鈕背景選擇器

在這里插入圖片描述

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/send" android:state_pressed="false"/>
    <item android:drawable="@drawable/send_pressed" android:state_pressed="true"/>
</selector>

(5)主布局資源檔案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:background="@drawable/background"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tvHost"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/host"
            android:textColor="#0000ff"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/edtHost"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="#ffffff"
            android:padding="5dp"
            android:singleLine="true"
            android:textColor="#000000"
            android:textSize="20sp" />
    </LinearLayout>

    <Button
        android:id="@+id/btnReceiveMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:background="@drawable/btn_receive_selector" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/edtMessage"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_weight="4"
            android:hint="@string/input_message"
            android:paddingLeft="5dp"
            android:singleLine="true"
            android:textColor="#000000"
            android:textSize="20sp" />

        <Button
            android:id="@+id/btnSendMessage"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:layout_weight="1"
            android:background="@drawable/btn_send_selector"
            android:textSize="18sp" />
    </LinearLayout>

    <EditText
        android:id="@+id/edtMessageList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="false"
        android:gravity="left|top"
        android:inputType="textMultiLine|none"
        android:scrollbars="vertical"
        android:textSize="18sp">
        <requestFocus />
    </EditText>
</LinearLayout>

(6)字串資源檔案strings.xml

在這里插入圖片描述

<resources>
    <string name="app_name">聊天安卓客戶端</string>
    <string name="host">服務器地址:</string>
    <string name="input_message">請輸入聊天內容</string>
</resources>

(7)在專案清單檔案里授權訪問因特網

在這里插入圖片描述

(8)主界面類 - MainActivity

在這里插入圖片描述

package net.hw.chat_android_client;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 功能:安卓聊天客戶端
 * 作者:華衛
 * 日期:2021年01月01日
 */
public class MainActivity extends AppCompatActivity {
    /**
     * 發送資訊按鈕
     */
    private Button btnSendMessage;
    /**
     * 接收資訊按鈕
     */
    private Button btnReceiveMessage;
    /**
     * 訊息編輯框
     */
    private EditText edtMessage;
    /**
     * 客戶端套接字
     */
    private Socket socket;

    /**
     * 訊息處理器(發送與處理訊息)
     */
    private Handler handler;
    /**
     * 服務器埠號
     */
    private static final int PORT = 8888;
    /**
     * 服務器端主機地址
     */
    private String host;
    /**
     * 初始化網路連接的執行緒
     */
    private Thread initNetworkThread;
    /**
     * 聊天訊息構建器
     */
    private StringBuilder chatMesssageBuilder;
    /**
     * 聊天資訊串列編輯框
     */
    private EditText edtMessageList;
    /**
     * 服務器地址
     */
    private EditText edtHost;
    /**
     * 資料輸出流
     */
    private static DataOutputStream netOut;
    /**
     * 資料輸入流
     */
    private static DataInputStream netIn;
    /**
     * 來自客戶端的訊息
     */
    private static String clientMsg;
    /**
     * 服務器端的訊息
     */
    private static String serverMsg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 利用布局資源檔案設定用戶界面
        setContentView(R.layout.activity_main);

        // 通過資源索引獲得界面控制元件實體
        btnSendMessage = findViewById(R.id.btnSendMessage);
        btnReceiveMessage = findViewById(R.id.btnReceiveMessage);
        edtMessage = findViewById(R.id.edtMessage);
        edtMessageList = findViewById(R.id.edtMessageList);
        edtHost = findViewById(R.id.edtHost);

        // 設定服務器地址
        edtHost.setText("192.168.1.5");

        // 實體化聊天訊息構建器
        chatMesssageBuilder = new StringBuilder();

        // 給發送按鈕注冊監聽器
        btnSendMessage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendMessage(); // 發送訊息
            }
        });

        // 給接收按鈕注冊監聽器
        btnReceiveMessage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                receiveMessage(); // 接收訊息
            }
        });

        // 給訊息編輯框注冊監聽器
        edtMessage.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_ENTER) {
                    sendMessage(); // 收發訊息
                }
                return false;
            }
        });

        // 創建訊息處理器
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == 0x001) {
                    // 設定聊天資訊串列內容
                    edtMessageList.setText(chatMesssageBuilder.toString());
                    // 清空輸入框
                    edtMessage.setText("");
                }
            }
        };
    }

    /**
     * 接收訊息:接收來自服務器端的訊息
     */
    private void receiveMessage() {
        new Thread() {
            @Override
            public void run() {
                // 獲取主機
                host = edtHost.getText().toString();

                // 非空校驗
                if (host.length() == 0) {
                    Toast.makeText(MainActivity.this, "請輸入服務器地址!", Toast.LENGTH_LONG);
                    return;
                }

                // 采用短連接,接收一次訊息,立馬斷開連接
                try {
                    // 創建客戶端套接字
                    socket = new Socket(host, PORT);

                    // 接收服務器端發送的訊息
                    netIn = new DataInputStream(socket.getInputStream());
                    // 從資料輸入流讀取內容
                    serverMsg = netIn.readUTF();

                    // 在聊天資訊串列里添加服務器端的資訊
                    chatMesssageBuilder.append("服務器>>>" + serverMsg + "\n");

                    // 發送訊息
                    handler.sendEmptyMessage(0x001);

                    // 關閉輸入流
                    netIn.close();
                    // 關閉客戶端套接字
                    socket.close();
                } catch (UnknownHostException e) {
                    Toast.makeText(MainActivity.this, "未知的主機例外!",
                            Toast.LENGTH_LONG).show();
                } catch (IOException e) {
                    Toast.makeText(MainActivity.this, "輸入輸出例外!",
                            Toast.LENGTH_LONG).show();
                }
            }
        }.start();
    }

    /**
     * 發送訊息:向服務器端發送訊息
     */
    private void sendMessage() {
        // 啟動子執行緒,執行發送聊天內容
        new Thread() {
            @Override
            public void run() {
                // 獲取主機
                host = edtHost.getText().toString();

                // 非空校驗
                if (host.length() == 0) {
                    Toast.makeText(MainActivity.this, "請輸入服務器地址!",
                            Toast.LENGTH_LONG);
                    return;
                }

                // 采用短連接,發送一次訊息,立馬斷開連接
                try {
                    // 創建客戶端套接字
                    socket = new Socket(host, PORT);

                    // 向服務器端發送資訊
                    netOut = new DataOutputStream(socket.getOutputStream());
                    // 獲取客戶端訊息
                    clientMsg = edtMessage.getText().toString();
                    // 不允許發送空訊息給服務器端
                    if (clientMsg.length() == 0) {
                        return;
                    }
                    // 向服務器端發送訊息
                    netOut.writeUTF(clientMsg);
                    // 清空輸出流緩沖資料
                    netOut.flush();

                    // 添加客戶端資訊
                    chatMesssageBuilder.append("客戶端>>>" + clientMsg + "\n");

                    // 發送訊息
                    handler.sendEmptyMessage(0x001);

                    // 關閉輸出流
                    netOut.close();
                    // 關閉客戶端套接字
                    socket.close();
                } catch (UnknownHostException e) {
                    Toast.makeText(MainActivity.this, "未知的主機例外!",
                            Toast.LENGTH_LONG).show();
                } catch (IOException e) {
                    Toast.makeText(MainActivity.this, "輸入輸出例外!",
                            Toast.LENGTH_LONG).show();
                }
            }
        }.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (socket != null) {
            try {
                // 關閉套接字
                socket.close();
            } catch (Exception e) {
                System.out.println("例外:無法關閉Socket!");
            }
        }
    }
}

在這里插入圖片描述

在這里插入圖片描述

3、啟動聊天服務器端與安卓客戶端進行測驗

(1)啟動聊天服務器端

在這里插入圖片描述

(2)啟動聊天安卓客戶端

在這里插入圖片描述

(3)演示服務器端與安卓客戶端進行聊天

在這里插入圖片描述
在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/243867.html

標籤:其他

上一篇:2020ICPC濟南 G.Xor Transformation(思維,異或)

下一篇:Android四大組件系列9 深入理解Context

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more