從2013年開始ldpi mdpi hdpi相繼退出了歷史舞台!以1280*720的720P主要機型占據了主流,即xhdpi。
2015年預計將會是1080P的天下了,因為從14年下半年到2015年推出的android手機均為1080P,可以預見未來的趨勢!
以下是當前android主要機型規範:
手機常見解析度:
原文網址:https://read01.com/NkD6Q0.html
PackageManager.hasSystemFeature()
method, as shown in the example code below:/** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ // this device has a camera return true; } else { // no camera on this device return false; } }
Camera.getNumberOfCameras()
method.Camera
(unless you are using an intent to access the camera).Camera.open()
method and be sure to catch any exceptions, as shown in the code below:/** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable }
Camera.open()
. Failing to check for exceptions if the camera is in use or does not exist will cause your application to be shut down by the system.Camera.open(int)
. The example code above will access the first, back-facing camera on a device with more than one camera.Camera.getParameters()
method and checking the returned Camera.Parameters
object for supported capabilities. When using API Level 9 or higher, use the Camera.getCameraInfo()
to determine if a camera is on the front or back of the device, and the orientation of the image.SurfaceView
that can display the live image data coming from a camera, so users can frame and capture a picture or video.View
layout. This class implements SurfaceHolder.Callback
in order to capture the callback events for creating and destroying the view, which are needed for assigning the camera preview input.private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
surfaceChanged()
method as getSupportedPreviewSizes()
. Do not set arbitrary values in the setPreviewSize()
method.FrameLayout
element is meant to be the container for the camera preview class. This <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="Capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </LinearLayout>
<activity android:name=".CameraActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <!-- configure this activity to use landscape orientation --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
setDisplayOrientation()
method to set the rotation of the preview image. In order to change preview orientation as the user re-orients the phone, within the surfaceChanged()
method of your preview class, first stop the preview with Camera.stopPreview()
change the orientation and then start the preview again with Camera.startPreview()
.FrameLayout
element shown in the public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } }
getCameraInstance()
method in the example above refers to the example method shown in Accessing cameras.Camera.PictureCallback
interface to receive the image data and write it to a file. The Camera.PictureCallback
interface to save an private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions: " + e.getMessage()); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } } };
build.gradle
file of the OpenCV (3.0) module:apply plugin: 'com.android.library'
android {
compileSdkVersion 17
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 8
targetSdkVersion 21
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
compileSdkVersion 17
to minimum 21 (recommended 24). Because android.hardware.camera2
was added in API 21.public class CircleDemoActivity extends AppCompatActivity implements OnSeekBarChangeListener, OnMarkerDragListener, OnMapLongClickListener, OnMapReadyCallback {}
先看 onCreate()
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.circle_demo); mColorBar = (SeekBar) findViewById(R.id.hueSeekBar); mColorBar.setMax(HUE_MAX); mColorBar.setProgress(0); mAlphaBar = (SeekBar) findViewById(R.id.alphaSeekBar); mAlphaBar.setMax(ALPHA_MAX); mAlphaBar.setProgress(127); mWidthBar = (SeekBar) findViewById(R.id.widthSeekBar); mWidthBar.setMax(WIDTH_MAX); mWidthBar.setProgress(10); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); mClickabilityCheckbox = (CheckBox) findViewById(R.id.toggleClickability); }有三個 colorBar... 和一個CheckBox....<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@string/properties_circle" /> <TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="1">// 只有一欄 <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical"> <TextView android:text="@string/fill_hue" /> <SeekBar android:id="@+id/hueSeekBar" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical"> <TextView android:text="@string/fill_alpha" /> <SeekBar android:id="@+id/alphaSeekBar" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical"> <TextView android:text="@string/stroke_width" /> <SeekBar android:id="@+id/widthSeekBar" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical"> <CheckBox android:id="@+id/toggleClickability" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:onClick="toggleClickability" android:text="@string/clickable"/> </TableRow> </TableLayout> <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.SupportMapFragment"/> </LinearLayout>先看 onMapReady()
@Overridepublic void onMapReady(GoogleMap map) { mMap = map; // Override the default content description on the view, for accessibility mode. map.setContentDescription(getString(R.string.map_circle_description)); mColorBar.setOnSeekBarChangeListener(this); mAlphaBar.setOnSeekBarChangeListener(this); mWidthBar.setOnSeekBarChangeListener(this); mMap.setOnMarkerDragListener(this); mMap.setOnMapLongClickListener(this); mFillColor = Color.HSVToColor( mAlphaBar.getProgress(), new float[]{mColorBar.getProgress(), 1, 1}); mStrokeColor = Color.BLACK; DraggableCircle circle = new DraggableCircle(SYDNEY, DEFAULT_RADIUS, mClickabilityCheckbox.isChecked()); mCircles.add(circle); // Move the map so that it is centered on the initial circle mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 4.0f)); // Set up the click listener for the circle. map.setOnCircleClickListener(new OnCircleClickListener() { @Override public void onCircleClick(Circle circle) { // Flip the r, g and b components of the circle's stroke color. int strokeColor = circle.getStrokeColor() ^ 0x00ffffff; circle.setStrokeColor(strokeColor); } }); }private class DraggableCircle { private final Marker centerMarker; private final Marker radiusMarker; private final Circle circle; private double radius; public DraggableCircle(LatLng center, double radius, boolean clickable) { this.radius = radius; centerMarker = mMap.addMarker(new MarkerOptions() .position(center) .draggable(true)); radiusMarker = mMap.addMarker(new MarkerOptions() .position(toRadiusLatLng(center, radius)) .draggable(true) .icon(BitmapDescriptorFactory.defaultMarker( BitmapDescriptorFactory.HUE_AZURE))); circle = mMap.addCircle(new CircleOptions() .center(center) .radius(radius) .strokeWidth(mWidthBar.getProgress()) .strokeColor(mStrokeColor) .fillColor(mFillColor) .clickable(clickable)); } public DraggableCircle(LatLng center, LatLng radiusLatLng, boolean clickable) { this.radius = toRadiusMeters(center, radiusLatLng); centerMarker = mMap.addMarker(new MarkerOptions() .position(center) .draggable(true)); radiusMarker = mMap.addMarker(new MarkerOptions() .position(radiusLatLng) .draggable(true) .icon(BitmapDescriptorFactory.defaultMarker( BitmapDescriptorFactory.HUE_AZURE))); circle = mMap.addCircle(new CircleOptions() .center(center) .radius(radius) .strokeWidth(mWidthBar.getProgress()) .strokeColor(mStrokeColor) .fillColor(mFillColor) .clickable(clickable)); } public boolean onMarkerMoved(Marker marker) { if (marker.equals(centerMarker)) { circle.setCenter(marker.getPosition()); radiusMarker.setPosition(toRadiusLatLng(marker.getPosition(), radius)); return true; } if (marker.equals(radiusMarker)) { radius = toRadiusMeters(centerMarker.getPosition(), radiusMarker.getPosition()); circle.setRadius(radius); return true; } return false; } public void onStyleChange() { circle.setStrokeWidth(mWidthBar.getProgress()); circle.setFillColor(mFillColor); circle.setStrokeColor(mStrokeColor); } public void setClickable(boolean clickable) { circle.setClickable(clickable); } }當常按時...新增一個circle.....@Overridepublic void onMapLongClick(LatLng point) { // We know the center, let's place the outline at a point 3/4 along the view. View view = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getView(); LatLng radiusLatLng = mMap.getProjection().fromScreenLocation(new Point( view.getHeight() * 3 / 4, view.getWidth() * 3 / 4)); // ok create it DraggableCircle circle = new DraggableCircle(point, radiusLatLng, mClickabilityCheckbox.isChecked()); mCircles.add(circle); // 新增一個 circles }// 當按下 checkbox -> toggleClickability
public void toggleClickability(View view) { boolean clickable = ((CheckBox) view).isChecked(); // Set each of the circles to be clickable or not, based on the // state of the checkbox. for (DraggableCircle draggableCircle : mCircles) { draggableCircle.setClickable(clickable); } }@Overridepublic void onMarkerDragStart(Marker marker) { onMarkerMoved(marker); } @Overridepublic void onMarkerDragEnd(Marker marker) { onMarkerMoved(marker); } @Overridepublic void onMarkerDrag(Marker marker) { onMarkerMoved(marker); } private void onMarkerMoved(Marker marker) { for (DraggableCircle draggableCircle : mCircles) { if (draggableCircle.onMarkerMoved(marker)) { break; } } }=======================================================================================================public class SplitStreetViewPanoramaAndMapDemoActivity extends AppCompatActivity implements OnMarkerDragListener, OnStreetViewPanoramaChangeListener {}@Overrideprotected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.split_street_view_panorama_and_map_demo); final LatLng markerPosition; if (savedInstanceState == null) { markerPosition = SYDNEY; } else { markerPosition = savedInstanceState.getParcelable(MARKER_POSITION_KEY); } SupportStreetViewPanoramaFragment streetViewPanoramaFragment = (SupportStreetViewPanoramaFragment) getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama); streetViewPanoramaFragment.getStreetViewPanoramaAsync( new OnStreetViewPanoramaReadyCallback() { @Override public void onStreetViewPanoramaReady(StreetViewPanorama panorama) { mStreetViewPanorama = panorama; mStreetViewPanorama.setOnStreetViewPanoramaChangeListener( SplitStreetViewPanoramaAndMapDemoActivity.this); // Only need to set the position once as the streetview fragment will maintain // its state. if (savedInstanceState == null) { mStreetViewPanorama.setPosition(SYDNEY); } } }); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap map) { map.setOnMarkerDragListener(SplitStreetViewPanoramaAndMapDemoActivity.this); // Creates a draggable marker. Long press to drag. mMarker = map.addMarker(new MarkerOptions() .position(markerPosition) .icon(BitmapDescriptorFactory.fromResource(R.drawable.pegman)) .draggable(true)); } }); }