成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

如何用HMSNearbyService給自己的App添加近距離數(shù)據(jù)傳輸功能

這篇文章將為大家詳細(xì)講解有關(guān)如何用HMS Nearby Service給自己的App添加近距離數(shù)據(jù)傳輸功能,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

超過(guò)10余年行業(yè)經(jīng)驗(yàn),技術(shù)領(lǐng)先,服務(wù)至上的經(jīng)營(yíng)模式,全靠網(wǎng)絡(luò)和口碑獲得客戶(hù),為自己降低成本,也就是為客戶(hù)降低成本。到目前業(yè)務(wù)范圍包括了:網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè),成都網(wǎng)站推廣,成都網(wǎng)站優(yōu)化,整體網(wǎng)絡(luò)托管,成都微信小程序,微信開(kāi)發(fā),成都App定制開(kāi)發(fā),同時(shí)也可以讓客戶(hù)的網(wǎng)站和網(wǎng)絡(luò)營(yíng)銷(xiāo)和我們一樣獲得訂單和生意!

??當(dāng)你給朋友發(fā)送手機(jī)資料時(shí),過(guò)了很久進(jìn)度條卻動(dòng)也不動(dòng);當(dāng)你想發(fā)送大文件給同事時(shí),僅一個(gè)文件就用光了你所有流量;當(dāng)你跟朋友乘坐飛機(jī)時(shí)想一起玩游戲時(shí),卻因沒(méi)有網(wǎng)絡(luò)無(wú)奈放棄。??

我們生活中似乎經(jīng)常能遇到這種尷尬的場(chǎng)景,近距離數(shù)據(jù)傳輸功能是用戶(hù)的一個(gè)痛點(diǎn)?,F(xiàn)在,只需要接入華為近距離通信服務(wù),通過(guò)Nearby Connection便可以輕松實(shí)現(xiàn)設(shè)備間的數(shù)據(jù)傳輸,傳輸類(lèi)型支持短文本、流數(shù)據(jù)和文件數(shù)據(jù)等類(lèi)型,可幫助app實(shí)現(xiàn)本地多人游戲、實(shí)時(shí)協(xié)作、多屏游戲和離線(xiàn)文件傳輸?shù)裙δ堋O聢D是功能演示:

如何用HMS Nearby Service給自己的App添加近距離數(shù)據(jù)傳輸功能

  如果你對(duì)實(shí)現(xiàn)方式感興趣,可以在Github上下載源碼:
   https://github.com/HMS-Core/hms-nearby-demo/tree/master/NearbyConnection

??首先需要了解Nearby Connection 開(kāi)發(fā)流程

如何用HMS Nearby Service給自己的App添加近距離數(shù)據(jù)傳輸功能

1. 業(yè)務(wù)流程

??整體流程可以劃分為4個(gè)階段。

  廣播掃描階段:廣播端啟動(dòng)廣播,發(fā)現(xiàn)端啟動(dòng)掃描以發(fā)現(xiàn)廣播端。

  1. 廣播端調(diào)用startBroadcasting()啟動(dòng)廣播。

  2. 發(fā)現(xiàn)端調(diào)用startScan()啟動(dòng)掃描以發(fā)現(xiàn)附近的設(shè)備。

  3. 由onFound()方法通知掃描結(jié)果。

  建立連接階段:發(fā)現(xiàn)端發(fā)起連接并啟動(dòng)對(duì)稱(chēng)的身份驗(yàn)證流程,雙端獨(dú)立接受或拒絕連接請(qǐng)求。

  1. 發(fā)現(xiàn)端調(diào)用requestConnect()向廣播端發(fā)起連接請(qǐng)求。

  2. 兩端由onEstablish()通知連接啟動(dòng)后,均可以調(diào)用acceptConnect()接受連接或調(diào)用rejectConnect()拒絕連接。

  3. 兩端由onResult()通知連接結(jié)果。僅當(dāng)兩端都接受連接時(shí),連接才能建立。

  傳輸數(shù)據(jù)階段:建立連接后,雙端進(jìn)行數(shù)據(jù)交換。

  1. 連接建立后,雙端均可以調(diào)用sendData()發(fā)送數(shù)據(jù)給對(duì)端。

  2. 接收數(shù)據(jù)的一端由onReceived()通知接收到數(shù)據(jù);兩端由onTransferUpdate()通知當(dāng)前的傳輸狀態(tài)。

  斷開(kāi)連接階段:雙端任意一端發(fā)起斷開(kāi)連接,通知對(duì)端連接斷開(kāi)。

  1. 主動(dòng)斷開(kāi)連接的一端調(diào)用disconnect()斷開(kāi)連接,對(duì)端由onDisconnected()通知連接斷開(kāi)。

