获取手机基本信息

手机的基本信息分两类,一类是与电话有关的信息,另一类是设备自身的信息。
与电话有关的信息可由TelephonyManager类获得,常用的参数与对应的方法如下所示:
网络运营商名称 : getNetworkOperatorName
网络运营商编号 : getNetworkOperator,返回五位数字,前三位表示国家代码(中国的为460),后两位表示运营商代码(中国移动为0,中国联通为1,中国电信为2)
手机类型 : getPhoneType
网络类型 : getNetworkType获得细分类型,getNetworkClass获得大类如2G/3G/4G
SIM卡状态 : getSimState
SIM卡运营商名称 : getSimOperatorName
SIM卡运营商编号 : getSimOperator
SIM卡序列号 : getSimSerialNumber
IMSI : getSubscriberId
IMEI : getDeviceId
手机号码 : 实测发现多数情况下getLine1Number和getMsisdn都无法正确取到号码,但是很多APP又需要用户的手机号,那又得想办法获取号码,获取的方法大致有如下几种:
1、用户首次使用,提示用户注册手机号,然后保存起来,下次就能取到手机号了;
2、APP自动用该手机发一条免费短信(比如向10086发),然后到发件箱中寻找该短信的发送号码;
3、如果能连到运营商的支撑系统,那么根据IMSI去后台系统查询手机号,这也是可以的;

设备自身的信息可由Build类获得,常用的参数与对应的方法如下所示:
手机厂商 : Build.MANUFACTURER
手机品牌 : Build.BRAND
手机型号 : Build.MODEL
设备名称 : Build.DEVICE
CPU指令 : Build.CPU_ABI
芯片型号 : Build.HARDWARE
手机序列号 : Build.SERIAL
SDK版本 : Build.VERSION.SDK_INT
系统版本 : Build.VERSION.RELEASE
版本代号 : Build.VERSION.CODENAME

功能开关的查询与设置

常用的设备功能主要有:屏幕自动旋转、亮度自动调节、飞行模式开关、GPS开关、蓝牙开关、WLAN开关、数据连接开关、闪光灯/手电筒开关。各功能的设置途径各不相同,废话少说,直接上代码:

import java.lang.reflect.Method;import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;//屏幕自动旋转、亮度自动调节、飞行模式开关、GPS开关、蓝牙开关、WLAN开关、数据连接开关、闪光灯/手电筒开关
public class SwitchUtil {private static final String TAG = "SwitchUtil";//获取屏幕的自动旋转状态public static boolean getRotationStatus(Context context) {int status = 0;try {status = android.provider.Settings.System.getInt(context.getContentResolver(),android.provider.Settings.System.ACCELEROMETER_ROTATION);} catch (SettingNotFoundException e) {Log.d(TAG, "getRotationStatus error: "+e.getMessage());}return status==1?true:false;}//设置屏幕的自动旋转开关public static void setRotationStatus(Context context, boolean enabled) {int status = (enabled==true)?1:0;Uri uri = android.provider.Settings.System.getUriFor("accelerometer_rotation");android.provider.Settings.System.putInt(context.getContentResolver(), "accelerometer_rotation", status);context.getContentResolver().notifyChange(uri, null);}//设置亮度自动调节的开关public static void setAutoBrightStatus(Context context, boolean enabled) {int screenMode = (enabled==true)?Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC:Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;Settings.System.putInt(context.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE,screenMode);}//获取亮度自动调节的状态public static boolean getAutoBrightStatus(Context context) {int screenMode = Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;try {screenMode = Settings.System.getInt(context.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS_MODE);} catch (Exception e) {Log.d(TAG, "getAutoBrightStatus error: "+e.getMessage());}return screenMode==Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC?true:false;}//获取飞行模式的开关状态public static boolean getAirplaneStatus(Context context) {boolean status = Settings.System.getInt(context.getContentResolver(),Settings.Global.AIRPLANE_MODE_ON, 0) == 1 ? true : false;return status;}//开启或关闭飞行模式。注意只有系统应用才能发送广播,普通app发送广播会提示无权限@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)public static void setAirplaneStatus(Context context, boolean enable) {Settings.System.putInt(context.getContentResolver(),Settings.Global.AIRPLANE_MODE_ON, enable ? 1 : 0);Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);intent.putExtra("state", enable);context.sendBroadcast(intent);}//获取Gps的开关状态public static boolean getGpsStatus(Context context) {LocationManager locationMgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);boolean gps_enabled = locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER);return gps_enabled;}//打开或关闭Gps@TargetApi(Build.VERSION_CODES.KITKAT)public static void setGpsStatus(Context context, boolean enabled) {Intent gpsIntent = new Intent();gpsIntent.setClassName("com.android.settings","com.android.settings.widget.SettingsAppWidgetProvider");gpsIntent.addCategory("android.intent.category.ALTERNATIVE");gpsIntent.setData(Uri.parse("custom:3"));try {PendingIntent.getBroadcast(context, 0, gpsIntent, 0).send();} catch (Exception e) {Log.d(TAG, "setGpsStatus error: "+e.getMessage());}  }//获取定位的开关状态public static boolean getLocationStatus(Context context) {LocationManager locationMgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);boolean gps_enabled = locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER);boolean network_enabled = locationMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER);return gps_enabled || network_enabled;}//获取蓝牙的开关状态public static boolean getBlueToothStatus(Context context) {BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();boolean enabled = false;switch (bluetoothAdapter.getState()) {case BluetoothAdapter.STATE_ON:case BluetoothAdapter.STATE_TURNING_ON:enabled = true;break;case BluetoothAdapter.STATE_OFF:case BluetoothAdapter.STATE_TURNING_OFF:default:enabled = false;break;}return enabled;}//打开或关闭蓝牙public static void setBlueToothStatus(Context context, boolean enabled) {BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (enabled == true) {bluetoothAdapter.enable();} else {bluetoothAdapter.disable();}}//获取Wifi的开关状态public static boolean getWlanStatus(Context context) {WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);return wifiMgr.isWifiEnabled();}//打开或关闭Wifipublic static void setWlanStatus(Context context, boolean enabled) {WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);wifiMgr.setWifiEnabled(enabled);}//获取数据连接的开关状态public static boolean getMobileDataStatus(Context context) {ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);boolean isOpen = false;try {String methodName = "getMobileDataEnabled";Method method = connMgr.getClass().getMethod(methodName);isOpen = (boolean) method.invoke(connMgr);} catch (Exception e) {Log.d(TAG, "getMobileDataStatus error: "+e.getMessage());}return isOpen;}//打开或关闭数据连接public static void setMobileDataStatus(Context context, boolean enabled) {ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);try {String methodName = "setMobileDataEnabled";Method method = connMgr.getClass().getMethod(methodName, Boolean.TYPE);//method.setAccessible(true);method.invoke(connMgr, enabled);} catch (Exception e) {Log.d(TAG, "setMobileDataStatus error: "+e.getMessage());}}//Camera对象需要做成单例模式,因为Camera不能重复打开private static Camera mCamera = null;//获取闪光灯/手电筒的开关状态public static boolean getFlashStatus(Context context) {if (mCamera == null) {mCamera = Camera.open();}Parameters parameters = mCamera.getParameters();String flashMode = parameters.getFlashMode();boolean enabled;if (flashMode.equals(Parameters.FLASH_MODE_TORCH)) {enabled = true;} else {enabled = false;}return enabled;}//打开或关闭闪光灯/手电筒public static void setFlashStatus(Context context, boolean enabled) {if (mCamera == null) {mCamera = Camera.open();}Parameters parameters = mCamera.getParameters();if (enabled == true) {parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);// 开启mCamera.setParameters(parameters);} else {parameters.setFlashMode(Parameters.FLASH_MODE_OFF);// 关闭mCamera.setParameters(parameters);mCamera.release();mCamera = null;}}}

看完了代码,总结一下功能开关的注意事项:
1、开启或关闭飞行模式,除了修改Settings,还得发送广播通知系统完成其他处理,因为开启飞行模式得同时关闭wifi、数据连接、蓝牙等功能。但是只有系统应用才能发送广播,普通app发送广播会提示无权限。
2、定位不等于GPS,定位包括GPS定位和网络定位,因此若要判断定位功能是否开启,得同时判断GPS定位和网络定位都不可用才是定位关闭。
3、开关闪光灯/手电筒借助了Camera类,不过Camera不能多次打开,否则会报错无效连接,所以在工具代码中要把Camera做成单例模式,确保每次使用Camera都只Open一次。

跳转到系统设置界面

上面可在代码中直接设置的仅仅是些基本的设备功能,还有更多的系统管理需要在专门的系统设置界面来完成。这些无法在我们代码中完成的工作,就得跳到系统设置页面,由用户去手工操作。下面是具体设置页面与Action的对应关系:
系统应用Settings中的设置
系统设置页面 : Settings.ACTION_SETTINGS
应用管理页面 : Settings.ACTION_APPLICATION_SETTINGS
存储管理页面 : Settings.ACTION_MEMORY_CARD_SETTINGS或者Settings.ACTION_INTERNAL_STORAGE_SETTINGS
显示设置页面 : Settings.ACTION_DISPLAY_SETTINGS
声音/铃声设置页面 : Settings.ACTION_SOUND_SETTINGS (有的手机是情景设置页面)
日期设置页面 : Settings.ACTION_DATE_SETTINGS
定位设置页面 : Settings.ACTION_LOCATION_SOURCE_SETTINGS
同步设置页面 : Settings.ACTION_SYNC_SETTINGS
输入法设置页面 : Settings.ACTION_INPUT_METHOD_SETTINGS
系统应用Phone中的设置
通话设置页面 : 按如下方式跳转(有的手机不在这个路径)

