A. 如何查看android設備的CPU架構信息
下面是獲取設備cpu信息的截圖:例子來自於android學習手冊,android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用androidstudio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,圖標上有貝殼publicString[]getCpuInfo(){Stringstr1="/proc/cpuinfo";Stringstr2="";String[]cpuInfo={"",""};String[]arrayOfString;try{FileReaderfr=newFileReader(str1);=newBufferedReader(fr,8192);str2=localBufferedReader.readLine();arrayOfString=str2.split("\\s+");for(inti=2;i
B. 新手Android中px=dp*(dpi/160)的解釋
在160dpi的手機上1px=1dp,這句話的以上是說,手機屏幕寬頻被分割成了160塊,每一塊有一個像素點,每一塊就是一個dp。 那麼1dp=1px
而320dpi的手機上,解析度是上一個手機的兩倍,手機屏幕寬頻也被分割成了160塊,每一塊有兩個像素點,每一塊也是一個dp,那麼1dp=2px
上面分析來自於android學習手冊,360手機助手中可以下載,裡面有108個android例子,源碼文檔都可在裡面看,下面是截圖
java">importandroid.content.Context;
publicclassDensityUtil{
/**
*根據手機的解析度從dp的單位轉成為px(像素)
*/
publicstaticintdip2px(Contextcontext,floatdpValue){
finalfloatscale=context.getResources().getDisplayMetrics().density;
return(int)(dpValue*scale+0.5f);
}
/**
*根據手機的解析度從px(像素)的單位轉成為dp
*/
publicstaticintpx2dip(Contextcontext,floatpxValue){
finalfloatscale=context.getResources().getDisplayMetrics().density;
return(int)(pxValue/scale+0.5f);
}
}
C. 三星s5安卓6.0更新手冊
中國大陸上市的Galaxy S5有6款機型,分別是G9006V、G9006W、G9008V、G9008W、G9009D以及G9009W。目前最新操作系統是Android 6.0。手機若有了新的固件,會有推送更新通知。可以進行以下操作:設置-(關於手機/關於設備)-系統更新-自動更新-開啟。若您的系統已是最新版本,則手機會提示您已安裝最新更新。固件升級可以對機器的部分功能進行優化、完善手機系統,使手機系統更穩定、更流暢。
若手機有更新版本提示但無法升級或升級過程中出現中斷、安裝失敗等情況,建議檢查:
1.手機是否設置為當前時間。
2.手機是否有足夠的電量或存儲空間(存儲空間建議至少為1GB)。
3.若手機系統更新提示注冊失敗,可能是網路問題,建議換一個時間段再試或連接穩定的無線網路/移動數據網路(固件可能會較大,建議連接WLAN升級)。
4.若問題依然存在,建議您攜帶購機發票、包修卡和機器送到三星服務中心檢查。
註:若手機系統更新提示設備已修改,可能是由於手機已刷機導致無法升級,建議聯系三星服務中心處理。
D. 大學生在做Android APP開發,需要寫安裝手冊、維護手冊嗎
- -。我還真沒聽說app需要安裝手和維護手冊,你又不是做實體的機械類的東西。。。
可以寫個應用的功能簡介~
如果是你開發一個應用賣給別人,可能協議裡面會涉及,以後應用的升級和維護要不要你負責和是否付費之類的。
E. 視頻快手的android版幫助手冊
1.視頻快手下載文件儲存地址
(1)媒體文件存放地址:文件管理器(存儲卡)——kuaishou——對應的應用文件夾內(包含某個任務的文件夾和其文件名對應的TASK文件)建議通過應用界面中的「空間」按鈕,來進行媒體文件管理。
(2)快手應用更新時APK存放地址:文件管理器(存儲卡)--->kuaishou--->ksfamily
* 溫馨提示:如果在空間里對該文件任務進行刪除操作,之前下載時的TASK文件會消失,但是任務文件夾不會消失,裡面已下載為完的MP4文件會被刪除,但是未下載完的MP4.TMP文件還在。
2.視頻快手應用是否能把緩存和下載內容放在外置的sd卡?
快手應用下載路徑是根據手機出廠配置進行默認,如有必要可根據以下方式更改:快手下載-menu-設置-下載路徑-選擇「/sdcard/」。但不排除有個別型號手機下載到內置ROM空間上,比如三星手機,暫時尚不支持用戶主動切換,這個功能我們正在研發中,敬請關注視頻快手官網的更新公告。
3.下載的是APK,存到電腦上的是ZIP。
IE下載時會自動把文件名後綴由.APK改為.ZIP,重命名.APK就可以了。
4.為什麼不能下載視頻?
(1)下載或在線觀看影片速度不理想時,請嘗試重新選擇服務線路:更多——設置——選擇服務線路,然後選擇其他線路。
(2)手機通過數據線和pc連接復制文件時會使快手不能讀寫SD卡,導致下載失敗。請重新選擇USB連接類型,停止手機和pc之間的數據傳輸。
(3)SD卡已滿或者SD卡裝機失敗。請檢查SD卡內存以及是否接觸良好。
(4)某一部或者某一個來源的影片不能下載,請聯系快手。
5.用【快手下載】有時會死機。
建議不要啟動多項應用程序程序,尤其是邊下載邊看邊打電話,多數手機會迅速過熱而啟動重啟。
6.不能續傳,提示「某某劇停止下載」。
無線網路不穩定或者網路擁堵。建議下載時不要同時使用其他佔用帶寬較多的功能,或多人同時共用一個路由器。
7.為什麼會出現視頻播放延遲?如何解決?
(1)檢查帶寬,一般流暢播放需要2MB帶寬,高清或超清需要4MB甚至更多。
(2)關閉手機後台多餘程序。
(3)手機硬體性能不足以支持視頻播放,建議將該節目下載後用第三方播放器播放。
8.為什麼WiFi網路連接暢通,手機在不充電時或者鎖屏之後,不能在線看片?
當WIFI的休眠策略為「充電時永不休眠」或「屏幕關閉時休眠」時,WIFI網路會自動斷點導致不能在線看視頻。建議將WiFi設置為「永不休眠」。設置-無線和網路-WlAN設置-memu-高級-WLAN休眠策略-選擇「永不休眠」
9.為什麼視頻無法播放,並提示「您的播放已中斷,可能是:您的網路不穩定;或您的手機不能播放當前內容」 ?
(1)無線網路不穩定。在線播放高清對無線網路的穩定性有很高的要求,網速需要至少2MB帶寬,老型號的無線路由器經常會有抖動、掉包等情況,這時雖然看上去信號是滿格的,其實數據流已經停止了,從而導致不能播放。建議您關閉無線路由器後等待3分鍾,再重新啟動。或者更換新型號的無線路由器。另外您可以通過下載來排除是否是網路問題,因為下載中支持斷點續傳,受網路影響小。下載完成後點【空間】--【播放】可以觀看,代表是網路問題,否則是內置播放器問題不支持看高清。另外在觀看視頻時建議避免和很多人共享同一台無線路由器
(2)機器硬體性能不足,視頻晶元解碼能力差。完美觀看的機型通常要求CPU主頻至少不低於1 GHz,或者擁有獨立顯卡,否則就有可能導致在播放中出現聲畫不同步、畫面頓挫、甚至黑屏無法播放的現象。
(3)視頻來源方壓制問題。由於來源網站壓片、轉碼等原因,可能導致文件頭損壞,從而無法讀取,會出現黑屏、綠屏、馬賽克等現象,畫面卡住不動。建議您將進度條向後拖動,通常可以解決;或者更換來源。同一部片子中的碼流偶爾也會有高低,如果出現提示【你的播放已中斷,可能是:您的網路不穩定,或者是您的手機不能播放當前內容】。首先請先排除網路和機器性能問題,則可能是視頻來源方使用了不同格式的視頻文件,導致無法播放。或者是來源網站對某些影片做了下線處理,導致鏈接失效。請您告知影片名稱,我們將盡快處理。建議更換來源或者通過第三方播放器來觀看。
(4)海外用戶無法觀看。如果您在海外用戶,某些運營商可能會限制流量,導致視頻內容無法讀取。建議您更換上網地點,選擇不同的運營商試試看。個別來源網站限制了非中國大陸地區的IP地址,建議您更換其他來源試試。
10.為什麼點擊立即觀看會出現提示「本視頻無法被訪問?」
(1)個別視頻涉及版許可權制,無法通過手機觀看。
(2)視頻鏈接失效
(3)網路不穩定
11.為什麼分段較少的片子播放一半就卡住或者停止,重新定位後仍然不起作用?
無線網路傳輸的數據流過大,導致網路卡死,和無線信號的強度無關。建議重啟無線路由器,或選擇視頻文件分段較多的來源,或避免在觀看大段視頻時和多人共用一台無線路由器。
12.為什麼播放下載好的視頻一段時間之後會出現「播放中斷,網路不穩定」的提示?
視頻壓縮過程中質量稍有偏差,導致部分內置播放器視頻解碼糾錯功能稍差的手機不能觀看。請下載後選擇第三方播放器:空間—查看—點擊播放,然後選擇第三方播放器播放。
F. android 多個頁面怎麼共用同一組件
自定義組件就行。如果覺得還不好就創建一個mole。
關於自定義組件的實例,請參考android學習手冊,android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用android studio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,圖標上有貝殼
.多個Activity共用相同布局或者相同控制項:避免重復代碼;
BaseActivit代碼:
{
/*
* 多個Activity共用相同布局或者相同控制項
* 寫個基類繼承,避免重復代碼
*/
@Override
publicvoidonClick(View v)
{
switch(v.getId())
{
caseR.id.common_titlebar_btn_back:
finish();
break;
default:
break;
}
baseOnClick(v);
}
protectedvoidbaseOnClick(View v)
{
}
@Override
protectedvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_base);
}
@Override
protectedvoidonResume()
{
super.onResume();
onPostOnCreate();
}
publicfinalvoidonPostOnCreate()//find同一個控制項
{
findViewById(R.id.common_titlebar_btn_back).setOnClickListener(this);
}
@Override
(Menu menu)
{
getMenuInflater().inflate(R.menu.base, menu);
returntrue;
}
}
子類代碼:
{
/**
* layout里復用同一布局:
* < include
* android:id="@+id/include1"
* layout="@layout/common_titlebar" />
*/
@Override
protectedvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third_main);
}
}
G. android開發什麼叫內存泄露
下面圖片是解決內存泄露的例子。例子來自android學習手冊,android學習手冊,裡面有源碼。android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用android studio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,圖標上有貝殼
在android程序開發中,當一個對象已經不需要再使用了,本該被回收時,而另外一個正在使用的對象持有它的引用從而導致它不能被回收,這就導致本該被回收的對象不能被回收而停留在堆內存中,內存泄漏就產生了。
內存泄漏有什麼影響呢?它是造成應用程序OOM的主要原因之一。由於android系統為每個應用程序分配的內存有限,當一個應用中產生的內存泄漏比較多時,就難免會導致應用所需要的內存超過這個系統分配的內存限額,這就造成了內存溢出而導致應用Crash。
了解了內存泄漏的原因及影響後,我們需要做的就是掌握常見的內存泄漏,並在以後的android程序開發中,盡量避免它。下面小編搜羅了5個android開發中比較常見的內存泄漏問題及解決辦法,分享給大家,一起來看看吧。
一、單例造成的內存泄漏
Android的單例模式非常受開發者的喜愛,不過使用的不恰當的話也會造成內存泄漏。因為單例的靜態特性使得單例的生命周期和應用的生命周期一樣長,這就說明了如果一個對象已經不需要使用了,而單例對象還持有該對象的引用,那麼這個對象將不能被正常回收,這就導致了內存泄漏。
如下這個典例:
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
這是一個普通的單例模式,當創建這個單例的時候,由於需要傳入一個Context,所以這個Context的生命周期的長短至關重要:
1、傳入的是Application的Context:這將沒有任何問題,因為單例的生命周期和Application的一樣長 ;
2、傳入的是Activity的Context:當這個Context所對應的Activity退出時,由於該Context和Activity的生命周期一樣長(Activity間接繼承於Context),所以當前Activity退出時它的內存並不會被回收,因為單例對象持有該Activity的引用。
所以正確的單例應該修改為下面這種方式:
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context.getApplicationContext();
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
這樣不管傳入什麼Context最終將使用Application的Context,而單例的生命周期和應用的一樣長,這樣就防止了內存泄漏。
二、非靜態內部類創建靜態實例造成的內存泄漏
有的時候我們可能會在啟動頻繁的Activity中,為了避免重復創建相同的數據資源,會出現這種寫法:
public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mManager == null){
mManager = new TestResource();
}
//...
}
class TestResource {
//...
}
}
這樣就在Activity內部創建了一個非靜態內部類的單例,每次啟動Activity時都會使用該單例的數據,這樣雖然避免了資源的重復創建,不過這種寫法卻會造成內存泄漏,因為非靜態內部類默認會持有外部類的引用,而又使用了該非靜態內部類創建了一個靜態的實例,該實例的生命周期和應用的一樣長,這就導致了該靜態實例一直會持有該Activity的引用,導致Activity的內存資源不能正常回收。正確的做法為:
將該內部類設為靜態內部類或將該內部類抽取出來封裝成一個單例,如果需要使用Context,請使用ApplicationContext 。
三、Handler造成的內存泄漏
Handler的使用造成的內存泄漏問題應該說最為常見了,平時在處理網路任務或者封裝一些請求回調等api都應該會藉助Handler來處理,對於Handler的使用代碼編寫一不規范即有可能造成內存泄漏,如下示例:
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//...
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadData();
}
private void loadData(){
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}
這種創建Handler的方式會造成內存泄漏,由於mHandler是Handler的非靜態匿名內部類的實例,所以它持有外部類Activity的引用,我們知道消息隊列是在一個Looper線程中不斷輪詢處理消息,那麼當這個Activity退出時消息隊列中還有未處理的消息或者正在處理消息,而消息隊列中的Message持有mHandler實例的引用,mHandler又持有Activity的引用,所以導致該Activity的內存資源無法及時回收,引發內存泄漏,所以另外一種做法為:
public class MainActivity extends AppCompatActivity {
private MyHandler mHandler = new MyHandler(this);
private TextView mTextView ;
private static class MyHandler extends Handler {
private WeakReference<Context> reference;
public MyHandler(Context context) {
reference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
activity.mTextView.setText("");
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
loadData();
}
private void loadData() {
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
}
創建一個靜態Handler內部類,然後對Handler持有的對象使用弱引用,這樣在回收時也可以回收Handler持有的對象,這樣雖然避免了Activity泄漏,不過Looper線程的消息隊列中還是可能會有待處理的消息,所以我們在Activity的Destroy時或者Stop時應該移除消息隊列中的消息,更准確的做法如下:
public class MainActivity extends AppCompatActivity {
private MyHandler mHandler = new MyHandler(this);
private TextView mTextView ;
private static class MyHandler extends Handler {
private WeakReference<Context> reference;
public MyHandler(Context context) {
reference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
activity.mTextView.setText("");
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
loadData();
}
private void loadData() {
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
使用mHandler.removeCallbacksAndMessages(null);是移除消息隊列中所有消息和所有的Runnable。當然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();來移除指定的Runnable和Message。
四、線程造成的內存泄漏
對於線程造成的內存泄漏,也是平時比較常見的,如下這兩個示例可能每個人都這樣寫過:
//——————test1
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(10000);
return null;
}
}.execute();
//——————test2
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(10000);
}
}).start();
上面的非同步任務和Runnable都是一個匿名內部類,因此它們對當前Activity都有一個隱式引用。如果Activity在銷毀之前,任務還未完成, 那麼將導致Activity的內存資源無法回收,造成內存泄漏。正確的做法還是使用靜態內部類的方式,如下:
static class MyAsyncTask extends AsyncTask<Void, Void, Void> {
private WeakReference<Context> weakReference;
public MyAsyncTask(Context context) {
weakReference = new WeakReference<>(context);
}
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(10000);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity activity = (MainActivity) weakReference.get();
if (activity != null) {
//...
}
}
}
static class MyRunnable implements Runnable{
@Override
public void run() {
SystemClock.sleep(10000);
}
}
//——————
new Thread(new MyRunnable()).start();
new MyAsyncTask(this).execute();
這樣就避免了Activity的內存資源泄漏,當然在Activity銷毀時候也應該取消相應的任務AsyncTask::cancel(),避免任務在後台執行浪費資源。
五、資源未關閉造成的內存泄漏
對於使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或者注銷,否則這些資源將不會被回收,造成內存泄漏。
H. 安卓系統可以給蘋果系統送手冊嗎
安卓系統不可以給蘋果系統送手冊。
《和平精英》游戲中的「手冊」目前並不能進行跨系統的贈送。倘若,玩家是安卓區,則無法贈送蘋果區的玩家禮物。而如果玩家是蘋果區,想贈送安卓區玩家禮物,同樣無法實現。
《和平精英》的精英手冊,分普通級與豪華版兩種,主要區別在於後者能直接提升20級,並且額外增加50%每周挑戰積分的獎勵,但是差距將近3倍。
《和平精英》是由騰訊光子工作室群自研打造的的反恐軍事競賽體驗類型國產手游,該作於2019年5月8日正式公測。
該游戲採用虛幻4引擎研發,沿襲端游《絕地求生》的玩法,以及前作《絕地求生:刺激戰場》與《絕地求生:全軍出擊》的運營模式,致力於從畫面、地圖、射擊手感等多個層面還原原始端游數據,為玩家全方位打造出極具真實感的軍事競賽體驗。
I. android 怎麼讀取res下的xml
相當於讀取res下面的文件,讀取成string類型,然後在通過xml解析器解析就行。下面是讀取res下面文件的例子,請看截圖,例子來自android學習手冊,android學習手冊,裡面有源碼。android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用android studio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,圖標上有貝殼
方法一、將要讀取的txt文件拷貝到Android工程目錄下的assets文件夾下
方法二、在res文件夾下新建raw文件夾,將txt拷貝到該目錄下
本方法是從assets中讀取
/**
* 從assets中讀取txt
*/
private void readFromAssets() {
try {
InputStream is = getAssets().open("qq.txt");
String text = readTextFromSDcard(is);
textView.setText(text);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
本方法是從raw中讀取
/**
* 從raw中讀取txt
*/
private void readFromRaw() {
try {
InputStream is = getResources().openRawResource(R.raw.qq);
String text = readTextFromSDcard(is);
textView.setText(text);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
本方法是解析輸入流,返回txt中的字元串
/**
* 按行讀取txt
*
* @param is
* @return
* @throws Exception
*/
private String readTextFromSDcard(InputStream is) throws Exception {
InputStreamReader reader = new InputStreamReader(is);
BufferedReader bufferedReader = new BufferedReader(reader);
StringBuffer buffer = new StringBuffer("");
String str;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
buffer.append("
");
}
return buffer.toString();
}
J. android meid存到哪裡
下面給你一個獲取android meid的例子,請看截圖:
例子 來自於android學習手冊,android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用android studio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,圖標上有貝殼
有時需要對用戶設備進行標識,所以希望能夠得到一個穩定可靠並且唯一的識別碼。雖然Android系統中提供了這樣設備識別碼,但是由於Android系統版本、廠商定製系統中的Bug等限制,穩定性和唯一性並不理想。而通過其他硬體信息標識也因為系統版本、手機硬體等限制存在不同程度的問題。
下面收集了一些「有能力」或「有一定能力」作為設備標識的串碼。
DEVICE_ID
這是Android系統為開發者提供的用於標識手機設備的串號,也是各種方法中普適性較高的,可以說幾乎所有的設備都可以返回這個串號,並且唯一性良好。
這個DEVICE_ID可以同通過下面的方法獲取:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); String DEVICE_ID = tm.getDeviceId();
它會根據不同的手機設備返回IMEI,MEID或者ESN碼,但在使用的過程中有以下問題:
非手機設備:最開始搭載Android系統都手機設備,而現在也出現了非手機設備:如平板電腦、電子書、電視、音樂播放器等。這些設備沒有通話的硬體功能,系統中也就沒有TELEPHONY_SERVICE,自然也就無法通過上面的方法獲得DEVICE_ID。
許可權問題:獲取DEVICE_ID需要READ_PHONE_STATE許可權,如果只是為了獲取DEVICE_ID而沒有用到其他的通話功能,申請這個許可權一來大才小用,二來部分用戶會懷疑軟體的安全性。
廠商定製系統中的Bug:少數手機設備上,由於該實現有漏洞,會返回垃圾,如:zeros或者asterisks
MAC ADDRESS
可以使用手機Wifi或藍牙的MAC地址作為設備標識,但是並不推薦這么做,原因有以下兩點:
硬體限制:並不是所有的設備都有Wifi和藍牙硬體,硬體不存在自然也就得不到這一信息。
獲取的限制:如果Wifi沒有打開過,是無法獲取其Mac地址的;而藍牙是只有在打開的時候才能獲取到其Mac地址。
獲取Wifi Mac地址:
獲取藍牙 Mac地址:
Sim Serial Number
裝有SIM卡的設備,可以通過下面的方法獲取到Sim Serial Number:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); String SimSerialNumber = tm.getSimSerialNumber();
注意:對於CDMA設備,返回的是一個空值!
ANDROID_ID
在設備首次啟動時,系統會隨機生成一個64位的數字,並把這個數字以16進制字元串的形式保存下來,這個16進制的字元串就是ANDROID_ID,當設備被wipe後該值會被重置。可以通過下面的方法獲取:
import android.provider.Settings; String ANDROID_ID = Settings.System.getString(getContentResolver(), Settings.System.ANDROID_ID);
ANDROID_ID可以作為設備標識,但需要注意:
廠商定製系統的Bug:不同的設備可能會產生相同的ANDROID_ID:9774d56d682e549c。
廠商定製系統的Bug:有些設備返回的值為null。
設備差異:對於CDMA設備,ANDROID_ID和TelephonyManager.getDeviceId() 返回相同的值。
Serial Number
Android系統2.3版本以上可以通過下面的方法得到Serial Number,且非手機設備也可以通過該介面獲取。
String SerialNumber = android.os.Build.SERIAL;
Installtion ID
以上幾種方式都或多或少存在一定的局限性或者Bug,如果並不是確實需要對硬體本身進行綁定,使用自己生成的UUID也是一個不錯的選擇,因為該方法無需訪問設備的資源,也跟設備類型無關。
這種方式的原理是在程序安裝後第一次運行時生成一個ID,該方式和設備唯一標識不一樣,不同的應用程序會產生不同的ID,同一個程序重新安裝也會不同。所以這不是設備的唯一ID,但是可以保證每個用戶的ID是不同的。可以說是用來標識每一份應用程序的唯一ID(即Installtion ID),可以用來跟蹤應用的安裝數量等。
Google Developer Blog提供了這樣的一個框架:
public class Installation { private static String sID = null; private static final String INSTALLATION = "INSTALLATION"; public synchronized static String id(Context context) { if (sID == null) { File installation = new File(context.getFilesDir(), INSTALLATION); try { if (!installation.exists()) writeInstallationFile(installation); sID = readInstallationFile(installation); } catch (Exception e) { throw new RuntimeException(e); } } return sID; } private static String readInstallationFile(File installation) throws IOException { RandomAccessFile f = new RandomAccessFile(installation, "r"); byte[] bytes = new byte[(int) f.length()]; f.readFully(bytes); f.close(); return new String(bytes); } private static void writeInstallationFile(File installation) throws IOException { FileOutputStream out = new FileOutputStream(installation); String id = UUID.randomUUID().toString(); out.write(id.getBytes()); out.close(); } }
設備唯一ID
上文可以看出,Android系統中並沒有可以可靠獲取所有廠商設備唯一ID的方法,各個方法都有自己的使用范圍和局限性,這也是目前流行的Android系統版本過多,設備也是來自不同廠商,且沒有統一標准等原因造成的。
從目前發展來看,Android系統多版本共存還會持續較長的時間,而Android系統也不會被某個設備生產廠商壟斷,長遠看Android基礎系統將會趨於穩定,設備標識也將會作為系統基礎部分而標准化,屆時這一問題才有望徹底解決。
目前的解決辦法,比較可行的是一一適配,在保證大多數設備方便的前提下,如果獲取不到,使用其他備選信息作為標識,即自己再封裝一個設備ID出來,通過內部演算法保證盡量和設備硬體信息相關,以及標識的唯一性。
android 底層是Linux,我們還是用Linux的方法來獲取:
1 cpu號:
文件在: /proc/cpuinfo
通過Adb shell 查看:
adb shell cat /proc/cpuinfo
2 mac 地址
文件路徑 /sys/class/net/wlan0/address
adb shell cat /sys/class/net/wlan0/address
xx:xx:xx:xx:xx:aa
這樣可以獲取兩者的序列號,
方法確定,剩下的就是寫代碼了
以Mac地址為例:
String getMac() {
String macSerial = null;
String str = "";
try {
Process pp = Runtime.getRuntime().exec(
"cat /sys/class/net/wlan0/address ");
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
for (; null != str;) {
str = input.readLine();
if (str != null) {
macSerial = str.trim();// 去空格
break;
}
}
} catch (IOException ex) {
// 賦予默認值
ex.printStackTrace();
}
return macSerial;
}
Android 手機上獲取物理唯一標識碼
唯一標識碼這東西在網路應用中非常有用,例如檢測是否重復注冊之類的。
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID);
我們在項目過程中或多或少會使用到設備的唯一識別碼,我們希望能夠得到一個穩定、可靠的設備唯一識別碼。今天我們將介紹幾種方式。
1. DEVICE_ID
假設我們確實需要用到真實設備的標識,可能就需要用到DEVICE_ID。在以前,我們的Android設備是手機,這個DEVICE_ID可以同通過TelephonyManager.getDeviceId()獲取,它根據不同的手機設備返回IMEI,MEID或者ESN碼,但它在使用的過程中會遇到很多問題:
非手機設備: 如果只帶有Wifi的設備或者音樂播放器沒有通話的硬體功能的話就沒有這個DEVICE_ID
許可權: 獲取DEVICE_ID需要READ_PHONE_STATE許可權,但如果我們只為了獲取它,沒有用到其他的通話功能,那這個許可權有點大才小用
bug:在少數的一些手機設備上,該實現有漏洞,會返回垃圾,如:zeros或者asterisks的產品
2. MAC ADDRESS
我們也可以通過手機的Wifi或者藍牙設備獲取MAC ADDRESS作為DEVICE ID,但是並不建議這么做,因為並不是所有的設備都有Wifi,並且,如果Wifi沒有打開,那硬體設備無法返回MAC ADDRESS.
3. Serial Number
在Android 2.3可以通過android.os.Build.SERIAL獲取,非手機設備可以通過該介面獲取。
4. ANDROID_ID
ANDROID_ID是設備第一次啟動時產生和存儲的64bit的一個數,當設備被wipe後該數重置
ANDROID_ID似乎是獲取Device ID的一個好選擇,但它也有缺陷:
它在Android <=2.1 or Android >=2.3的版本是可靠、穩定的,但在2.2的版本並不是100%可靠的
在主流廠商生產的設備上,有一個很經常的bug,就是每個設備都會產生相同的ANDROID_ID:9774d56d682e549c
5. Installtion ID : UUID
以上四種方式都有或多或少存在的一定的局限性或者bug,在這里,有另外一種方式解決,就是使用UUID,該方法無需訪問設備的資源,也跟設備類型無關。
這種方式是通過在程序安裝後第一次運行後生成一個ID實現的,但該方式跟設備唯一標識不一樣,它會因為不同的應用程序而產生不同的ID,而不是設備唯一ID。因此經常用來標識在某個應用中的唯一ID(即Installtion ID),或者跟蹤應用的安裝數量。很幸運的,Google Developer Blog提供了這樣的一個框架:
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
如何獲取Android手機的唯一標識?
代碼: 這里是你在Android里讀出 唯一的 IMSI-ID / IMEI-ID 的方法。
Java:
String myIMSI = android.os.SystemProperties.get(android.telephony.TelephonyProperties.PROPERTY_IMSI);
// within my emulator it returns: 310995000000000
String myIMEI = android.os.SystemProperties.get(android.telephony.TelephonyProperties.PROPERTY_IMEI);
// within my emulator it returns: 000000000000000
註:android.os.SystemProperties的標簽被打上@hide了,所以sdk中並不會存在。如果需要使用,需要有android的source code支持。