2. 開(kāi)發(fā)步驟

2.1 開(kāi)發(fā)準(zhǔn)備

??如果你以前沒(méi)有集成華為移動(dòng)服務(wù)的經(jīng)驗(yàn),那么需要先配置AppGallery Connect,開(kāi)通近距離通信服務(wù)并集成HMS SDK。相關(guān)步驟請(qǐng)參考官方文檔。

2.2 聲明系統(tǒng)權(quán)限

??Nearby Connection開(kāi)發(fā)場(chǎng)景需要使用Nearby Discovery API和Nearby Transfer API,你的應(yīng)用必須根據(jù)所使用的策略聲明適當(dāng)?shù)臋?quán)限。例如:使用POLICY_STAR策略開(kāi)發(fā)文件傳輸?shù)膽?yīng)用,需要添加特定的權(quán)限到AndroidManifest.xml:

<!-- Required for Nearby Discovery and Nearby Transfer --> 
<uses-permission android:name="android.permission.BLUETOOTH" /> 
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />   
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />    
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<!-- Required for FILE payloads --> 
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

??由于ACCESS_FINE_LOCATION,WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE 是危險(xiǎn)的系統(tǒng)權(quán)限,因此,必須動(dòng)態(tài)的申請(qǐng)這些權(quán)限。如果權(quán)限不足,近距離通信服務(wù)(Nearby Service)將會(huì)拒絕應(yīng)用開(kāi)啟廣播或者開(kāi)啟發(fā)現(xiàn)。

2.3 選擇策略

??Nearby Discovery支持3種不同的連接策略:POLICY_MESH,POLICY_STAR和POLICY_P2P??梢愿鶕?jù)應(yīng)用場(chǎng)景優(yōu)選策略。

??策略選擇并創(chuàng)建BroadcastOption對(duì)象的示例代碼如下:

Policy policy = Policy.POLICY_STAR;  
BroadcastOption broadcastOption = new BroadcastOption.Builder().setPolicy (policy).build();

2.4 廣播和掃描

??一旦授予應(yīng)用所需的權(quán)限,并為應(yīng)用選擇一個(gè)策略,就可以開(kāi)始廣播和掃描以發(fā)現(xiàn)附近的設(shè)備。

2.4.1  啟動(dòng)廣播

??廣播端以選定的policy和serviceId為參數(shù),調(diào)用startBroadcasting()啟動(dòng)廣播。其中serviceId應(yīng)該唯一標(biāo)識(shí)的應(yīng)用。建議使用應(yīng)用的包名作為serviceId(例如:com.huawei.example.myapp)。示例代碼如下:

private void doStartBroadcasting() {
    Policy policy = Policy.POLICY_STAR;
    BroadcastOption broadcastOption = new BroadcastOption.Builder().setPolicy(policy).build();
    Nearby.getDiscoveryEngine(getApplicationContext())
            .startBroadcasting(name, serviceId, connectCallback, broadcastOption)
            .addOnSuccessListener(
                    new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {
                            /* We are broadcasting. */
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(Exception e) {
                            /* Fail to start broadcasting. */
                        }
                    });
}

??參數(shù)connectCallback是一個(gè)連接監(jiān)聽(tīng)回調(diào)類(lèi)實(shí)例,用于通知連接狀態(tài)信息。有關(guān)ConnectCallback類(lèi)的詳細(xì)信息及示例代碼,參見(jiàn)確認(rèn)連接章節(jié)。

2.4.2  啟動(dòng)掃描

??發(fā)現(xiàn)端以選定的policy和serviceId為參數(shù),調(diào)用startScan()啟動(dòng)掃描以發(fā)現(xiàn)附近的設(shè)備。示例代碼如下:

