Upload
flower-lantern
View
88
Download
0
Embed Size (px)
DESCRIPTION
gg
Citation preview
PHÁT TRIỂN ỨNG DỤNG CHO CÁC DỊCH VỤ DI ĐỘNG
Các vấn đề khác19/04/23
Animation và graphic
19/04/23
Animation
Có 2 hệ thống animation chính trong android Property animation
Cho phép thay đổi thuộc tính của các đối tượng (cả đối tượng không xuất hiện trên màn hình)
Khá mềm dẻo và mạnh View animation
Chỉ cho phép thực hiện animation trên đối tượng view Đủ mạnh cho hầu hết các hệ thống
Ngoài ra còn có Drawable animation Là cách thực hiện animation sử dụng chuỗi các
drawable (giống chiều phim)
19/04/23
Graphic
Có nhiều lựa chọn để vẽ các đối tượng graphic Canvas và drawable
Cung cấp một số view dùng để vẽ và hiển thị các đối tượng drawable
Hardware acceleration Có thể tăng tốc sử dụng phần cứng khi xử lý các hình
vẽ trong hầu hết các trường hợp OpenGL
Có thể sử dụng OpenGL cả trong Android framework API và Native Development Kit (NDK)
19/04/23
Property animation
Cho phép định nghĩa nhưng thông số của animation sau Độ dài Mức độ thay đổi tính chất theo thời gian
Hàm thay đổi của tính chất phụ thuộc vào thời gian Số lần lập lại và hành vi của animation
Có lập lại hay không Hành vi đặc biệt (chạy ngược)
Animation theo bộ Lập các bộ animation để quản lý (chạy theo thứ tự hay
đồng thời) Tốc độ refresh của màn hình
19/04/23
Animation
19/04/23
Non-linear animation
Linear animation
Các animator
Các các lớp dùng để thực hiện các animation ValueAnimator
Chỉ thực hiện tính toán thay đổi của giá trị Để thực hiện animation cần nghe sự kiện và tự thay
đổi thuộc tính của các đối tượng ObjectAnimator
Lớp con của ValueAnimator Thực hiện thêm bước thay đổi tính chất của đối tượng
AnimatorSet Gom các animation vào nhóm Cho phép sắp xếp thứ tự các animation trong nhóm
19/04/23
View animation
Dùng để thay đổi một số thuộc tính các đối tượng view Vị trí Kích thước Chiều xoay Mức độ trong (transparency)
19/04/23
19/04/23
<set android:shareInterpolator="false"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromXScale="1.0" android:toXScale="1.4" android:fromYScale="1.0" android:toYScale="0.6" android:pivotX="50%" android:pivotY="50%" android:fillAfter="false" android:duration="700" /> <set android:interpolator="@android:anim/decelerate_interpolator"> <scale android:fromXScale="1.4" android:toXScale="0.0" android:fromYScale="0.6" android:toYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:startOffset="700" android:duration="400" android:fillBefore="false" /> <rotate android:fromDegrees="0" android:toDegrees="-45" android:toYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:startOffset="700" android:duration="400" /> </set></set>
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);spaceshipImage.startAnimation(hyperspaceJumpAnimation);
Dãn hình
Co và xoay đông thời
Load và áp dụng vào một ImageView
Drawable animation
Cho phép load một chuỗi các tài nguyên drawable Định nghĩa animation như là một tài nguyên
drawable (res/drawable/) Load và sử dụng như tài nguyên drawable bình
thường Tuy nhiên có thể khởi động animation
19/04/23
Drawable animation
19/04/23
Activity.javaAnimationDrawable rocketAnimation;
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image); rocketImage.setBackgroundResource(R.drawable.rocket_thrust); rocketAnimation = (AnimationDrawable) rocketImage.getBackground();}
public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { rocketAnimation.start(); return true; } return super.onTouchEvent(event);}
rocket_thrust.xml<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true"> <item android:drawable="@drawable/rocket_thrust1" android:duration="200" /> <item android:drawable="@drawable/rocket_thrust2" android:duration="200" /> <item android:drawable="@drawable/rocket_thrust3" android:duration="200" /></animation-list>
Canvas và drawable
Vẽ trực tiếp lên đối tượng View Dùng trong trường hợp chỉ muốn vẽ đối tượng
đơn giản Ứng dụng tương đối tĩnh
Vẽ lên Canvas và điểu khiển mọi khía cạch của hiển thị và animation
19/04/23
Vẽ sử dụng Canvas
Vẽ lên View Sử dụng đối tượng Canvas khi vẽ trong phương
thức callback onDraw() onDraw() chỉ được gọi khi cần thiết nên nếu
muốn render lại thì cần gọi invalidate() Vẽ lên SurfaceView
Là một lớp con của View Cho phép vẽ các đối tượng bằng một thread
riêng (tránh phải chờ thread hệ thống)
19/04/23
Vẽ một hình bằng ImageView
19/04/23
LinearLayout mLinearLayout;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
// Create a LinearLayout in which to add the ImageView mLinearLayout = new LinearLayout(this);
// Instantiate an ImageView and define its properties ImageView i = new ImageView(this); i.setImageResource(R.drawable.my_image); i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimensions i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
// Add the ImageView to the layout and set the layout as the content view mLinearLayout.addView(i); setContentView(mLinearLayout); }
Nine-patch
Nine-patch là hình chia làm 9 phần cho phép co dãn
19/04/23
<Button id="@+id/tiny" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerInParent="true" android:text="Tiny" android:textSize="8sp" android:background="@drawable/my_button_background"/>
<Button id="@+id/big" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" android:text="Biiiiiiig text!" android:textSize="30sp" android:background="@drawable/my_button_background"/>
Media và Camera
19/04/23
Media playback
Android hỗ trợ media playback sử dụng MediaPlayer
Trước khi sử dụng MediaPlayer cần cài đặt một số quyền Internet permission
<uses-permission android:name="android.permission.INTERNET" />
Wake lock permission <uses-permission android:name="android.permission.WAKE_LOCK" />
19/04/23
MediaPlayer
Dùng để bật audio và video từ các nguồn khác nhau Tài nguyên địa phương URI trong (từ các ứng dụng khác) URL ngoài (stream)
19/04/23
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);mediaPlayer.start(); // no need to call prepare(); create() does that for you
Uri myUri = ....; // initialize Uri hereMediaPlayer mediaPlayer = new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDataSource(getApplicationContext(), myUri);mediaPlayer.prepare();mediaPlayer.start();
String url = "http://........"; // your URL hereMediaPlayer mediaPlayer = new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDataSource(url);mediaPlayer.prepare(); // might take long! (for buffering, etc)mediaPlayer.start();
prepare()
Hàm prepare() có thể mất nhiều thời gian Load dữ liệu trên mạng Nên gọi prepare từ một thread không phải là UI
thread Dùng prepareAsync() thay vì prepare()
onPrepared() của OnPreparedListener sẽ được gọi khi việc chuẩn bị được hoàn tất
19/04/23
Quản lý trạng thái của MediaPlayer
Cần hiểu trạng thái của MediaPlayer Mỗi hành động chỉ hợp lệ khi MediaPlayer ở một
trạng thái nhất định nào đó Nếu thực hiện hành động không hợp lệ,
exception sẽ xảy ra
19/04/23
19/04/23
Trả lại tài nguyên
MediaPlayer có thể sử dụng nhiều tài nguyên Cần phải trả lại tài nguyên khi không sử dụng Gọi release() khi không sử dụng Giải phóng biến trỏ đến MediaPlayer để Java có
thể xóa đối tượng
19/04/23
Sử dụng Service với MediaPlayer
Khi sử dụng MediaPlayer với Service ta nên Thực hiện các công việc nặng trên thread riêng Sử dụng prepareAsync
19/04/23
public class MyService extends Service implements MediaPlayer.OnPreparedListener { private static final String ACTION_PLAY = "com.example.action.PLAY"; MediaPlayer mMediaPlayer = null;
public int onStartCommand(Intent intent, int flags, int startId) { ... if (intent.getAction().equals(ACTION_PLAY)) { mMediaPlayer = ... // initialize it here mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.prepareAsync(); // prepare async to not block main thread } }
/** Called when MediaPlayer is ready */ public void onPrepared(MediaPlayer player) { player.start(); }}
Chạy service nổi
Sử dụng service nổi để bật media
19/04/23
String songName;// assign the song name to songNamePendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(), MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);Notification notification = new Notification();notification.tickerText = text;notification.icon = R.drawable.play0;notification.flags |= Notification.FLAG_ONGOING_EVENT;notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample", "Playing: " + songName, pi);startForeground(NOTIFICATION_ID, notification);
Kiểu media hỗ trợ
Hỗ trợ hầu hết các định dạng Audio
AAC, FLAC, MP3, MIDI, WAVE … Image
JPEG, GIF, PNG, BMP… Video
H.263, MPEG-4 …
Xem thêm: http://developer.android.com/guide/appendix/media-formats.html
19/04/23
Ghi âm
Để ghi âm cần thực hiện các bước Tạo MediaRecorder Khai báo nguồn setAudioSource()
(MediaRecorder.AudioSource.MIC) Khai báo format setOutputFormat Khai báo tên file setOutputFile() Khai báo hệ mã hóa setAudioEncoder() Gọi prepare() Ghi âm start() Ngừng stop() Giải phóng MediaRecorder release()
19/04/23
19/04/23
public class AudioRecordTest extends Activity{ private static final String LOG_TAG = "AudioRecordTest"; private static String mFileName = null;
private RecordButton mRecordButton = null; private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null; private MediaPlayer mPlayer = null;
private void onRecord(boolean start) { if (start) {startRecording();} else {stopRecording();} }
private void onPlay(boolean start) { if (start) {startPlaying();} else {stopPlaying();} }
private void startPlaying() { mPlayer = new MediaPlayer(); try { mPlayer.setDataSource(mFileName); mPlayer.prepare(); mPlayer.start(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } }
private void stopPlaying() { mPlayer.release(); mPlayer = null; }
private void startRecording() { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setOutputFile(mFileName); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try { mRecorder.prepare(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); }
mRecorder.start(); } private void stopRecording() { mRecorder.stop(); mRecorder.release(); mRecorder = null; }
19/04/23
class RecordButton extends Button { boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() { public void onClick(View v) { onRecord(mStartRecording); if (mStartRecording) { setText("Stop recording"); } else { setText("Start recording"); } mStartRecording = !mStartRecording; } };
public RecordButton(Context ctx) { super(ctx); setText("Start recording"); setOnClickListener(clicker); } }
class PlayButton extends Button { boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() { public void onClick(View v) { onPlay(mStartPlaying); if (mStartPlaying) { setText("Stop playing"); } else { setText("Start playing"); } mStartPlaying = !mStartPlaying; } };
public PlayButton(Context ctx) { super(ctx); setText("Start playing"); setOnClickListener(clicker); } }
19/04/23
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this); mRecordButton = new RecordButton(this); ll.addView(mRecordButton, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0)); mPlayButton = new PlayButton(this); ll.addView(mPlayButton, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0)); setContentView(ll); }
@Override public void onPause() { super.onPause(); if (mRecorder != null) { mRecorder.release(); mRecorder = null; }
if (mPlayer != null) { mPlayer.release(); mPlayer = null; } }}
public AudioRecordTest() { mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileName += "/audiorecordtest.3gp"; }
Camera
Định hướng ứng dụng Ứng dụng có nhất thiết phải cần camera không
Nếu có thì cần yêu cầu trong manifest Cách dùng camera
Sử dụng có thể sử dụng ảnh chụp từ ứng dụng khác Cung cấp một cách dùng camera mới
Lưu trữ Lưu trữ trong ứng dụng Lưu trữ trong Gallery cho ứng dụng khác sử dụng
19/04/23
Permission
Yêu cầu sử dụng Camera <uses-permission android:name="android.permission.CAMERA" /> Chú ý:Khi sử dụng ứng dụng chụp ảnh ngoài thì không cần permission này
Yêu cầu chỉ cài trên thiết bị có Camera <uses-feature android:name="android.hardware.camera" />
Yêu cầu sử dụng lưu trữ ngoài <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Yêu cầu được ghi âm <uses-permission android:name="android.permission.RECORD_AUDIO" />
Yêu cầu sử dụng thông tin định vị <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
19/04/23
Chụp ảnh sử dụng ứng dụng có sẵn
19/04/23
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;private Uri fileUri;
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
// create Intent to take a picture and return control to the calling application Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
// start the image capture Intent startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);}
Quay phim sử dụng ứng dụng có sẵn
19/04/23
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;private Uri fileUri;
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
//create new Intent Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO); // create a file to save the video intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high
// start the Video Capture Intent startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);}
Nhận ảnh và phim kết quả
19/04/23
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // Image captured and saved to fileUri specified in the Intent Toast.makeText(this, "Image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { // User cancelled the image capture } else { // Image capture failed, advise user } }
if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // Video captured and saved to fileUri specified in the Intent Toast.makeText(this, "Video saved to:\n" + data.getData(), Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { // User cancelled the video capture } else { // Video capture failed, advise user } }}
Viêt ứng dụng sử dụng Camera
Cần thực hiện các bước Phát hiện và truy cập Camera Tạo lớp xem trước Xây dựng layout để xem trước Cài đặt listener để thu ảnh Thu và lưu ảnh Giải phóng Camera
Xem thêm: http://developer.android.com/guide/topics/media/camera.html
#custom-camera
19/04/23
Xác định vị trí và cảm biến
19/04/23
Cảm biến trong thiết bị Android
Hầu hết các thiết bị Android đều có các cảm biến sau Cảm biến vị trí (GPS, A-GPS) Cảm biến gia tốc (accelerometer) Cảm biến con quay hồi chuyển (gyroscope) Cảm biến khoảng cách vật thể với màn hình
Có thể có Cảm biến ánh sáng Cảm biến áp suất (barometer) Cảm biến nhiệt độ (có thể) …
19/04/23
Vấn đề
Thông tin cảm biến môi trường là nhiều Sử dụng thông tin như thế nào?
Nhận dạng trạng thái của điện thoại Nhận dạng tình huống sử dụng Nhận dạng hành động của người dùng
Từ đó Cung cấp dịch vụ tiện lợi Cung cấp các tương tác trực quan Cung cấp các tương tác thông minh
19/04/23
Xác định vị trí
Android cung cấp dịch vụ xác định vị trí thông qua Google Location Service API Sử dụng LocationManager Lấy sử dụng
getSystemService(Context.LOCATION_SERVICE)
Có thể: Truy cập các vị trí người dùng đã từng qua Đăng ký hoặc bỏ cập nhật về vị trí Đăng ký hoặc bỏ việc kích hoạt một Intent nào đó khi
đến gần một vị trí xác định trước
19/04/23
Xác định vị trí đúng
Vấn đề của xác định vị trí chính xác Nhiều nguồn
GPS, Cell-ID và WIFI Sử dụng như thế nào còn phụ thuộc vào mức độ
chinh xác, tốc độ và tiết kiệm pin mong muốn Người dùng di chuyển
Phải cập nhật vị trí thường xuyên Mức độ chính xác thay đổi
Cùng một thiết bị có thể cho vị trí với độ chính xác khác nhau tại các thời điểm khác nhau
19/04/23
Yêu cầu cập nhật vị trí
19/04/23
// Acquire a reference to the system Location ManagerLocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updatesLocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { // Called when a new location is found by the network location provider. makeUseOfNewLocation(location); }
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {} };
// Register the listener with the Location Manager to receive location updateslocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
Cell và wifi
Điều khiển tần xuất cập nhật.•Thời gian giữa 2 cập nhật•Mức độ thay đổi tối thiểu giữa cập nhật
Permission
Để yêu cầu cập nhật vị trí sử dụng NETWORK_PROVIDER
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
GPS_PROVIDER <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
19/04/23
Mô hình nên sử dụng
Các bước nên dùng để xác định vị trí người dùng Khởi động ứng dụng Sau đó một thời gian, bắt đầu lắng nghe cập nhật vị
trí Giữ một giá trị vị trí tốt nhất, loại bỏ các vị trí mới
không chính xác Ngừng nghe cập nhật Sử dụng vị trí chính xác nhất đã ghi lại
19/04/23
Bắt đầu và dừng nghe cập nhật
Có thể bắt đầu nghe cập nhật ngay nhưng Nên đợi đến khi cần thiết
Nếu nghe quá lâu thì tốn pin Nêu nghe quá ngắn thì kết quả không chính xác
Nên trước khi sử dụng thông tin một khoảng thời gian và dừng ngay khi có đủ thông tin
19/04/23
//Start listeningString locationProvider = LocationManager.NETWORK_PROVIDER;// Or, use GPS location data:// String locationProvider = LocationManager.GPS_PROVIDER;
locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
//Stop listening// Remove the listener you previously addedlocationManager.removeUpdates(locationListener);
Xác định vị trí cuối cùng
Để đợi cập nhật vị trí đầu tiên có thể hơi lâu Nên sử dụng vị trí cuối cùng để cung cấp
thông tin cho người dùng
19/04/23
String locationProvider = LocationManager.NETWORK_PROVIDER;// Or use LocationManager.GPS_PROVIDER
Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
Duy trì vị trí chính xác nhất
Vị trí mới nhất chưa chắc đã là tốt nhất Do độ chính xác thay đổi
Để xác định độ chính xác cần làm Kiểm tra xem vị trí mới có mới hơn nhiều so với
cũ không Kiểm tra độ chính xác thiết bị vừa đưa ra vị trị
mới có tốt hơn thiêt bị đưa ra vị trí cũ không Kiểm tra loại thiết bị đo đạc và xác định độ tin cậy
19/04/23
19/04/23
private static final int TWO_MINUTES = 1000 * 60 * 2;
/** Determines whether one Location reading is better than the current Location fix * @param location The new Location that you want to evaluate * @param currentBestLocation The current Location fix, to which you want to compare the new one */protected boolean isBetterLocation(Location location, Location currentBestLocation) { if (currentBestLocation == null) { // A new location is always better than no location return true; }
// Check whether the new location fix is newer or older long timeDelta = location.getTime() - currentBestLocation.getTime(); boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location // because the user has likely moved if (isSignificantlyNewer) { return true; // If the new location is more than two minutes older, it must be worse } else if (isSignificantlyOlder) { return false; }
19/04/23
// Check whether the new location fix is more or less accurate int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); boolean isLessAccurate = accuracyDelta > 0; boolean isMoreAccurate = accuracyDelta < 0; boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy if (isMoreAccurate) { return true; } else if (isNewer && !isLessAccurate) { return true; } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { return true; } return false;}
/** Checks whether two providers are the same */private boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2);}
Tiết kiêm pin
Để tiết kiệm pin cần chỉnh những thông số sau Giảm độ dài của đoạn lắng nghe cập nhật Giảm tần suất cập nhật Giảm số thiết bị cung cấp vị trí
19/04/23
Test ứng dụng
Có thể test ứng dụng chạy trên emulator bằng cách sử dụng Window > Show View > Other > Emulator
Contron
19/04/23
Bản đồ
Android cung cấp dịch vụ bản đồ thông qua Google Maps Android API Sử dụng MapView
Hiển thị bản đồ Lắng nghe sự kiện tương tác khi có focus Có thể vẽ nhiều lớp lên bản đồ
Xem thêm: https://developers.google.com/maps/documentation/android/start#getting_the_google_maps_android_api_v2
19/04/23
Sử dụng cảm biến
Có ba loại cảm biến chính Cảm biến chuyển động
Gia tốc, lực hút, con quay hồi chuyển, Cảm biến môi trường
Nhiệt độ, áp suất, ánh sáng, độ ẩm Cảm biến vị trí
Hướng quay, từ tính
Truy cập vào các cảm biến sử dụng Android Sensor Framework
19/04/23
Android Sensor Framework
Dùng để Xác định cảm biến nào có trên thiết bị Xác định khả năng của từng cảm biến
Phạm vi đo đạc Mức độ chính xác (resolution) Nhà sản xuất, mức độ sử dụng năng lượng
Thu thập dữ liệu thô và xác định tần suất thu nhận
Đăng ký và bỏ lắng nghe sự kiện thay đổi giá trị đo mới
19/04/23
Các loại cảm biến
19/04/23
Cảm biến Loại Mô tả Sử dụng
TYPE_ACCELEROMETER Phần cứngĐo gia tốc theo 3 chiều, cả lực hút trái đất (m/s2)
Xác định chuyển động
TYPE_AMBIENT_TEMPERATURE Phần cứng Đo nhiệt độ môi trường (độ C) Theo dõi nhiệt độ
TYPE_GRAVITYPhần cứng, phần mềm
Đo lực hút của trái đất theo 3 chiều (m/s2)
Xác định chuyền động
TYPE_GYROSCOPE Phần cứng Xác định tốc độ xoay theo 3 chiều (rad/s) Xác định độ xoay
TYPE_LIGHT Phần cứng Xác định độ sáng của môi trường (lx)Điều khiển độ sáng màn hình
TYPE_LINEAR_ACCELERATIONPhần cứng,phần mềm
Xác định gia tốc theo 3 chiều không bao gồm lực hút trái đất (m/s2)
Xác định gia tốc theo một hướng nhất định
TYPE_MAGNETIC_FIELD Phần cứngXác định từ tính của môi trường theo 3 chiều (μT)
Xác định hướng compass
Các loại cảm biến (tt)
19/04/23
Cảm biến Loại Mô tả Sử dụng
TYPE_ORIENTATION Phần mềmXác định hương xoay của thiết bị theo 3 chiều
Xác định vị trí của thiết bị
TYPE_PRESSURE Phần cứngXác định áp suất không khí (hPa hoặc mbar)
Theo dõi thay đổi áp suất, xác định độ cao so với mặt nước biển
TYPE_PROXIMITY Phần cứngXác định khoảng cách của vật thê so với mặt của màn hình
Xác định xem thiết bị đang được đặt gần tai người dùng
TYPE_RELATIVE_HUMIDITY Phần cứng Xác định độ ẩm không khí (%)Xác đinh độ ngưng tụ, độ ẩm
TYPE_ROTATION_VECTORPhần cứng,phần mềm
Xác định hướng xoay của thiết bị theo 3 thành phần của vector hướng
Xác định hướng xoay của thiết bị
TYPE_TEMPERATURE Phần cứng Xác định nhiệt độ của thiết bị (độ C) Theo dõ nhiệt độ thiết bị
Sensor framework
SensorManager Truy cập danh sách cảm biến Đăng ký và bỏ lắng nghe sự kiện cập nhật Hằng số của cảm biến Cài tần suất cảm biến Hiệu chuẩn cảm biến
Sensor Xác định khả năng của cảm biến
SensorEvent Sự kiện thông báo thông số đo của cảm biến
SensorEventListener Xử lý thông báo cập nhật độ đo của cảm biến
19/04/23
Xác định cảm biến và khả năng
Nên xác định các cảm biến có trên thiết bị Sử dụng các cảm biến khác nhau để thực hiện công việc
Sử dụng cảm biến lực hút hoặc gia tốc để điều khiển game đua xe
19/04/23
//Lấy SensorManagerprivate SensorManager mSensorManager;...mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//Lấy danh sách cảm biếnList<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
//Kiểm tra loại cảm biến cụ thểprivate SensorManager mSensorManager;...mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){ // Success! There's a magnetometer. }else { // Failure! No magnetometer. }
Lắng nghe sự kiện cảm biến
Sử dụng SensorEventListener Cài onAccuracyChanged()
Cung cấp đối tượng Sensor Cung cấp độ chính xác của cảm biến
SENSOR_STATUS_ACCURACY_LOW SENSOR_STATUS_ACCURACY_MEDIUM SENSOR_STATUS_ACCURACY_HIGH SENSOR_STATUS_UNRELIABLE.
Cài onSensorChanged() Thông báo giá trị mới thông qua đối tượng
SensorEvent
19/04/23
19/04/23
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager mSensorManager; private Sensor mLight;
@Override public final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); }
@Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. }
@Override public final void onSensorChanged(SensorEvent event) { // The light sensor returns a single value. // Many sensors return 3 values, one for each axis. float lux = event.values[0]; // Do something with this sensor value. }
@Override protected void onResume() { super.onResume(); mSensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL); }
@Override protected void onPause() { super.onPause(); mSensorManager.unregisterListener(this); }}
Hệ tọa độ của cảm biến
Một số cảm biển chỉ đo một giá trị
Nhưng số khác đo giá trị trong một hệ tọa độ 3 chiều Hệ tọa độ này không đổi khi sử
dụng thiết bị Hệ tọa độ được xác định dựa
vào vị trí tự nhiên của thiết bị Điện thoại dùng dọc Tablet dùng ngang
19/04/23
Lưu ý khi sử dụng cảm biến
Bỏ đăng khi khi không cần sử dụng Không test code trên emulator
Có thể dùng giả lập Không nên xử lý nhiều trong onSensorChanged() Tránh sử dụng hàm và loại cảm biến đã bị loại
(deprecated) Luôn kiểm tra sự tồn tại của cảm biến trước khi
sử dụng Xác định tần suất đo đạc hợp lý, tránh lãng phí
năng lượng
19/04/23
Chi tiết các cảm biến
Cảm biến chuyển động: http://developer.android.com/guide/topics/sensors/sensors_motion.html
Cảm biến vị trí: http://developer.android.com/guide/topics/sensors/sensors_position.html
Cảm biến môi trường: http://developer.android.com/guide/topics/sensors/sensors_environment.html
19/04/23
Kết nối
19/04/23
Kết nối trong Android
Thiết bị di động có rất nhiều loại kết nối để tương tác với các thiết bị khác Bluetooth NFC Wifi P2P USB
Xem thêm: http://developer.android.com/guide/topics/connectivity/index.html
19/04/23
Lưu trữ
19/04/23
Các lựa chọn lưu trữ
Có nhiều lựa chọn Nội bộ Trên thiết bị Trên thẻ nhớ Trên cơ sở dữ liệu (SQLite) Trên mạng
Xem thêm: http://developer.android.com/guide/topics/data/index.html
19/04/23
Các lưu ý khác
19/04/23
Các lưu ý khác
Hỗ trợ nhiều kích thước màn hình Kích thước Mật độ Hướng xoay Xem thêm:
http://developer.android.com/guide/practices/screens_support.html
Hỗ trợ cả điện thoại và tablet Sử dụng Fragment Sử dụng Action bar Sử dụng layout mềm dẻo Xem thêm:
http://developer.android.com/guide/practices/tablets-and-handsets.html
19/04/23