android示例
① android監控sim卡是否有服務示例
給你個示例吧:
package com.water.activity;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.telephony.CellLocation;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.util.Log;
public class MyList extends Activity {
/**
* android API中的TelephonyManager對象,可以取得SIM卡中的信息
*/
private TelephonyManager telMgr;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
telMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if (telMgr.getSimState() == telMgr.SIM_STATE_READY) {
Log.i("MyList", "良好");
} else if (telMgr.getSimState() == telMgr.SIM_STATE_ABSENT) {
Log.i("MyList", "無SIM卡");
} else {
Log.i("MyList", "SIM卡被鎖定或未知的狀態");
}
Log.i("MyList", "電話狀態[0 無活動/1 響鈴/2 摘機]:" + getCallState());
Log.i("MyList", "電話方位:" + getCellLocation());
Log.i("MyList", "唯一的設備ID:" + getDeviceId());
Log.i("MyList", "設備的軟體版本號:" + getDeviceSoftwareVersion());
Log.i("MyList", "手機號:" + getLine1Number());
Log.i("MyList", "附近的電話的信息:" + getNeighboringCellInfo());
Log.i("MyList", "獲取ISO標準的國家碼,即國際長途區號:" + getNetworkCountryIso());
Log.i("MyList", "MCC+MNC:" + getNetworkOperator());
Log.i("MyList", "(當前已注冊的用戶)的名字:" + getNetworkOperatorName());
Log.i("MyList", "當前使用的網路類型:" + getNetworkType());
Log.i("MyList", "手機類型:" + getPhoneType());
Log.i("MyList", "SIM卡的國家碼:" + getSimCountryIso());
Log.i("MyList", "獲取SIM卡提供的移動國家碼和移動網路碼.5或6位的十進制數字:" + getSimOperator());
Log.i("MyList", "服務商名稱:" + getSimOperatorName());
Log.i("MyList", "SIM卡的序列號:" + getSimSerialNumber());
Log.i("MyList", "SIM的狀態信息:" + getSimState());
Log.i("MyList", "唯一的用戶ID:" + getSubscriberId());
Log.i("MyList", "取得和語音郵件相關的標簽,即為識別符:" + getVoiceMailAlphaTag());
Log.i("MyList", "獲取語音郵件號碼:" + getVoiceMailNumber());
Log.i("MyList", "ICC卡是否存在:" + hasIccCard());
Log.i("MyList", "是否漫遊:" + isNetworkRoaming());
Log.i("MyList", "獲取數據活動狀態:" + getDataActivity());
Log.i("MyList", "獲取數據連接狀態:" + getDataState());
}
/**
* 電話狀態:<br/>
* CALL_STATE_IDLE 無任何狀態時<br/>
* CALL_STATE_OFFHOOK 接起電話時<br/>
* CALL_STATE_RINGING 電話進來時
*
* @return
*/
private int getCallState() {
return telMgr.getCallState();
}
/**
* 返回當前移動終端的位置 <br/>
*
* @return
*/
private CellLocation getCellLocation() {
CellLocation location = telMgr.getCellLocation();
// 請求位置更新,如果更新將產生廣播,接收對象為注冊LISTEN_CELL_LOCATION的對象,需要的permission名稱為ACCESS_COARSE_LOCATION。
// location.requestLocationUpdate();
return location;
}
/**
* 唯一的設備ID:<br/>
* 如果是GSM網路,返回IMEI;如果是CDMA網路,返回MEID<br/>
* 需要許可權:android.permission.READ_PHONE_STATE
*
* @return null if device ID is not available.
*/
private String getDeviceId() {
return telMgr.getDeviceId();
}
/**
* 返回移動終端的軟體版本:<br/>
* 例如:GSM手機的IMEI/SV碼。<br/>
*
* @return null if the software version is not available.
*/
private String getDeviceSoftwareVersion() {
return telMgr.getDeviceSoftwareVersion();
}
/**
* 手機號:<br/>
* 對於GSM網路來說即MSISDN
*
* @return null if it is unavailable.
*/
private String getLine1Number() {
return telMgr.getLine1Number();
}
/**
* 返回當前移動終端附近移動終端的信息:<br/>
* 類型:List<NeighboringCellInfo><br/>
* 需要許可權:android.Manifest.permission#ACCESS_COARSE_UPDATES
*
* @return
*/
private List<NeighboringCellInfo> getNeighboringCellInfo() {
// List<NeighboringCellInfo> infos = telMgr.getNeighboringCellInfo();
// for (NeighboringCellInfo info : infos) {
// // 獲取鄰居小區號
// int cid = info.getCid();
//
// // 獲取鄰居小區LAC,LAC:
// // 位置區域碼。為了確定移動台的位置,每個GSM/PLMN的覆蓋區都被劃分成許多位置區,LAC則用於標識不同的位置區。
// info.getLac();
// info.getNetworkType();
// info.getPsc();
//
// // 獲取鄰居小區信號強度
// info.getRssi();
// }
return telMgr.getNeighboringCellInfo();
}
/**
* 獲取ISO標準的國家碼,即國際長途區號。<br/>
* 注意:僅當用戶已在網路注冊後有效。<br/>
* 在CDMA網路中結果也許不可靠。<br/>
*
* @return
*/
private String getNetworkCountryIso() {
return telMgr.getNetworkCountryIso();
}
/**
* MCC+MNC(mobile country code + mobile network code)<br/>
* 注意:僅當用戶已在網路注冊時有效。<br/>
* 在CDMA網路中結果也許不可靠。<br/>
*
* @return
*/
private String getNetworkOperator() {
return telMgr.getNetworkOperator();
}
/**
* 按照字母次序的current registered operator(當前已注冊的用戶)的名字<br/>
* 注意:僅當用戶已在網路注冊時有效。<br/>
* 在CDMA網路中結果也許不可靠。
*
* @return
*/
private String getNetworkOperatorName() {
return telMgr.getNetworkOperatorName();
}
/**
* 當前使用的網路類型:<br/>
* NETWORK_TYPE_UNKNOWN 網路類型未知 0<br/>
* NETWORK_TYPE_GPRS GPRS網路 1<br/>
* NETWORK_TYPE_EDGE EDGE網路 2<br/>
* NETWORK_TYPE_UMTS UMTS網路 3<br/>
* NETWORK_TYPE_HSDPA HSDPA網路 8<br/>
* NETWORK_TYPE_HSUPA HSUPA網路 9<br/>
* NETWORK_TYPE_HSPA HSPA網路 10<br/>
* NETWORK_TYPE_CDMA CDMA網路,IS95A 或 IS95B. 4<br/>
* NETWORK_TYPE_EVDO_0 EVDO網路, revision 0. 5<br/>
* NETWORK_TYPE_EVDO_A EVDO網路, revision A. 6<br/>
* NETWORK_TYPE_1xRTT 1xRTT網路 7<br/>
* 在中國,聯通的3G為UMTS或HSDPA,移動和聯通的2G為GPRS或EGDE,電信的2G為CDMA,電信的3G為EVDO<br/>
*
* @return
*/
private int getNetworkType() {
return telMgr.getNetworkType();
}
/**
* 返回移動終端的類型:<br/>
* PHONE_TYPE_CDMA 手機制式為CDMA,電信<br/>
* PHONE_TYPE_GSM 手機制式為GSM,移動和聯通<br/>
* PHONE_TYPE_NONE 手機制式未知<br/>
*
* @return
*/
private int getPhoneType() {
return telMgr.getPhoneType();
}
/**
* 獲取ISO國家碼,相當於提供SIM卡的國家碼。
*
* @return Returns the ISO country code equivalent for the SIM provider's
* country code.
*/
private String getSimCountryIso() {
return telMgr.getSimCountryIso();
}
/**
* 獲取SIM卡提供的移動國家碼和移動網路碼.5或6位的十進制數字.<br/>
* SIM卡的狀態必須是 SIM_STATE_READY(使用getSimState()判斷).
*
* @return Returns the MCC+MNC (mobile country code + mobile network code)
* of the provider of the SIM. 5 or 6 decimal digits.
*/
private String getSimOperator() {
return telMgr.getSimOperator();
}
/**
* 服務商名稱:<br/>
* 例如:中國移動、聯通<br/>
* SIM卡的狀態必須是 SIM_STATE_READY(使用getSimState()判斷).
*
* @return
*/
private String getSimOperatorName() {
return telMgr.getSimOperatorName();
}
/**
* SIM卡的序列號:<br/>
* 需要許可權:READ_PHONE_STATE
*
* @return
*/
private String getSimSerialNumber() {
return telMgr.getSimSerialNumber();
}
/**
* SIM的狀態信息:<br/>
* SIM_STATE_UNKNOWN 未知狀態 0<br/>
* SIM_STATE_ABSENT 沒插卡 1<br/>
* SIM_STATE_PIN_REQUIRED 鎖定狀態,需要用戶的PIN碼解鎖 2<br/>
* SIM_STATE_PUK_REQUIRED 鎖定狀態,需要用戶的PUK碼解鎖 3<br/>
* SIM_STATE_NETWORK_LOCKED 鎖定狀態,需要網路的PIN碼解鎖 4<br/>
* SIM_STATE_READY 就緒狀態 5
*
* @return
*/
private int getSimState() {
return telMgr.getSimState();
}
/**
* 唯一的用戶ID:<br/>
* 例如:IMSI(國際移動用戶識別碼) for a GSM phone.<br/>
* 需要許可權:READ_PHONE_STATE
*
* @return
*/
private String getSubscriberId() {
return telMgr.getSubscriberId();
}
/**
* 取得和語音郵件相關的標簽,即為識別符<br/>
* 需要許可權:READ_PHONE_STATE
*
* @return
*/
private String getVoiceMailAlphaTag() {
return telMgr.getVoiceMailAlphaTag();
}
/**
* 獲取語音郵件號碼:<br/>
* 需要許可權:READ_PHONE_STATE
*
* @return
*/
private String getVoiceMailNumber() {
return telMgr.getVoiceMailNumber();
}
/**
* ICC卡是否存在
*
* @return
*/
private boolean hasIccCard() {
return telMgr.hasIccCard();
}
/**
* 是否漫遊:(在GSM用途下)
*
* @return
*/
private boolean isNetworkRoaming() {
return telMgr.isNetworkRoaming();
}
/**
* 獲取數據活動狀態<br/>
* DATA_ACTIVITY_IN 數據連接狀態:活動,正在接受數據<br/>
* DATA_ACTIVITY_OUT 數據連接狀態:活動,正在發送數據<br/>
* DATA_ACTIVITY_INOUT 數據連接狀態:活動,正在接受和發送數據<br/>
* DATA_ACTIVITY_NONE 數據連接狀態:活動,但無數據發送和接受<br/>
*
* @return
*/
private int getDataActivity() {
return telMgr.getDataActivity();
}
/**
* 獲取數據連接狀態<br/>
* DATA_CONNECTED 數據連接狀態:已連接<br/>
* DATA_CONNECTING 數據連接狀態:正在連接<br/>
* DATA_DISCONNECTED 數據連接狀態:斷開<br/>
* DATA_SUSPENDED 數據連接狀態:暫停<br/>
*
* @return
*/
private int getDataState() {
return telMgr.getDataState();
}
}
② AndroidStudio怎樣使用NDK開發示例
1、新建一個Android工程,這一步就不多說了;
2、在AndroidStudio中配置NDK路徑,方法是:
(1)先下載NDK並安裝(這句基本是廢話);
(2)點菜單欄的File->ProjectStructure…->在打開的窗口中左側選中SDKLocation->在右側Android NDK Location中填入NDK目錄所在路徑
3、編譯生成.class文件,方法是:
點菜單欄的Build->Make Project
這時,在工程的app/build/intermediates下就會生成classes文件夾,打開classes目錄下的debug目錄就會看到以你的包名命名的各級文件夾,最里邊文件夾下有你的Java類對應的.class文件;
4、確定你要引用本地方法的類:
其實你也可以先生成jni目錄,再去創建這個類,但是先Google顯然建議先創建要引用C代碼的Java類,因為AndroidStudio可以根據你在java類中定義的native方法的名稱來自動生成.h頭文件。
比如你想在MainActivity中引用本地方法,那麼你先用
static {
System.loadLibrary("myNativeLib");
}
來聲明本地代碼庫,然後定義幾個natvie方法,比如
public native String getStringFromNative();
5、使用javah命令行生成jni目錄及對應的頭文件:
我用的是AndroidStudio 2.1.1,在主界面最下邊就能找到Terminal,點一下就能打開系統的命令行工具,並且已經為你自動cd到當前工程所在目錄
6、配置build.gradle文件
這里的build.gradle是指app模塊下的build.gradle,不是整個工程的build.gradle文件。在模塊的build.gradle的defaultConfig下加入以下idk配置:
ndk {
moleName"myNativeLib"
ldLibs "log", "z", "m"
abiFilters "armeabi", "armeabi-v7a", "x86"
}
7、配置local.properties文件
打開工程目錄下的local.properties,感覺這一步是自動配置的,或者說在你一開始在AndroidStudio中指定NDK目錄時已經自動生成了。我的AndroidStudio在打開local.properties已經有了
ndk.dir=/Develop/Android/android-ndk-r10e
這一行,所以就不用配了;
8、配置gradle.properties
打開工程目錄下的gradle.properties文件(注意不是build.gradle,而是gradle.properties),在文件的最後一行加入
android.useDeprecatedNdk=true
這句的作用是允許我們使用已經過時的NDK版本,不知道AndroidStudio要求使用哪個版本的NDK才不會報錯,總之只要配置了這一句就可以使用比較舊的NDK版本了,我用的r10;
至此我們在AndroidStudio中就完成了NDK環境的配置,接下來就可以寫Native代碼了;
9、寫一個.c文件測試一下是否運行正常
(1)在我們之前生成src/main/jni目錄下新建一個.c文件,方法是在jni文件夾上點滑鼠右鍵,選擇New->C/C++ Source File,然後在彈出的對話框中填入.c或.cpp文件的文件名就可以了,比如說mail.c
③ android下載圖片和視頻到本地,求代碼,求案例
下面是android多線程下載例子截圖:
packagemm.shandong.com.testmultithreaddownload;
importandroid.app.ProgressDialog;
importandroid.content.Intent;
importandroid.net.Uri;
importandroid.os.Environment;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.support.v7.app.AppCompatActivity;
importandroid.os.Bundle;
importandroid.text.TextUtils;
importandroid.view.View;
importandroid.widget.EditText;
importandroid.widget.Toast;
importjava.io.File;
importmm.shandong.com.testmultithreaddownload.thread.UpdateUIThread;
importmm.shandong.com.testmultithreaddownload.util.FileUtil;
{
ProgressDialogpb;
EditTexteditText;
Handlerhandler;
=null;
///文件路徑
privateStringurl=
"http://gdown..com/data/wisegame/3c00add7144d3915/kugouyinle.apk";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_multi_thread_down_load);
editText=(EditText)findViewById(R.id.editText);
initHandler();
}
publicvoidinitHandler(){
handler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseFileUtil.startDownloadMeg:
pb.setMax(mUpdateUIThread.getFileSize());//開始
break;
caseFileUtil.updateDownloadMeg:
if(!mUpdateUIThread.isCompleted())//下載進度消息
{
pb.setProgress(mUpdateUIThread.getDownloadSize());
pb.setMessage("下載速度:"+
mUpdateUIThread.getDownloadSpeed()+"k/秒"+
"下載百分比"+mUpdateUIThread.getDownloadPercent()+"%");
}else{
pb.setMessage("下載完成");
}
break;
caseFileUtil.endDownloadMeg:
Toast.makeText(.this,
"下載完成,馬上安裝",Toast.LENGTH_SHORT).show();
/*apk安裝界面跳轉*/
Stringfilename=FileUtil.getFileName(url);
Stringstr="/myfile/"+filename;
StringfileName=Environment.getExternalStorageDirectory()+str;
Intentintent=newIntent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newFile(fileName)),
"application/vnd.android.package-archive");
startActivity(intent);
break;
}
super.handleMessage(msg);
}
};
}
///開始下載軟體
publicvoidstartDownLoad(Viewview){
if(TextUtils.isEmpty(editText.getText().toString())){
Toast.makeText(this,"你輸入下載文件地址",Toast.LENGTH_SHORT).show();
return;
}else{
url=editText.getText().toString();
}
//啟動線程初始化下載參數
mUpdateUIThread=newUpdateUIThread(handler,url,
FileUtil.setMkdir(this)+File.separator,FileUtil.getFileName(url));
pb=newProgressDialog(this);
pb.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pb.show();
mUpdateUIThread.start();
}
}
例子代碼太長,只能給你一部分,如果想看完整例子代碼,請去360手機助手下載安卓學習手冊,點擊裡面的源碼可以查看完成代碼,方面快速,裡面還有安卓的其它小例子,共108個。
④ 百度地圖的Android示常式序怎麼使用
如果你不會,請加入QQ718081228428,我為你解答!!!!!!
⑤ 怎樣使用Android SDK 里的示例代碼
直接Import是會出錯的,我試過,
你可以這樣:新建一個Android工程的時候,在Contents選擇:Create project form exising source
然後選擇示例代碼。
⑥ android 代碼布局簡單的例子
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
linearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
ImageButton news = new ImageButton(context);
news.setId(85);
news.setOnClickListener(this);
news.setBackgroundResource(R.drawable.news);
news.setLayoutParams(new LayoutParams(33, 33));
linearLayout.addView(news);
這段代碼就動態把一個ImageButton添加到一個LinearLayout中去了~
同時設定了VIEW的長寬背景布局方式等~
同理,刪除掉使用的方法例如:
XXX.removeViewAt(index)
index就是這個子view在父view中是第(index+1)個添加進去的(index從0開始算的)
先嘗試去修改下,再有不懂的請留言~
幫你網路的 大致就這樣 下面有參考資料http://..com/question/255392766.html
⑦ Android-Ble藍牙開發Demo示例–掃描,連接,發送和接收數據,分包解包(附源碼)
萬物互聯的物聯網時代的已經來臨,ble藍牙開發在其中扮演著舉重若輕的角色。最近剛好閑一點,抽時間梳理下這塊的知識點。
涉及ble藍牙通訊的客戶端(開啟、掃描、連接、發送和接收數據、分包解包)和服務端(初始化廣播數據、開始廣播、配置Services、Server回調操作)整個環節以及一些常見的問題即踩過的一些坑。
比如
1、在Android不同版本或不同手機的適配問題,掃描不到藍牙設備
2、如何避免ble藍牙連接出現133錯誤?
3、單次寫的數據大小有20位元組限制,如何發送長數據
藍牙有傳統(經典)藍牙和低功耗藍牙BLE(Bluetooth Low Energy)之分,兩者的開發的API不一樣,本文主講Ble藍牙開發,傳統藍牙不展開,有需要的可以自行了解。
相對傳統藍牙,BLE低功耗藍牙,主要特點是快速搜索,快速連接,超低功耗保持連接和數據傳輸。
客戶端
服務端
Android4.3(API Level 18)開始引入BLE的核心功能並提供了相應的 API。應用程序通過這些 API 掃描藍牙設備、查詢 services、讀寫設備的 characteristics(屬性特徵)等操作。
BLE藍牙協議是GATT協議, BLE相關類不多, 全都位於android.bluetooth包和android.bluetooth.le包的幾個類:
android.bluetooth.
.BluetoothGattService 包含多個Characteristic(屬性特徵值), 含有唯一的UUID作為標識
.BluetoothGattCharacteristic 包含單個值和多個Descriptor, 含有唯一的UUID作為標識
.BluetoothGattDescriptor 對Characteristic進行描述, 含有唯一的UUID作為標識
.BluetoothGatt 客戶端相關
.BluetoothGattCallback 客戶端連接回調
.BluetoothGattServer 服務端相關
.BluetoothGattServerCallback 服務端連接回調
android.bluetooth.le.
.AdvertiseCallback 服務端的廣播回調
.AdvertiseData 服務端的廣播數據
.AdvertiseSettings 服務端的廣播設置
.BluetoothLeAdvertiser 服務端的廣播
.BluetoothLeScanner 客戶端掃描相關(Android5.0新增)
.ScanCallback 客戶端掃描回調
.ScanFilter 客戶端掃描過濾
.ScanRecord 客戶端掃描結果的廣播數據
.ScanResult 客戶端掃描結果
.ScanSettings 客戶端掃描設置
BLE設備分為兩種設備: 客戶端(也叫主機/中心設備/Central), 服務端(也叫從機/外圍設備/peripheral)
客戶端的核心類是 BluetoothGatt
服務端的核心類是 BluetoothGattServer 和 BluetoothLeAdvertiser
BLE數據的核心類是 BluetoothGattCharacteristic 和 BluetoothGattDescriptor
下面詳細講解下客戶端和服務端的開發步驟流程
安卓手機涉及藍牙許可權問題,藍牙開發需要在AndroidManifest.xml文件中添加許可權聲明:
在搜索設備之前需要詢問打開手機藍牙:
注意: BLE設備地址是動態變化(每隔一段時間都會變化),而經典藍牙設備是出廠就固定不變了!
通過掃描BLE設備,根據設備名稱區分出目標設備targetDevice,下一步實現與目標設備的連接,在連接設備之前要停止搜索藍牙;停止搜索一般需要一定的時間來完成,最好調用停止搜索函數之後加以100ms的延時,保證系統能夠完全停止搜索藍牙設備。停止搜索之後啟動連接過程;
BLE藍牙的連接方法相對簡單只需調用connectGatt方法;
參數說明
與設備建立連接之後與設備通信,整個通信過程都是在BluetoothGattCallback的非同步回調函數中完成;
BluetoothGattCallback中主要回調函數如下:
上述幾個回調函數是BLE開發中不可缺少的;
當調用targetdDevice.connectGatt(context, false, gattCallback)後系統會主動發起與BLE藍牙設備的連接,若成功連接到設備將回調onConnectionStateChange方法,其處理過程如下:
判斷newState == BluetoothGatt.STATE_CONNECTED表明此時已經成功連接到設備;
mBluetoothGatt.discoverServices();
掃描BLE設備服務是安卓系統中關於BLE藍牙開發的重要一步,一般在設備連接成功後調用,掃描到設備服務後回調onServicesDiscovered()函數,函數原型如下:
BLE藍牙開發主要有負責通信的BluetoothGattService完成的。當且稱為通信服務。通信服務通過硬體工程師提供的UUID獲取。獲取方式如下:
具體操作方式如下:
開啟監聽,即建立與設備的通信的首發數據通道,BLE開發中只有當客戶端成功開啟監聽後才能與服務端收發數據。開啟監聽的方式如下:
BLE單次寫的數據量大小是有限制的, 通常是20位元組 ,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20位元組,分兩種包,數據包和非數據包。對於數據包,頭兩個位元組表示包的序號,剩下的都填充數據。對於非數據包,主要是發送一些控制信息。
監聽成功後通過向 writeCharacteristic寫入數據實現與服務端的通信。寫入方式如下:
其中:value一般為Hex格式指令,其內容由設備通信的藍牙通信協議規定;
若寫入指令成功則回調BluetoothGattCallback中的onCharacteristicWrite()方法,說明將數據已經發送給下位機;
若發送的數據符合通信協議,則服務端會向客戶端回復相應的數據。發送的數據通過回調onCharacteristicChanged()方法獲取,其處理方式如下:
通過向服務端發送指令獲取服務端的回復數據,即可完成與設備的通信過程;
當與設備完成通信之後之後一定要斷開與設備的連接。調用以下方法斷開與設備的連接:
源碼上傳在CSDN上了,有需要的可以借鑒。
=====> Android藍牙Ble通訊Demo示例源碼–掃描,連接,發送和接收數據,分包解包
BLE單次寫的數據量大小是有限制的,通常是20位元組,可以嘗試通過requestMTU增大,但不保證能成功。分包寫是一種解決方案,需要定義分包協議,假設每個包大小20位元組,分兩種包,數據包和非數據包。對於數據包,頭兩個位元組表示包的序號,剩下的都填充數據。對於非數據包,主要是發送一些控制信息。
總體流程如下:
1、定義通訊協議,如下(這里只是個舉例,可以根據項目需求擴展)
2、封裝通用發送數據介面(拆包)
該介面根據會發送數據內容按最大位元組數拆分(一般20位元組)放入隊列,拆分完後,依次從隊列里取出發送
3、封裝通用接收數據介面(組包)
該介面根據從接收的數據按協議里的定義解析數據長度判讀是否完整包,不是的話把每條消息累加起來
4、解析完整的數據包,進行業務邏輯處理
5、協議還可以引入加密解密,需要注意的選演算法參數的時候,加密後的長度最好跟原數據長度一致,這樣不會影響拆包組包
一般都是Android版本適配以及不同ROM機型(小米/紅米、華為/榮耀等)(EMUI、MIUI、ColorOS等)的許可權問題
藍牙開發中有很多問題,要靜下心分析問題,肯定可以解決的,一起加油;
⑧ android一個示例同時在onSaveInstanceState和onPause中調用數據保存函數,這是為什麼
onSaveInstanceState和onPause都寫上調用數據保存函數是針對正常和非正常結束activity的場景。
1、onSaveInstanceState:非正常結束,當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷毀一個Activity時,onSaveInstanceState() 會被調用。當用戶主動去銷毀一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用
2、onPause:正常結束,是activity的生命周期一個環節,正常結束都會調用該函數。
⑨ Android技術分享|Android 中部分內存泄漏示例及解決方案
內存泄漏:
舉例:
請注意以下的例子是虛構的
內存抖動
源自Android文檔中的 Memory churn 一詞,中文翻譯為內存抖動。
指快速頻繁的創建對象從而產生的性能問題。
引用Android文檔原文:
Java內存泄漏的根本原因是 長生命周期 的對象持有 短生命周期 對象的引用就很可能發生內存泄漏。
盡管短生命周期對象已經不再需要,但因為長生命周期依舊持有它的引用,故不能被回收而導致內存泄漏。
靜態集合類引起的內存泄漏
如果僅僅釋放引用本身(tO = null), ArrayList 依然在引用該對象,GC無法回收。
監聽器
在Java應用中,通常會用到很多監聽器,一般通過 addXXXXListener() 實現。但釋放對象時通常會忘記刪除監聽器,從而增加內存泄漏的風險。
各種連接
如資料庫連接、網路連接(Socket)和I/O連接。忘記顯式調用 close() 方法引起的內存泄漏。
內部類和外部模塊的引用
內部類的引用是很容易被遺忘的一種,一旦沒有釋放可能會導致一系列後續對象無法釋放。此外還要小心外部模塊不經意的引用,內部類是否提供相應的操作去除外部引用。
單例模式
由於單例的靜態特性,使其生命周期與應用的生命周期一樣長,一旦使用不恰當極易造成內存泄漏。如果單利持有外部引用,需要注意提供釋放方式,否則當外部對象無法被正常回收時,會進而導致內存泄漏。
集合類泄漏
如集合的使用范圍超過邏輯代碼的范圍,需要格外注意刪除機制是否完善可靠。比如由靜態屬性 static 指向的集合。
單利泄漏
以下為簡單邏輯代碼,只為舉例說明內存泄漏問題,不保證單利模式的可靠性。
AppManager 創建時需要傳入一個 Context ,這個 Context 的生命周期長短至關重要。
1. 如果傳入的是 Application 的 Context ,因為 Application 的生命周期等同於應用的生命周期,所以沒有任何問題。
2. 如果傳入的是 Activity 的 Context ,則需要考慮這個 Activity 是否在整個生命周期都不會被回收了,如果不是,則會造成內存泄漏。
非靜態內部類創建靜態實例造成的內存泄漏
應該將該內部類單獨封裝為一個單例來使用。
匿名內部類/非同步線程
Runnable都使用了匿名內部類,將持有MyActivity的引用。如果任務在Activity銷毀前未完成,將導致Activity的內存無法被回收,從而造成內存泄漏。
解決方法:將Runnable獨立出來或使用靜態內部類,可以避免因持有外部對象導致的內存泄漏。
Handler造成的內存泄漏
Handler屬於TLS(Thread Local Storage)變數,生命周期與Activity是不一致的,容易導致持有的對象無法正確被釋放
當Android應用程序啟動時,該應用程序的主線程會自動創建一個Looper對象和與之關聯的MessageQueue。
當主線程中實例化一個Handler對象後,它就會自動與主線程Looper的MessageQueue關聯起來。所有發送到MessageQueue的Messag都會持有Handler的引用,所以Looper會據此回調Handle的handleMessage()方法來處理消息。只要MessageQueue中有未處理的Message,Looper就會不斷的從中取出並交給Handler處理。
另外,主線程的Looper對象會伴隨該應用程序的整個生命周期。
在Java中,非靜態內部類和匿名類內部類都會潛在持有它們所屬的外部類的引用,但是靜態內部類卻不會。
當該 Activity 被 finish() 掉時,延遲執行任務的 Message 還會繼續存在於主線程中,它持有該 Activity 的 Handler 引用,所以此時 finish() 掉的 Activity 就不會被回收了從而造成內存泄漏(因 Handler 為非靜態內部類,它會持有外部類的引用,在這里就是指 SampleActivity)。
避免不必要的靜態成員變數
對於BroadcastReceiver、ContentObserver、File、Cursor、Stream、Bitmap等資源的使用,應在Activity銷毀前及時關閉或注銷。
不使用WebView對象時,應調用`destroy()`方法銷毀。
⑩ android的API 示例是什麼
下載android的sdk包,裡面有個sample目錄,裡面就是示常式序。都是開源的,如果你想學習Android的API介面的使用方法,或者你想寫一個Android應用程序,都可以參考這些示例,甚至可以用這些程序作為模型,做功能的強化,而不必擔心授權的問題。