private void doStartScan() {
    Policy policy = Policy.POLICY_STAR;
    ScanOption scanOption = new ScanOption.Builder().setPolicy(policy).build();
    Nearby.getDiscoveryEngine(getApplicationContext())
            .startScan(serviceId, scanEndpointCallback, scanOption)
            .addOnSuccessListener(
                    new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {
                            /* Start scan success. */
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(Exception e) {
                            /* Fail to start scan. */
                        }
                    }); 
}

??參數(shù)scanEndpointCallback是一個(gè)掃描監(jiān)聽(tīng)回調(diào)類(lèi)實(shí)例,通知發(fā)現(xiàn)端掃描結(jié)果,發(fā)現(xiàn)設(shè)備或者已發(fā)現(xiàn)設(shè)備丟失。

private ScanEndpointCallback scanEndpointCallback =
            new ScanEndpointCallback() {
                @Override
                public void onFound(String endpointId, ScanEndpointInfo discoveryEndpointInfo) {
                    mEndpointId = endpointId;
                    mDiscoveryEngine.requestConnect(myNameStr, mEndpointId, mConnCb);
                }
                @Override
                public void onLost(String endpointId) {
                    Log.d(TAG, "Nearby Connection Demo app: Lost endpoint: " + endpointId);
                }
            };

2.4.3  停止廣播

??當(dāng)需要停止廣播時(shí),調(diào)用stopBroadcasting()。停止廣播后,廣播端不可以接收來(lái)自發(fā)現(xiàn)端的連接請(qǐng)求。

2.4.4  停止掃描

??當(dāng)需要停止掃描時(shí),調(diào)用stopScan()。停止掃描后,發(fā)現(xiàn)端仍可以向已發(fā)現(xiàn)的設(shè)備請(qǐng)求連接。一種常見(jiàn)的做法是:一旦發(fā)現(xiàn)需要連接的設(shè)備,就調(diào)用stopScan()停止掃描。

2.5 建立連接

2.5.1  請(qǐng)求連接

??當(dāng)附近的設(shè)備被發(fā)現(xiàn),發(fā)現(xiàn)端可以調(diào)用requestConnect()發(fā)起連接。示例代碼如下:

private void doStartConnect(String name, String endpointId) throws RemoteException {
    Nearby.getDiscoveryEngine(getApplicationContext())
            .requestConnect(name, endpointId, connectCallback)
            .addOnSuccessListener(
                    new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {
                            /* Request success. */
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(Exception e) {
                            /* Fail to request connect. */
                        }
                    });
}

??當(dāng)然,根據(jù)需要,可以向用戶(hù)展示發(fā)現(xiàn)的設(shè)備列表,并允許他們選擇連接哪些設(shè)備。

2.5.2  確認(rèn)連接

??發(fā)現(xiàn)端發(fā)起連接后,通過(guò)回調(diào)connectCallback的onEstablish()方法將連接建立事件通知給雙方。雙方必須通過(guò)調(diào)用acceptConnect()接受連接或者通過(guò)調(diào)用rejectConnect()拒絕連接。僅當(dāng)雙方都接受連接時(shí),連接才會(huì)建立成功。如果一方或雙方都選擇拒絕,則連接失敗。無(wú)論哪種方式,連接結(jié)果都會(huì)通過(guò)onResult()方法通知。示例代碼如下:

private final ConnectCallback connectCallback =
        new ConnectCallback() {
            @Override
            public void onEstablish(String endpointId, ConnectInfo connectInfo) {
                /* Accept the connection request without notifying user. */
                Nearby.getDiscoveryEngine(getApplicationContext())
.acceptConnect(endpointId, dataCallback);
            }
            @Override
            public void onResult(String endpointId, ConnectResult result) { 
                switch (result.getStatus().getStatusCode()) {
                    case StatusCode.STATUS_SUCCESS:
                        /* The connection was established successfully, we can exchange data. */  
                        break;  
                    case StatusCode.STATUS_CONNECT_REJECTED:  
                        /* The Connection was rejected. */
                        break;   
                    default:
                        /* other unknown status code. */  
                }   
            }
            @Override   
            public void onDisconnected(String endpointId) {
                /* The connection was disconneted. */
            }  
        };