 Intent intent = new Intent(Intent.ACTION_MAIN);intent.setClassName("com.android.phone","com.android.phone.CallFeaturesSetting");startActivity(intent);

使用通讯功能

打电话/拨号

打电话调用系统的拨号应用即可,示例代码如下:

         Intent intent = new Intent();Uri uri = Uri.parse("tel:"+"15960238696");intent.setAction(Intent.ACTION_CALL);intent.setData(uri);startActivity(intent);

发短信

发短信有两种方式,分别是手工发送和自动发送,手工发送是调用系统的短消息应用,自动发送则是调用SmsManager的相关API。使用SmsManager类有三个注意点:
1、因手机短信有长度限制,故需对过长的短信内容进行拆分,具体是调用SmsManager类的divideMessage方法;
2、SmsManager同时支持短短信和长短信两种方式,发送短短信调用的是sendTextMessage方法,发送长短信调用的是sendMultipartTextMessage方法。长短信虽然在发送时也需要拆分,但对方收到的是一条完整的短信;另外,长短信方式可以只发送一次广播,而短短信方式每发一条短信就会发送一次广播。
3、如果需要处理短信发送成功通知事件和短信接收成功事件,则需确保打开发送短信的完全权限,不是那种还需提示的不完整权限,不然不但收不到广播,连短信都无法发送了。

发邮件

发邮件需要调用手机上的其他邮件客户端,如QQ邮箱,这样发送时在列表中选择QQ邮箱才能完成邮件发送操作,示例代码如下:

         Intent intent = new Intent(Intent.ACTION_SEND);String[] to = {"aaa@163.com"};String[] cc = {"abc@163.com"};String[] bcc = {"xyz@163.com"};intent.putExtra(Intent.EXTRA_EMAIL, to);intent.putExtra(Intent.EXTRA_CC, cc);intent.putExtra(Intent.EXTRA_BCC, bcc);intent.putExtra(Intent.EXTRA_SUBJECT, "这里是邮件标题");intent.putExtra(Intent.EXTRA_TEXT, "这里是邮件内容");intent.setType("message/rfc822");startActivity(Intent.createChooser(intent, "请选择邮件客户端"));

代码例子

打电话、发短信、发邮件的完整代码例子如下:

import java.util.ArrayList;import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;public class MobileActivity extends Activity implements OnClickListener {private static final String TAG = "MobileActivity";private TextView tv_send, tv_deliver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_mobile);Button btn_dial = (Button) findViewById(R.id.btn_dial);Button btn_sms_manual = (Button) findViewById(R.id.btn_sms_manual);Button btn_sms_auto = (Button) findViewById(R.id.btn_sms_auto);Button btn_sms_long = (Button) findViewById(R.id.btn_sms_long);Button btn_email = (Button) findViewById(R.id.btn_email);btn_dial.setOnClickListener(this);btn_sms_manual.setOnClickListener(this);btn_sms_auto.setOnClickListener(this);btn_sms_long.setOnClickListener(this);btn_email.setOnClickListener(this);tv_send = (TextView) findViewById(R.id.tv_send);tv_deliver = (TextView) findViewById(R.id.tv_deliver);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_dial) {Intent intent = new Intent();Uri uri = Uri.parse("tel:"+"15960238696");intent.setAction(Intent.ACTION_CALL);intent.setData(uri);startActivity(intent);} else if (v.getId() == R.id.btn_sms_manual) {sendSmsManual("15960238696", "我把短信丢过去就不管结果啦");} else if (v.getId() == R.id.btn_sms_auto) {sendSmsAuto("15960238696", "快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。", SMS_SHORT);} else if (v.getId() == R.id.btn_sms_long) {sendSmsAuto("15960238696", "快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。快来看看短信发成功了没有。", SMS_LONG);} else if (v.getId() == R.id.btn_email) {Intent intent = new Intent(Intent.ACTION_SEND);String[] to = {"aaa@163.com"};String[] cc = {"abc@163.com"};String[] bcc = {"xyz@163.com"};intent.putExtra(Intent.EXTRA_EMAIL, to);  //主送intent.putExtra(Intent.EXTRA_CC, cc);  //抄送intent.putExtra(Intent.EXTRA_BCC, bcc);  //密送intent.putExtra(Intent.EXTRA_SUBJECT, "这里是邮件标题");intent.putExtra(Intent.EXTRA_TEXT, "这里是邮件内容");intent.setType("message/rfc822");startActivity(Intent.createChooser(intent, "请选择邮件客户端"));}}public void sendSmsManual(String phoneNumber, String message) {if (PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber)) {Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+ phoneNumber));intent.putExtra("sms_body", message);startActivity(intent);}}public void sendSmsAuto(String phoneNumber, String message, int type) {Intent sentIntent = new Intent(SENT_SMS_ACTION);sentIntent.putExtra(PHONE, phoneNumber);sentIntent.putExtra(MESSAGE, message);PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, sentIntent, PendingIntent.FLAG_UPDATE_CURRENT);Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);deliverIntent.putExtra(PHONE, phoneNumber);deliverIntent.putExtra(MESSAGE, message);PendingIntent deliverPI = PendingIntent.getBroadcast(this, 1, deliverIntent, PendingIntent.FLAG_UPDATE_CURRENT);SmsManager smsManager = SmsManager.getDefault();// 拆分短信内容(手机短信长度限制)ArrayList<String> divideContents = smsManager.divideMessage(message);if (type == SMS_SHORT) {for (String text : divideContents) {//要确保打开发送短信的完全权限,不是那种还需提示的不完整权限smsManager.sendTextMessage(phoneNumber, null, text, sentPI, deliverPI);}} else if (type == SMS_LONG) {ArrayList<PendingIntent> sendPiArray = new ArrayList<PendingIntent>();sendPiArray.add(sentPI);ArrayList<PendingIntent> deliverPiArray = new ArrayList<PendingIntent>();deliverPiArray.add(deliverPI);//发送长短信使用方法sendMultipartTextMessage//长短信方式可以只发送一次广播,短短信方式每发一条短信就会发送一次广播smsManager.sendMultipartTextMessage(phoneNumber, null, divideContents, sendPiArray, deliverPiArray);}}private int SMS_SHORT=0, SMS_LONG=1;private String SENT_SMS_ACTION = "com.example.exmdevice.SENT_SMS_ACTION";private String DELIVERED_SMS_ACTION = "com.example.exmdevice.DELIVERED_SMS_ACTION";private String PHONE = "phone";private String MESSAGE = "message";@Overridepublic void onStart() {super.onStart();sendReceiver = new SendReceiver();registerReceiver(sendReceiver, new IntentFilter(SENT_SMS_ACTION));deliverReceiver = new DeliverReceiver();registerReceiver(deliverReceiver, new IntentFilter(DELIVERED_SMS_ACTION));}@Overridepublic void onStop() {unregisterReceiver(sendReceiver);unregisterReceiver(deliverReceiver);super.onStop();}private SendReceiver sendReceiver;private class SendReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d(TAG, "SendReceiver onReceive");switch (getResultCode()) {case Activity.RESULT_OK:String phone = intent.getStringExtra(PHONE);String message = intent.getStringExtra(MESSAGE);String desc = String.format("您的短信已发送成功。接收人为%s,短信内容为:%s", phone, message);tv_send.setText(desc);break;case SmsManager.RESULT_ERROR_GENERIC_FAILURE:case SmsManager.RESULT_ERROR_RADIO_OFF:case SmsManager.RESULT_ERROR_NULL_PDU:tv_send.setText("短信发送异常代码为"+getResultCode());break;}}}private DeliverReceiver deliverReceiver;private class DeliverReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d(TAG, "DeliverReceiver onReceive");if (intent != null) {String phone = intent.getStringExtra(PHONE);String message = intent.getStringExtra(MESSAGE);String desc = String.format("您的短信已成功接收。接收人为%s,短信内容为:%s", phone, message);tv_deliver.setText(desc);}}}}

权限申请

通过前面对设备的基本操作介绍,可看到Android四大组件各显神通,各组件协同配合完成了许多功能。具体的组件使用分类如下:
1、Activity:包括拨号(Intent.ACTION_CALL)、手工发短信(Intent.ACTION_SENDTO)、发邮件(Intent.ACTION_SEND)、系统设置页面(Settings.ACTION_SETTINGS)以及其他分项设置页面。
2、Service:包括获取子系统服务的管理器,如电话管理器TelephonyManager(Context.TELEPHONY_SERVICE)、定位管理器LocationManager(Context.LOCATION_SERVICE)、蓝牙管理器BluetoothAdapter(BLUETOOTH_MANAGER_SERVICE)、WLAN管理器WifiManager(Context.WIFI_SERVICE)、数据连接管理器ConnectivityManager(Context.CONNECTIVITY_SERVICE)。
3、Broadcast:包括开关飞行模式、开关GPS、自动发送短信的发送成功通知与接收成功通知。
4、ContentProvider:包括通过ContentResolver获取与开关的功能,如屏幕自动旋转、亮度自动调节、飞行模式等等。

由于操作设备涉及到一些系统层面与硬件层面的交互,因此需要给APP赋予相关的权限,这样才能合法的使用系统服务与硬件设施。本节中用到的权限主要有:

    <!-- 读取手机设置 --><uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- 更改手机设置 --><uses-permission android:name="android.permission.WRITE_SETTINGS" /><!-- 定位 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><!-- 蓝牙 --><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><!-- WLAN --><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_NETWORK_STATE" /><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /><!-- 摄像头与闪光灯/手电筒 --><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.FLASHLIGHT" /><!-- 拨号/打电话 --><uses-permission android:name="android.permission.CALL_PHONE" /><!-- 发短信/收短信/写短信/读短信 --><uses-permission android:name="android.permission.SEND_SMS" /><uses-permission android:name="android.permission.RECEIVE_SMS" /><uses-permission android:name="android.permission.WRITE_SMS" /><uses-permission android:name="android.permission.READ_SMS" /><!-- 下面是其他常用的权限 --><!-- 上网 --><uses-permission android:name="android.permission.INTERNET" /><!-- 震动 --><uses-permission android:name="android.permission.VIBRATE" /><!-- 录像/录音 --><uses-permission android:name="android.permission.RECORD_VIDEO"/><uses-permission android:name="android.permission.RECORD_AUDIO" /><!-- SD卡 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><!-- 读写联系人 --><uses-permission android:name="android.permission.READ_CONTACTS" /><uses-permission android:name="android.permission.WRITE_CONTACTS" /><!-- 读写通话记录 --><uses-permission android:name="android.permission.READ_CALL_LOG"/><uses-permission android:name="android.permission.WRITE_CALL_LOG"/><!-- 接收开机广播 --><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><!-- 无需通知的下载 --><uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /><!-- 允许Service服务弹出对话框 --><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

点击下载本文用到的手机设备基本操作的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(五十五)手机设备基本操作相关推荐

  1. Android开发笔记(十五)淡入淡出动画TransitionDrawable

    说到淡入淡出动画,可能大家会想到补间动画里面的AlphaAnimation,不过这个深浅动画只能对透明度做渐变效果,也就是只能对一个图形做深浅的颜色变换.如果我们想要从A图片逐渐变为B图片,也就是要实 ...

  2. Android开发笔记(九十五)自定义Drawable

    Drawable Bitmap是Android对图像的定义描述,而Drawable则是对图像的展现描述,在View视图中显示图像都是通过Drawable来实现的.其中有关Bitmap的介绍参见< ...

  3. Android开发笔记(一百五十七)使用OpenGL实现翻书动画

    上一篇文章介绍了如何通过纹理渲染绘制地球仪,当然OpenGL的三维图形处理能力是很强大的,只要善于利用OpenGL,就能很方便地虚拟各种现实生活中的动画效果.本文再来谈谈使用OpenGL实现浏览电子书 ...

  4. Android开发笔记(一百五十四)OpenGL的画笔工具GL10

    上一篇文章介绍了OpenGL绘制三维图形的流程,其实没有传说中的那么玄乎,只要放平常心把它当作一个普通控件就好了,接下来继续介绍OpenGL具体的绘图操作,这项工作得靠三维图形的画笔GL10来完成了. ...

  5. Android开发笔记(一百五十八)运行时动态授权管理

    App开发过程中,涉及到硬件设备的操作,比如拍照.录音.定位等等,都要在AndroidManifest.xml中声明相关的权限.可是Android系统为了防止某些App滥用权限,从而允许用户在系统设置 ...

  6. Android开发笔记(一百五十九)Android7.0的分屏模式

    现在的手机屏幕越来越大,使得在屏幕上同时开多个窗口不再奢侈,因此Android从7.0开始顺势推出了分屏功能,也被称作多窗口模式.比如把竖长的手机屏幕分成上下两个窗口,一边在上面的窗口中观看电影,一边 ...

  7. Android开发笔记(一百五十二)H5通过WebView上传图片

    上一篇文章介绍了WebView与JS之间的数据交互,其实就是把字符串传来传去,这对文本格式的信息传输来说倒还凑合,倘若要传输图片信息就不管用了.所以,要想让h5网页支持从手机上传图片,还得另外想办法, ...

  8. Android开发笔记(一百五十)自动识别验证码图片

    若问目前IT领域最炙手可热的技术方向,必属人工智能(简称AI)无疑.前有谷歌的阿法狗完胜围棋世界冠军柯洁,后有微软小冰出版了诗集<阳光失了玻璃窗>,一时间沸沸扬扬,似乎人工智能无所不能,从 ...

  9. Android开发笔记(一百五十六)通过渲染纹理展示地球仪

    上一篇文章介绍了如何使用GL10描绘三维物体的线段框架,后面给出的立方体和球体效果图,虽然看起来具备立体的轮廓,可离真实的物体还差得远.因为现实生活中的物体不仅仅有个骨架,还有花纹有光泽(比如衣服), ...

  10. Android开发笔记(一百五十五)利用GL10描绘点、线、面

    上一篇文章介绍了GL10的常用方法,包括如何设置颜色.如何指定坐标系.如何调整镜头参数.如何挪动观测方位等等,不过这些方法只是绘图前的准备工作,真正描绘点.线.面的制图工作并未涉及,那么本文就来谈谈如 ...

最新文章

  1. solidworks activator未响应_SolidWorks之初识工程图
  2. 有没有python的班_【万字长文】别再报班了,一篇文章带你入门Python
  3. 针对新手的Java EE7和Maven项目–第7部分
  4. [软技能] png-8和png-24有什么区别?
  5. mysql中同一天入职怎么表示_ORACLE入职考试题及答案
  6. ubuntu如何解压.tar.gz
  7. 【大数据部落】R在GIS中用ggmap地理空间数据分析
  8. 谈谈坚持写博客的感悟
  9. redies集群方案
  10. Git 版本控制系统的安装与使用
  11. java实现光盘摆渡_一种光盘摆渡机的制作方法
  12. 初中不读学计算机难吗,为什么初中生更加适合学习计算机编程?
  13. 控制系统设计专题(四)——控制分配矩阵的求解及相关问题
  14. C语言中带负数的除法
  15. 分享云安全实践,透视2022亚马逊云科技re:Inforce全球安全大会
  16. Note For Linux By Jes(12)-认识系统服务(daemons)
  17. L1-038 新世界 (5 分) C语言
  18. cnpm : 无法加载文件 D:\myDEV\newNode\node_global\cnpm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com
  19. 网安学习日记之 PKI技术
  20. mac idea 常用快捷键总结

热门文章

  1. TensorFlow2.0:索引和切片(2)
  2. Vue入门指南-05 Vue实例的生命周期(快速上手vue)
  3. dataframe drop_Pandas数据结构Series和DataFrame基础详解
  4. 文件格式和扩展名不匹配。文件可能已损坏或不安全。除非您信任其来源,否则请勿打开。是否仍要打开它?
  5. 怎样将Redis以本地服务方式进行启动?
  6. 最新快手JS逆向分析
  7. Linux配置JAVA环境变量(图文教程)
  8. 2019新悦动打火困难解决了吗_悦动大面积存在启动困难北京现代检查不出原因就换零件...
  9. android启动画面白屏,Android app启动时黑屏或者白屏的原因及解决办法
  10. 服务器虚拟化的意思,服务器虚拟化存储的好处以及作用