安卓逆向入门-Android后端开发入门 Activity 在一个Android应用中,多个Activity组成Activity栈,当前活动的Activity位于栈顶,之前的被压入下面,成为非活动Activity,等待是否可能被恢复为活动状态。Activity声明周期中有4个状态:
状态
描述
运行状态
当前Activity,位于Activity栈顶,用户可见,可获得焦点
暂停状态
失去焦点的Activity,仍然可见
停止状态
被其他Activity覆盖,不可见,但保存所有状态信息。低内存状态可能被系统kill
销毁状态
该Activity结束
生命周期中回调方法有:
方法
描述
onCreate
创建Activity时被回调
onStart
启动Activity时被回调
onResume
由暂停恢复为活动状态时调用
onPause
暂停Activity时被回调
onRestart
重启Activity时被回调
onStop
停止Activity时被回调
onDestroy
销毁Activity时被回调
创建Activity方法为:
1 2 3 4 5 6 7 8 import android.app.Activity;public class MyActivity extends Activity { @Override public void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_my); } }
还要在AndroidManifest.xml中application标签中配置activity标签:
1 2 3 4 5 6 7 8 9 <application > <activity android:anme =".DetailActivity" android:label ="说明性文字" android:theme ="要应用的主题" > ... </activity > </application >
操作有:
1 2 3 4 5 6 Intent intent=new Intent (MainActivity.this ,DetailActivity.class); startActivity(intent); finish();
Bundle是个键值对的组合,保存要携带的数据包。在Activity之间交换数据时,可将要保存的数据存放在Bundle对象中,通过Intent传递数据。
1 2 3 4 5 6 7 8 9 10 11 Intent intent=new Intent (MainActivity.this , AddressActivity.class); Bundle bundle=new Bundle (); bundle.putCharSequence("name" ,name); intent.putExtras(bundle); startActivity(intent); Intetnt intent=getIntent(); Bundle bundle=intent.getExtras(); System.out.println(bundle.getString("name" ));
还可以调用另一个Activity并返回结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Intent intent=new Intent (MainActivity.this ,HeadActivity.class); startActivityForResult(intent,0x11 ); Intent intent=getIntent(); Bundle bundle=new Bundle (); bundle.putInt("imageId" ,imageId[posistion]); intent.putExtras(bundle); setResult(0x11 ,intent); finish(); @Override protected void onActivityResult (int requestCode,int resultCode,Intent data) { super .onActivityResult(requestCode,resultCode,data); if (requestCode==0x11 &&resultCode==0x11 ){ Bundle bundle=data.getExtras(); int imageId=bundle.getInt("imageId" ); } }
Fragment可在一个单独的Activity中建立多个UI面板,也可在多个Activity中重用Fragment。一个Fragment必须嵌入到一个Activity中,也有自己的生命周期。当Activity被暂停/销毁时,其中的Fragmen也被暂停/销毁。当一个Activity在运行时,可单独对每个Fragment进行操作。创建方法如下:
1 2 3 4 5 6 7 8 public class NewsFragment extends Fragment { @Nullable @Override public View onCreateView (LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) { View v=inflater.inflate(R.layout.news,container,false ); return false ; } }
为布局文件.xml添加Fragment:
1 2 3 4 5 6 7 8 <fragment android:name ="com.xxx.ListFragment" android:id ="@+id/list" android:layout_weight ="1" android:layout_width ="0dp" android:layout_height ="match_parent" /> ...
或者在Activity运行时添加Fragment法:
1 2 3 4 DetailFragment details=new DetailFragment (); FragmentTransaction ft=getFragmentManager().beginTransaction(); ft.add(android.R.id.content,details); ft.commit();
Intent 一个Android程序由Activity、Service和BroadcastReceiver组件组成,它们之间通信由Intent协助完成,后者负责对应用中一次操作的Action、Action涉及的Data、Extras进行描述。Android根据Intent的描述,找到对应组件,将Intent传给调用的组件,我弄成组件的调用。Intent起着媒体中介作用,提供组件间互相调用的相关信息,实现调用者和被调用者之间的解耦。
Intent对象包含以下属性:
属性
作用
Component name
指定为处理Intent对象的组件名称
Action
Intent要完成的一个动作
Category
用来对执行动作的类别进行描述
Data
向Action提供要操作的数据
Extras
向Intent组件添加附加信息
Flags
指示Android程序如何启动一个Activity
Component name属性设置Intent对象的组件名称,属性值是个ComponentName对象。,需要指定包名和类名,可选。若设置该属性则Intent对象或被发送给指定类的实例,若没设置,Android用Intent中其他信息定位合适的目标组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ComponentName(Context context,Class<?> cls); ComponentName(String pkg,String cls); Intent intent=new Intent (); ComponentName componentName=new ComponentName (MainActivity.this ,DetailActivity.class); intent.setComponent(componentName); public Intent setClass (Context packageContext,Class<?> cls) ;Intent intent=new Intent (); intent.setClass(this ,DetailActivity.class); public Intent setClassName (Context packageContext,String className) ;Intent intent=new Intent (); intent.setClassName(MainActivity.this ,"com.xxx.xxx" ); public ComponentName getComponent () ;ComponentName componentName=getIntent().getComponent(); Log.i(componentName.getPackageName()+componentName.getShortClassName());
Action属性指定要执行的动作,目标组件分为Activity和Broadcast两类。标准Activity用于启动Activity,动作字符串如“android.intent.action.MAIN”:
字符串
说明
MAIN
初始Activity启动,没有数据输入输出
VIEW
显示数据
ATTACH_DATA
数据该附属于其他地方
EDIT
显示数据并用于编辑
PICK
选择并返回一项数据
CHOOSER
显示一个Activity选择器
GET_CONTENT
允许用户选择并返回特定类型数据
DIAL
拨打电话
CALL
给某人拨打电话
SEND
发送消息
SENDTO
指定接收者并发送消息
ANSWER
接听电话
INSERT
向容器中插入空白项
DELETE
从容器中删除给定数据
RUN
无条件运行数据
SYNC
执行数据同步
PICK_ACTIVITY
选择给定Intent的Activity,返回选择的类
SEARCH
执行查询
WEB_SEARCH
执行联机查询
FACTORY_TEST
工厂测试主注入点
标准广播动作用于接收广播:
字符串
说明
TIME_TICK
每分钟通知一次当前时间改变
TIME_CHANGED
通知时间被修改
TIMEZONE_CHANGED
通知时区被修改
BOOT_COMPLETED
系统启动完成后发出一次通知
PACKAGE_ADDED
通知新应用程序包已安装到设备上
PACKAGE_CHANGED
通知已安装应用程序包已被修改
PACKAGE_REMOVED
从设备中删除应用程序包
PACKAGE_RESTARTED
通知用户重启应用程序包,其所有进程被关闭
PACKAGE_DATA_CLEARED
通知用户清空程序包中数据
UID_REMOVED
通知从系统中删除用户ID值
BATTERY_CHANGED
含充电状态、等级和其他电池信息
POWER_CONNECTED
通知设备连接外置电源
POWER_DISCONNECED
通知设备移除外置电源
SHUTDOWN
通知设备已关闭
方法有:
1 2 3 4 public Intent setAction (String action) ;public String getAction () ;
Data向Action提供要操作的数据,数据规格如下:
操作类型
实例
浏览网页
http://ww.xxx.com
拨打电话
tel:043187654321
发送短信
smsto:13666666666
查找SD卡文件
file:///sdcard/Download/ly.jpg
显示地图
geo:26.236966,-26.998566
联系人信息
content://com.android.contacts/contacts/1
方法有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public Intent setData (Uri data) ;intent.setData(Uri.parse("content://com.android.contacts/contacts/1" )); public Intent setType (String type) ;intent.setType("image/" ); public Intent setDataAndType (Uri data,String type) ;Uri uri=Uri.fromFile(new File (Environment.getExternalStorageDirectory().getPath()+"/pictures/img01.png" )); intent.setDataAndType(uri,"image/*" ); public Uri getData () ;public String getType () ;
Category属性对执行动作的类别进行描述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public Intent addCategory (String category) ;Intent intent=new Intent (); intent.setAction(Intent.ACTION_MAIN); intent.addCategory("android.intent.category.HOME" ); public void removeCategory (String category) ;intent.removeCategory("android.intent.category.HOME" ); public Set<String> getCategories () ;Set<String> categories=intent.getCategories();
Extras添加附加信息:
1 2 3 4 5 6 7 8 9 public Intent putExtras (Bundle extras) ;Bundle bundle=new Bundle (); bundle.putCharSequence("name" ,"xxx" ); intent.putExtras(bundle); public Bundle getExtras () ;
Flags属性指示Android程序如何启动一个Activity,以及启动后如何处理。
1 2 3 4 5 6 7 8 9 10 public Intent setFlags (int flags) ; intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); public Intent addFlags (int flags) ;public int getFlags () ;
隐式Intent为创建Intent对象时不指定具体接收者,让系统根据相应匹配机制找,如:
1 2 3 4 Intent intent=new Intent (); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.xxx.com" )); startActivity(intent);
消息机制 消息提示框:
1 Toast toast=Toast.makeText(this ,"内容" ,Toast.LENGTH_SHORT);
对话框:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 AlertDialog alertDialog=new AlertDialog .Builder(MainActivity.this ).create(); alertDialog.setIcon(R.drawable.advise); alertDialog.setTitle("标题" ); alertDialog.setMessage("内容" ); alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,"是" ,new DialogInterface .OnClickListener(){ @Override public void onClick (DialogInterface dialog,int which) { Toast.makeText(MainActivity.this ,"xxx" ,Toast.LENGTH_SHORT).show(); } }); alertDialog.show(); final String[] items=new String []{"xxx" ,"xxx" ,"xxx" ,"xxx" };AlertDialog.Builder builder=new AlertDialog .Builder(MainActivity.this ); builder.setIcon(R.drawable.advise1); builder.setTitle("标题" ); builder.setItems(items,new DialogInterface .OnClickListener(){ @Override public void onClick (DialogInterface dialog,int which) { Toast.makeText(MainActivity.this ,items[which],Toast.LENGTH_SHORT).show(); } }); builder.create.show();
状态栏上显示通知:
1 2 3 4 5 6 7 8 9 10 11 12 13 final int NOTIFYID=0x123 ; final NotificationManager notificationManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE); Notification.Builder notification=new Notification .Builder(this ); notification.setAutoCancel(true ); notification.setSmallIcon(R.drawable.packet); notification.setContentTitle("标题" ); notification.setContentText("内容" ); notification.setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_VIBRATE); notification.setWhen(System.currentTimeMillis()); Intent intent=new Intent (MainActivity.this ,DetailActivity.class); PendingIntent pi=PendingIntent.getActivity(MainActivity.this ,0 ,intent,0 ); notification.setContentIntent(pi); notificationManager.notify(NOTIFYID,notification.build());
当发生电池电量低、系统启动完成、系统时间/日期改变、系统连接电源、系统被关闭等事件时发送系统广播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Intent intent=new Intent (); intent.setAction("xxx" ); sendBroadcast(intent); public class MyReceiver extends BroadcastReceiver { private static final String action1="xxx" ; public MyReceiver () {} @Override public void onReceive (Context context,Intent intent) { if (intent.getAction().equals(action1)) Toast.makeText(context,"xxx" ,Toast.LENGTH_SHORT).show(); } }
多媒体 Android支持的音频格式为.mp3、.3gp、.ogg、.wav等,视频格式为.3gp、.mp4等。
使用MediaPlayer播放音频:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 MediaPlayer player=MediaPlayer.create(this ,Uri.parse("http://www.xxx.com/bg.mp3" )); MediaPlayer player1=new MediaPlayer (); try { player1.setDataSource("/sdcard/music.mp3" ); player1.prepare(); } catch (IOException e){ e.printStackTrace(); } player.start(); player.stop(); player.pause();
使用SoundPool播放音频:
1 2 3 4 5 6 7 8 9 SoundPool(int maxStreams,int streamType,int srcQuality); public int load (Context context,int resId,int priority) ;public int load (Stirng path,int priority) ;public int load (AssetFileDescriptor afd,int priority) ;public int load (FileDescriptor fd,long offset,long length,int priority) ;play(int soundID,float leftVolume,float rightVolume,int priority,int loop,float rate);
使用VideoView播放视频:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); VideoView video=(VideoView)findViewById(R.id.video); File file=new File (Environment.getExternalStorageDirectory()+"/video.mp4" ); if (file.exists()){ video.setVideoPath(file.getAbsolutePath()); video.setMediaController(mc); video.requestFocus(); try { video.start(); } catch (Exception e){ e.printStackTrace(); } video.setOnCompletionListener(new MediaPlayer .OnCompletionListener(){ @Override public void onCompletion (MediaPlayer mp) { } }); } else { }
数据存储 SharedPreferences方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 getSharedPreferences(String name,int mode); getPreferences(int mode); SharedPreferences.Editor editor=getSharedPreferences("xxx" ,MODE_PRIVATE).edit(); editor.putString("username" ,username); editor.putBoolean("status" ,false ); editor.putInt("age" ,20 ); editor.commit(); SharedPreferences sp=getSharedPreferences("xxx" ,MODE_PRIVATE); String username=sp.getString("username" ,"xxx" ); Boolean status=sp.getBoolean("status" ,false ); int age=sp.getInt("age" ,18 );
内部存储如下,卸载应用程序时保存的数据文件一起被删除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 try { FileOutputStream fos=openFileOutput("xxx.txt" ,MODE_PRIVATE); fos.write("xxx" .getBytes()); fos.flush(); fos.close(); } catch (FileNotFoundException e){ e.printStackTrace(); } FileInputStream fis=openFileInput("xxx.txt" ); byte [] buffer=new byte [fis.available()];fis.read(buffer);
外部存储:
1 2 3 4 private File file;file=new File (Environment.getExternalStorageDirectory(),"xxx.txt" ); fos=new FileOutputStream (file); fis=new FileInputStream (file);
Content Provider用于不同应用之间实现数据共享。它使用基于数据库模型的简单表格来提供其中数据,每条记录包含一个数值型“_ID”字段,用于唯一标识该记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static final Uri CONTENT_URI=Uri.parse("content://com.xxx.xxx" );private String columns=ContactsContract.Contacts.DISPLAY_NAME;private CharSequence getQueryData () { StringBuilder sb=new StringBuilder (); ContentResolver resolver=getContentResolver(); Cursor cursor=resolver.query(ContactsContract.Contacts.CONTENT_URI,null ,null ,null ,null ); int displayNameIndex=cursor.getColumnIndex(columns); for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){ String displayName=cursor.getString(displayNameIndex); sb.append(displayName+"\n" ); } cursor.close(); return sb.toString(); }
Handler消息处理 创建新线程:
1 2 3 4 5 6 7 Thread thread=new Thread (new Runnable (){ @Override public void run () { } }); thread.start();
Handler时一个用来更新UI的机制,也是个消息处理的机制。
在任意线程中发送消息时,将Message用sendMessage
发送到MessageQueue中,发送时指定延迟时间、发送时间以及要携带的Bundle数据。当Looper循环到该Message时,调用相应Handler对象handlerMessage
对其处理。
在主线程中获取并处理消息时,重写Handler类中处理消息的方法,当新启动的线程发送消息时,Handler类中处理消息的方法会被自动回调。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 final int TIME=60 ;final int TIMER_MSG=0x001 ;private ProgressBar timer;private int mProgressStatus=0 ;Handler handler=new Handler (){ @Override public void handleMessage (Message msg) { if (TIME-mProgressStatus>0 ){ mProgressStatus++; timer.setProgress(TIME-mProgressStatus); handler.sendEmptyMessageDelayed(TIEMR_MSG,1000 ); } else { } } };
一个线程对应一个Looper对象,而一个Looper对象又对应一个MessageQueue,后者用于存放Message。Handler发送Message给Looper管理的MessageQueue,然后Looper从MessageQueue中取出消息,分配给Handler进行处理。要在程序中使用Handler,必须在当前线程中有个Looper对象,线程中Looper对象有两种创建方式:主UI线程中,系统已经初始化了一个Looper对象,程序中可直接创建Handler;子线程中必须手动创建并启动一个Looper对象。
Message被存放在MessageQueue中,一个MessageQueue可包含多个Message对象。一个Message对象有5个属性:
属性
类型
描述
arg1
int
存放整型数据
arg2
int
存放整型数据
obj
Object
存放发送给接收器的Object类型任意对象
replyTo
Messenger
指定此Message发送到何处
what
int
指定用户自定义的消息代码
例如循环播放广告的消息部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 final int FLAG_MSG=0X001 ;private Message message;Handler handler=new Handler (){ @Override public void handleMessage (Message msg) { if (msg.what==FLAG_MSG) flipper.showPrevious(); message=handler.obtainMessage(FLAG_MSG); handler.sendMessageDelayed(message,3000 ); } } message=Message.obtain(); message.what=FLAG_MSG; handler.sendMessage(message);
Looper对象用来为线程开启一个消息循环,操作MessageQueue。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class LooperThread extends Thread { public Handler handler; @Override public void run () { super .run(); Looper.prepare(); handler=new Handler (){ public void handleMessage (Message msg) { } }; Message m=handler.obtainMessage(); m.what=0x7 ; handler.sendMessage(m); Looper.loop(); } } LooperThread thread=new LooperThead (); thread.start();
Service应用 Service时能够在后台长时间运行,并不提供用户界面的应用程序组件。其他应用程序组件能启动Service,即使用户切到另一个应用程序,Service还可在后台运行。组件能绑定到Service并与之交互,甚至执行进程间通信IPC。
Service按照启动方式分为Started Service和Bound Service两种。对于Started Service,当应用程序组件用startService
启动Service时,Service处于启动状态。一旦启动,Service能在后台无限期运行。对于Bound Service,当应用程序组件用bindService
绑定到Service时,后者处于绑定状态。多个组件可一次绑定到一个Service上,当它们都解绑定时,Service被销毁。
当其他组件用startService
时,Service被创建,并无限期运行,自身必须用stopSelf
或其他组件用stopService
来停止Service。当Service停止时系统将其销毁。当其他组件用bindService
时,Service被创建,接着客户端通过IBinder接口于Service通信。客户端通过unbindService
关闭连接。多个客户端能绑定到同一个Service,当它们都解绑定时,系统销毁Service,而不需要被停止。
对于创建启动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class MyService extends Service { public MyService () {} @Override public IBinder onBind (Intent intent) { throw new UnsupportedOperationException ("xxx" ); } @Override public void onDestroy () { super .onDestroy(); } @Override public void onCreate () { super .onCreate(); } public int onStartCommand (Intent intent,int flags,int startId) { new Thread (new Runnable (){ @Override public void run () { long endTime=System.currentTimeMillis()+5 *1000 ; while (System.currentTimeMillis()<endTime){ synchronized (this ){ try { wait(endTime-System.currentTimeMillis()); } catch (Exception e){ e.printStackTrace(); } } } stopSelf(); } }).start(); } } Intent intent=new Intent (this ,MyService.class); startService(intent);
对于绑定启动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class BinderService extends Service { public MyService () {} public class MyBinder extends Binder { public BinderService getService () { return BinderService.this ; } } @Override public IBinder onBind (Intent intent) { return new MyBinder (); } @Override public void onDestroy () { super .onDestroy(); } } BinderService binderService; private ServiceConnection conn=new ServiceConnection (){ @Override public void onServiceConnected (ComponentName name,IBinder service) { binderService=((BinderService.MyBinder)service).getService(); } @Override public void onServiceDisconnected (ComponentName name) {} }; @Override protected void onStart () { super .onStart(); Intent intent=new Intent (this ,BinderService.class); bindService(intent,conn,BIND_AUTO_CREATE); } @Override protected void onStop () { super .onStop(); unbindService(conn); }
Service不会专门启动一个线程执行好事操作,所有操作都是在主线程中进行,以至于容易出现应用无响应ANR情况,需要手动开一个子线程。Service不会自动停止,需要stopSelf
或stopService
停止。使用IntentService时,开启Service后会自动开启一个新线程来执行,Service运行结束后会自动停止。
1 2 3 4 5 6 7 8 9 10 11 12 13 public class MyIntentService extends IntentService { public MyIntentService () { super ("MyIntentService" ); } @Override protected void onHandleIntent (Intent intent) { } @Override public void onDestroy () { } }
传感器 x轴沿屏幕向右,y轴沿屏幕向前,z轴垂直屏幕向上。
例如重力传感器和光线传感器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class MainActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE); } @Override public void onSensorChanged (SensorEvent event) { float [] values=event.values; int sensorType=event.sensor.getType(); switch (sensorType){ case Sensor.TYPE_GRAVITY: StringBuilder stringBuilder=new StringBuilder (); stringBuilder.append(values[0 ]); stringBuilder.append(values[1 ]); stringBuilder.append(values[2 ]); break ; case Sensor.TYPE_LIGHT: StringBuilder stringBuilder=new StringBuilder (); stringBuilder.append(values[0 ]); break ; } } @Override public void onAccuracyChanged (Sensor sensor,int accuracy) {} @Override protected void onResume () { super .onResume(); sensorManager.registerListener(this ,sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(this ,sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),SensorManger.SENSOR_DELAY_GAME); } @Override protected void onPause () { sensorManager.unegisterListener(this ); super .onPause(); } @Override protected void onStop () { sensorManager.unregisterListener(this ); super .onStop(); } }
磁场传感器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private SensorManager sensorManager;private float [] allValue;sensorManager=(SensorManager)context.getSystemService(Context.SENSOR_SERIVCE); sensorManager.registerListener(this ,sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_GAME); if (event.sensor.getType()==Sensor.TYPE_MAGNETIC_FIELD){ float value[]=event.values; allValue=value; super .postInvalidate(); }; if (allValue!=null ){ float x=allValue[0 ]; float y=allValue[1 ]; };
加速度传感器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private SensorManager sensorManager;private Vibrator vibrator;sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE); vibrator=(Vibrator)getSystemService(Service.VIBRATOR_SERVICE); sensorManager.registerListener(this ,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_GAME); int sensorType=event.sensor.getType();if (sensorType==Sensor.TYPE_ACCELEROMETER){ float [] values=event.values; vibrator.vibrate(500 ); sensorManager.unregisterListener(this ); };
位置服务 Android系统需要使用以下类访问定位服务:
API类
描述
LocationManager
提供系统定位服务访问功能
LocationProvider
定位组件抽象表示,可获得该定位组件相关信息
Location
特定时间地理位置信息,位置由经纬度、UTC时间戳、可选的高度、速度、方向等
LocationProvider是位置源,提供定位信息,常用的有:
方法名
描述
passive
被动定位,利用其他应用使用定位更新了定位信息,系统会保存下来,该应用收到消息后直接读取即可
gps
通过GPS芯片利用卫星获取定位信息
network
通过网络获取定位信息,通常用手机基站和WIFI节点地址大致定位
下面例子直接指定GPS为提供者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 LocationManager locationManager=(LocationManager)getSystemService(LOCATION_SERVICE); locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 1000 , 1 , new LocationListener (){ @Override public void onLocationChanged (Location location) { locationUpdates(location); } @Override public void onStatusChanged (String provider,int status,Bundle,extras) {} @Override public void onProviderEnabled (String provider) {} @Override public void onProviderDisabled (String provider) {} } ); Location location=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); locationUpdates(location); public void locationUpdates (Location location) { if (location!=null ){ StringBuilder stringBuilder=new StringBuilder (); stringBuilder.append(location.getLongitude()); stringBuilder.append(location.getLatitude()); stringBuilder.append(location.getAccuracy()); stringBuilder.append(location.getAltitude()); stringBuilder.append(location.geBearing()); stringBuilder.append(location.getSpeed()); stringBuilder.append(location.getTime()); }; }
网络编程 对于使用GET请求的HttpURLConnection:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 private Handler handler;public String base64 (String content) { try { content=Base64.encodeToString(content.getBytes("utf-8" ),Base64.DEFAULT); content=URLEncoder.encode(content,"utf-8" ); } catch (UnsupportedEncodingException e){ e.printStackTrace(); } return content; } public void send () { String target="" ; target="http://xxx.xxx.xxx.xxx:8080/get.jsp?content=" +base64(content.getText().toString().trim()); URL url; try { url=new URL (target); HttpURLConnection urlConn=(HttpURLConnection)url.openConnection(); InputStreamReader in=new InputStreamReader (urlConn.getInputStream()); BufferedReader buffer=new BufferedReader (in); String inputLine=null ; while ((inputLine=buffer.readLine())!=null ) result+=inputLine+"\n" ; in.close(); urlConn.disconnect(); } catch (MalformedURLException e){ e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } } button.setOnClickListener(new View .OnClickListener(){ @Override public void onClick (View v) { if ("" .equals(content.getText().toString())){ return ; } handler=new Handler (){ @Override public void handleMessage (Message msg) { super .handleMessage(msg); } }; new Thread (new Runnable (){ public void run () { send(); Message m=handler.obtainMessage(); handler.sendMessage(m); } }).start(); } })
对于POST请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public void send () { String target="http://xxx.xxx.xxx.xxx:8080/post.jsp" ; URL url; try { url=new URL (target); HttpURLConnection urlConn=(HttpURLConnection)url.openConnection(); urlConn.setRequestMethod("POST" ); urlConn.setDoInput(true ); urlConn.setDoOutput(true ); urlConn.setUseCaches(false ); urlConn.setInstanceFollowRedirects(true ); urlConn.setRequestProperty("Content-Type" ,"application/x-www-form-urlencoded" ); DataOutputStream out=new DataOutputStream (urlConn.getOutputStream()); String param="usernam=" +URLEncoder.encode(edit_Username.getText().toString(),"utf-8" )+"&password=" +URLEncoder.encode(edit_Password.getText().toString(),"utf-8" ); out.writeBytes(param); out.flush(); out.close(); if (urlConn.getResponseCode()==HttpURLConnecion.HTTP_OK){ InputStreamReader in=new InputStreamReader (urlConn.getInputStream()); BufferedReader buffer=new BufferedReader (in); String inputLine=null ; while ((inputLine=buffer.readLine())!=null ) result+=inputLine+"\n" ; in.close(); } urlConn.disconnect(); } catch (MalformedURLException e){ e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } }
对于JSON格式的处理,演示handleMessage的重写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 TextView[][] tv={{step,time,heat,km},{step1,time1,heat1,km1}}; try { JSONArray jsonArray=new JSONArray (result); for (int i=0 ;i<jsonArray.length();i++){ JSONObject jsonObject=jsonArray.getJSONObject(i); tv[i][0 ].setText(jsonObject.gtString("step" )); tv[i][1 ].setText(jsonObject.getString("time" )); tv[i][2 ].setText(jsonObejct.getString("heat" )); tv[i][3 ].setText(jsonObject.getString("km" )); } } catch (JSONException e){ e.printStackTrace(); }
Android提供内置浏览器,使用开源WebKit引擎,需要通过WebView组件实现。
1 2 3 4 5 6 7 8 9 10 11 WebView webView=(WebView)findViewById(R.id.webView1); webView.loadUrl("http://xxx.xxx.com/xxx.html" ); webView.getSettings().setUseWideViewPort(true ); webView.getSettings().setLoadWithOverviewMode(true ); webView.loadDataWithBaseURL(null ,"<br>" ,"text/html" ,"utf-8" ,null ); webView.getSettings().setJavaScriptEnabled(true ); webView.setWebChromeClient(new WebChromeClient ())