??此示例顯示了一種雙方自動(dòng)接受連接的確認(rèn)連接方式。根據(jù)需要,可以使用其他的確認(rèn)連接方式。

2.5.3  驗(yàn)證連接

&emsp;&emsp;應(yīng)用程序可以提供一種讓用戶(hù)確認(rèn)連接到指定設(shè)備的方法,例如:通過(guò)驗(yàn)證token(token可以是一個(gè)短隨機(jī)字符串或者數(shù)字)。通常這涉及在兩個(gè)設(shè)備上顯示token并要求用戶(hù)手動(dòng)輸入或者確認(rèn),類(lèi)似于藍(lán)牙配對(duì)對(duì)話(huà)框。
?下面演示一種通過(guò)彈窗確認(rèn)配對(duì)碼的方式驗(yàn)證連接。示例代碼如下:

@Override 
public void onEstablish(String endpointId, ConnectInfo connectInfo) { 
    AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());   
    builder.setTitle(connectInfo.getEndpointName() + " request connection") 
            .setMessage("Please confirm the match code is: " + connectInfo.getAuthCode()) 
            .setPositiveButton(
                    "Accept",   
                    (DialogInterface dialog, int which) ->  
                            /* Accept the connection. */
                            Nearby.getDiscoveryEngine(getApplicationContext())  
                                    .acceptConnect(endpointId, dataCallback))
            .setNegativeButton(
                    "Reject",
                    (DialogInterface dialog, int which) ->
                            /* Reject the connection. */
                            Nearby.getDiscoveryEngine(getApplicationContext())
                                    .rejectConnect(endpointId))
            .setIcon(android.R.drawable.ic_dialog_alert);
    AlertDialog alert = builder.create();
    alert.show(); 
}

2.6 傳輸數(shù)據(jù)

??設(shè)備間建立連接后,可以使用該連接傳輸Data對(duì)象。Data對(duì)象的類(lèi)型包括字節(jié)序列、文件和流。通過(guò)調(diào)用sendData()方法發(fā)送數(shù)據(jù),通過(guò)DataCallback類(lèi)實(shí)例的onReceived()方法接收數(shù)據(jù)。

2.6.1 數(shù)據(jù)類(lèi)型

  1. BYTES
    通過(guò)調(diào)用Data.fromBytes()創(chuàng)建Data.Type.BYTES類(lèi)型的Data對(duì)象。
    發(fā)送BYTES類(lèi)型的數(shù)據(jù),示例代碼如下:

    Data bytesData = Data.fromBytes(new byte[] {0xA, 0xA, 0xA, 0xA, 0xA});   
    Nearby.getTransferEngine(getApplicationContext()).sendData(toEndpointId, bytesData);

    &emsp;&emsp;注意:BYTES類(lèi)型數(shù)據(jù)的長(zhǎng)度大小不能超過(guò)32KB。
    ?接收BYTES類(lèi)型的數(shù)據(jù),示例代碼如下:

static class BytesDataReceiver extends DataCallback {  
    @Override
    public void onReceived(String endpointId, Data data) {
        /* BYTES data is sent as a single block, so we can get complete data. */
        if (data.getType() == Data.Type.BYTES) {
            byte[] receivedBytes = data.asBytes();
        }
    }
    @Override
    public void onTransferUpdate(String endpointId, TransferStateUpdate update) {
        /* We will receive TRANSFER_STATE_SUCCESS update after onReceived() called. */
    }
}

??注意:BYTES與FILE和STREAM類(lèi)型不同,BYTES是以單個(gè)數(shù)據(jù)塊發(fā)送的,因此接收端不用等待BYTES類(lèi)型的狀態(tài)更新為T(mén)RANSFER_STATE_SUCCESS,當(dāng)onReceived()被調(diào)用時(shí)候,你就可以調(diào)用data.asBytes()以獲取全部數(shù)據(jù)。

  1. FILE
    通過(guò)調(diào)用Data.fromFile()創(chuàng)建Data.Type.FILE類(lèi)型的Data對(duì)象。
    發(fā)送FILE類(lèi)型數(shù)據(jù)的示例代碼如下:

File fileToSend = new File(getApplicationContext().getFilesDir(), "fileSample.txt");
try {  
    Data fileData = Data.fromFile(fileToSend);
    Nearby.getTransferEngine(getApplicationContext())
.sendData(endpointList, fileData);
} catch (FileNotFoundException e) { 
    /* Exception handle. */
}

??一種更高效方法是使用ParcelFileDescriptor創(chuàng)建FILE類(lèi)型,可以最大程度地減少文件的復(fù)制。示例代碼如下:

ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r");
Data fileData = Data.fromFile(pfd);

??接收設(shè)備收到文件后,文件保存在Download目錄,并且將以fileData.getId()轉(zhuǎn)化后的字符串命名。傳輸完成后,可以獲取FILE對(duì)象。示例代碼如下:

/* We can get the received file in the Download folder. */    
File payloadFile = fileData.asFile().asJavaFile();
)
  1. STREAM
    ?通過(guò)調(diào)用Data.fromStream()創(chuàng)建Data.Type.STREAM類(lèi)型的Data對(duì)象。發(fā)送流的示例代碼如下:

URL url = new URL("https://developers.huawei.com");  
Data streamData = Data.fromStream(url.openStream());  
Nearby.getTransferEngine(getApplicationContext()).sendData(toEndpointId, streamData);

??接收端,當(dāng)onTransferUpdate()回調(diào)成功時(shí),可以調(diào)用streamData.asStream().asInputStream()或者 streamData.asStream().asParcelFileDescriptor()獲取流對(duì)象。示例代碼如下:

static class StreamDataReceiver extends DataCallback {  
    private final HashMap<Long, Data> incomingData = new HashMap<>();
    @Override
    public void onTransferUpdate(String endpointId, TransferStateUpdate update) {
        if (update.getStatus() == TransferStateUpdate.Status.TRANSFER_STATE_SUCCESS) {
            Data data = incomingData.get(update.getDataId());
            InputStream inputStream = data.asStream().asInputStream();
            /* Further processing... */
        }
    }
    @Override
    public void onReceived(String endpointId, Data data) {
        incomingData.put(data.getId(), data);
    } 
}

2.6.2  進(jìn)度更新

??DataCallBack回調(diào)類(lèi)onTransferUpdate()方法提供數(shù)據(jù)發(fā)送或接收的進(jìn)度更新,基于此可以向用戶(hù)顯示傳輸進(jìn)度,例如:進(jìn)度條。

2.6.3  取消傳輸

??如果需要在接收或發(fā)送過(guò)程中取消傳輸,調(diào)用TransferEngine類(lèi)實(shí)例方法cancelDataTransfer()。

2.7 斷開(kāi)連接

??如果需要斷開(kāi)與對(duì)端的連接,調(diào)用DiscoveryEngine類(lèi)實(shí)例方法disconnect()。一旦調(diào)用此接口,將不能從此endpoint收發(fā)數(shù)據(jù)。

關(guān)于如何用HMS Nearby Service給自己的App添加近距離數(shù)據(jù)傳輸功能就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

標(biāo)題名稱(chēng):如何用HMSNearbyService給自己的App添加近距離數(shù)據(jù)傳輸功能
URL網(wǎng)址:http://jinyejixie.com/article42/ghdchc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、品牌網(wǎng)站制作、手機(jī)網(wǎng)站建設(shè)靜態(tài)網(wǎng)站、搜索引擎優(yōu)化做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)
永靖县| 兴海县| 盐边县| 炉霍县| 合江县| 绥芬河市| 米林县| 鹿泉市| 商河县| 南阳市| 斗六市| 鸡泽县| 浮梁县| 依安县| 安图县| 本溪市| 嘉义市| 神木县| 德阳市| 石首市| 青田县| 阿勒泰市| 镇宁| 邵东县| 太湖县| 申扎县| 竹溪县| 文成县| 林芝县| 松江区| 房山区| 庐江县| 柞水县| 阿拉善左旗| 涡阳县| 类乌齐县| 大冶市| 永德县| 乌鲁木齐市| 麻江县| 轮台县|