ฉันพยายามเปิดภาพ / ภาพในแอปในตัวคลังภาพจากภายในแอปพลิเคชันของฉัน
ฉันมี URI ของรูปภาพ (รูปภาพตั้งอยู่บนการ์ด SD)
คุณมีข้อเสนอแนะใด?
ฉันพยายามเปิดภาพ / ภาพในแอปในตัวคลังภาพจากภายในแอปพลิเคชันของฉัน
ฉันมี URI ของรูปภาพ (รูปภาพตั้งอยู่บนการ์ด SD)
คุณมีข้อเสนอแนะใด?
คำตอบ:
นี่เป็นโซลูชั่นที่สมบูรณ์ ฉันเพิ่งอัปเดตโค้ดตัวอย่างนี้พร้อมข้อมูลที่ให้ไว้ในคำตอบด้านล่างโดย @mad ตรวจสอบวิธีแก้ไขด้านล่างจาก @Khobaib เพื่ออธิบายวิธีจัดการกับภาพ picasa
ฉันเพิ่งตรวจสอบคำตอบดั้งเดิมของฉันและสร้างโครงการ Android Studio แบบง่ายคุณสามารถชำระเงินจาก GitHub และนำเข้าโดยตรงในระบบของคุณ
https://github.com/hanscappelle/SO-2169649
(โปรดทราบว่าการเลือกหลายไฟล์ยังคงต้องใช้งานอยู่)
ด้วยการสนับสนุนภาพจากไฟล์ explorers ขอบคุณผู้ใช้บ้า
public class BrowsePictureActivity extends Activity {
// this is the action code we use in our intent,
// this way we know we're looking at the response from our own action
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.Button01)
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
}
}
}
/**
* helper to retrieve the path of an image URI
*/
public String getPath(Uri uri) {
// just some safety built in
if( uri == null ) {
// TODO perform some logging or show user feedback
return null;
}
// try to retrieve the image from the media store first
// this will only work for images selected from gallery
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if( cursor != null ){
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
cursor.close();
return path;
}
// this is our fallback here
return uri.getPath();
}
}
เนื่องจากมีคนขอข้อมูลในความคิดเห็นและดีกว่าที่จะรวบรวมข้อมูล
ตั้งค่าพารามิเตอร์เพิ่มเติมEXTRA_ALLOW_MULTIPLE
ตามเจตนา:
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
และในการตรวจสอบการจัดการผลลัพธ์สำหรับพารามิเตอร์นั้น:
if (Intent.ACTION_SEND_MULTIPLE.equals(data.getAction()))
&& Intent.hasExtra(Intent.EXTRA_STREAM)) {
// retrieve a collection of selected images
ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
// iterate over these images
if( list != null ) {
for (Parcelable parcel : list) {
Uri uri = (Uri) parcel;
// TODO handle the images one by one here
}
}
}
โปรดทราบว่านี่รองรับ API ระดับ 18 ขึ้นไปเท่านั้น
นี่คือการปรับปรุงรหัสละเอียดที่ hcpl โพสต์ แต่ใช้ได้กับตัวจัดการไฟล์ OI, ตัวจัดการไฟล์ astro และแกลเลอรี่สื่อด้วย (ทดสอบแล้ว) ดังนั้นฉันเดาว่ามันจะทำงานกับตัวจัดการไฟล์ทุกตัว (มีคนอื่นอีกกว่าที่กล่าวถึงเหรอ?) ได้ทำการแก้ไขรหัสที่เขาเขียน
public class BrowsePicture extends Activity {
//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
//ADDED
private String filemanagerstring;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.Button01))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
}
//UPDATED
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
//OI FILE Manager
filemanagerstring = selectedImageUri.getPath();
//MEDIA GALLERY
selectedImagePath = getPath(selectedImageUri);
//DEBUG PURPOSE - you can delete this if you want
if(selectedImagePath!=null)
System.out.println(selectedImagePath);
else System.out.println("selectedImagePath is null");
if(filemanagerstring!=null)
System.out.println(filemanagerstring);
else System.out.println("filemanagerstring is null");
//NOW WE HAVE OUR WANTED STRING
if(selectedImagePath!=null)
System.out.println("selectedImagePath is the right one for you!");
else
System.out.println("filemanagerstring is the right one for you!");
}
}
}
//UPDATED!
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if(cursor!=null)
{
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
else return null;
}
else return null;
ในgetPath(Uri uri)
การreturn uri.getPath();
และกำจัดคนแรกที่filemanagerstring = selectedImageUri.getPath();
ตรวจสอบ วิธีนี้คุณเพียงแค่โทรออกครั้งเดียวgetPath(Uri)
แล้วรับเส้นทางกลับมา (ไม่ว่าจะเป็น Gallery หรือโปรแกรมจัดการไฟล์ที่ใช้)
วิธีการของ hcpl ทำงานได้อย่างสมบูรณ์แบบล่วงหน้า KitKat แต่ไม่ทำงานกับ DocumentsProvider API เพียงแค่ทำตามแบบฝึกหัด Android อย่างเป็นทางการสำหรับ documentproviders: https://developer.android.com/guide/topics/providers/document-provider.html -> เปิดเอกสารส่วน Bitmap
ฉันใช้รหัส hcpl และขยายมัน: หากไฟล์ที่มีพา ธ ที่ดึงไปยังรูปภาพมีข้อผิดพลาดเกิดขึ้นฉันเรียกฟังก์ชันนี้ว่า
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
ทดสอบบน Nexus 5
พื้นฐานด้วยรหัสข้างต้นฉันสะท้อนให้เห็นถึงรหัสเช่นด้านล่างอาจจะเหมาะกว่า:
public String getPath(Uri uri) {
String selectedImagePath;
//1:MEDIA GALLERY --- query from MediaStore.Images.Media.DATA
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if(cursor != null){
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
selectedImagePath = cursor.getString(column_index);
}else{
selectedImagePath = null;
}
if(selectedImagePath == null){
//2:OI FILE Manager --- call method: uri.getPath()
selectedImagePath = uri.getPath();
}
return selectedImagePath;
}
ฉันผ่านวิธีแก้ปัญหาจาก @hcpl & @mad โซลูชันของ hcpl รองรับภาพท้องถิ่นในแกลเลอรี & mad เป็นวิธีแก้ปัญหาที่ดีกว่านั้น - ช่วยในการโหลดภาพ OI / Astro / Dropbox เช่นกัน แต่ในแอพของฉันในขณะที่ทำงานกับไลบรารี่ของ Picasaที่รวมอยู่ในแกลเลอรี Android แล้วทั้งคู่ก็แก้ปัญหาไม่ได้
ฉันค้นหาและวิเคราะห์เล็กน้อยและในที่สุดก็มาพร้อมกับโซลูชันที่ดีกว่าและสง่างามที่เอาชนะข้อ จำกัด นี้ได้ ขอบคุณDimitar Darazhanskiสำหรับบล็อกของเขาที่ช่วยฉันในกรณีนี้ฉันปรับเปลี่ยนเล็กน้อยเพื่อให้เข้าใจง่ายขึ้น นี่คือทางออกของฉันไป -
public class BrowsePicture extends Activity {
//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
//ADDED
private String filemanagerstring;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.Button01))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
Log.d("URI VAL", "selectedImageUri = " + selectedImageUri.toString());
selectedImagePath = getPath(selectedImageUri);
if(selectedImagePath!=null){
// IF LOCAL IMAGE, NO MATTER IF ITS DIRECTLY FROM GALLERY (EXCEPT PICASSA ALBUM),
// OR OI/ASTRO FILE MANAGER. EVEN DROPBOX IS SUPPORTED BY THIS BECAUSE DROPBOX DOWNLOAD THE IMAGE
// IN THIS FORM - file:///storage/emulated/0/Android/data/com.dropbox.android/...
System.out.println("local image");
}
else{
System.out.println("picasa image!");
loadPicasaImageFromGallery(selectedImageUri);
}
}
}
}
// NEW METHOD FOR PICASA IMAGE LOAD
private void loadPicasaImageFromGallery(final Uri uri) {
String[] projection = { MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if(cursor != null) {
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
if (columnIndex != -1) {
new Thread(new Runnable() {
// NEW THREAD BECAUSE NETWORK REQUEST WILL BE MADE THAT WILL BE A LONG PROCESS & BLOCK UI
// IF CALLED IN UI THREAD
public void run() {
try {
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
// THIS IS THE BITMAP IMAGE WE ARE LOOKING FOR.
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
}
cursor.close();
}
public String getPath(Uri uri) {
String[] projection = { MediaColumns.DATA};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if(cursor != null) {
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
String filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
else
return uri.getPath(); // FOR OI/ASTRO/Dropbox etc
}
ตรวจสอบและแจ้งให้เราทราบหากมีปัญหาเกิดขึ้น ฉันได้ทดสอบแล้วมันใช้งานได้ดีในทุกกรณี
หวังว่านี่จะช่วยทุกคน
สมมติว่าคุณมีโฟลเดอร์รูปภาพในไดเรกทอรีการ์ด SD สำหรับรูปภาพเท่านั้น
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*");
startActivityForResult(intent, 1);
จากนั้นคุณสามารถตัดสินใจด้วยสิ่งที่คุณต้องการจะทำกับเนื้อหากลับมาในกิจกรรมของคุณ
นี่เป็นตัวอย่างในการเรียกชื่อพา ธ ของรูปภาพทดสอบด้วยรหัสของคุณเพื่อให้แน่ใจว่าคุณสามารถจัดการผลลัพธ์ที่กลับมาได้ คุณสามารถเปลี่ยนรหัสได้ตามต้องการเพื่อให้เหมาะกับความต้องการของคุณ
protected final void onActivityResult(final int requestCode, final int
resultCode, final Intent i) {
super.onActivityResult(requestCode, resultCode, i);
// this matches the request code in the above call
if (requestCode == 1) {
Uri _uri = i.getData();
// this will be null if no image was selected...
if (_uri != null) {
// now we get the path to the image file
cursor = getContentResolver().query(_uri, null,
null, null, null);
cursor.moveToFirst();
String imageFilePath = cursor.getString(0);
cursor.close();
}
}
คำแนะนำของฉันคือพยายามดึงภาพทำงานอย่างถูกต้องฉันคิดว่าปัญหาคือเนื้อหาของการเข้าถึงภาพใน sdcard ลองดูที่การแสดงภาพในการ์ด SD
หากคุณสามารถเริ่มต้นใช้งานได้โดยตัวอย่างอาจจัดหาผู้ให้บริการที่ถูกต้องคุณควรจะสามารถหาวิธีแก้ไขสำหรับรหัสของคุณได้
ให้ฉันได้รับการปรับปรุงโดยการอัปเดตคำถามนี้กับความคืบหน้าของคุณ โชคดี
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT typ=file:///sdcard/images/* }
startActivityforResult
และจัดหากิจกรรม นั่นคือสิ่งที่ฉันหมายถึงเกี่ยวกับการตัดสินใจว่าจะทำอะไรต่อไปฉันไม่ดี
startActivityForResult(intent, 1);
และยังคงได้รับข้อผิดพลาดนี้ ... รหัสนี้อยู่นอกกิจกรรม แต่ฉันมีการอ้างอิงถึงกิจกรรมและเรียกstartActivityForResult
วิธีการในการอ้างอิงนั้น - นี่อาจเป็นเหตุผลหรือไม่
1
ที่เธอผ่านเข้ามา? ลองIMAGE_PICK
Intent.ACTION_PICK
Intent.ACTION_GET_CONTENT
คุณหมายถึงIMAGE_PICK
อะไร ไม่มีค่าคงที่ดังกล่าว intent.setData(Uri.fromFile(new File("/sdcard/image/")));
ฉันยังพยายาม ฉันพยายามทั้งหมดรวมกันเป็นไปได้ของเหล่านี้และไม่มีอะไรน่าจะทำงาน ...
นี่คือการเยี่ยมชมหัวข้อนี้อีกครั้งของฉันรวบรวมข้อมูลทั้งหมดที่นี่รวมถึงคำถามอื่น ๆ มันคืนภาพจากผู้ให้บริการบางอย่างในขณะที่การจัดการเงื่อนไขหน่วยความจำไม่เพียงพอและการหมุนภาพ สนับสนุนแกลเลอรี่, Picasa และตัวจัดการไฟล์เช่นกล่องแบบหล่น การใช้งานง่าย: เนื่องจากอินพุตตัวสร้างจะได้รับตัวแก้ไขเนื้อหาและ uri ผลลัพธ์คือบิตแมปสุดท้าย
/**
* Creates resized images without exploding memory. Uses the method described in android
* documentation concerning bitmap allocation, which is to subsample the image to a smaller size,
* close to some expected size. This is required because the android standard library is unable to
* create a reduced size image from an image file using memory comparable to the final size (and
* loading a full sized multi-megapixel picture for processing may exceed application memory budget).
*/
public class UserPicture {
static int MAX_WIDTH = 600;
static int MAX_HEIGHT = 800;
Uri uri;
ContentResolver resolver;
String path;
Matrix orientation;
int storedHeight;
int storedWidth;
public UserPicture(Uri uri, ContentResolver resolver) {
this.uri = uri;
this.resolver = resolver;
}
private boolean getInformation() throws IOException {
if (getInformationFromMediaDatabase())
return true;
if (getInformationFromFileSystem())
return true;
return false;
}
/* Support for gallery apps and remote ("picasa") images */
private boolean getInformationFromMediaDatabase() {
String[] fields = { Media.DATA, ImageColumns.ORIENTATION };
Cursor cursor = resolver.query(uri, fields, null, null, null);
if (cursor == null)
return false;
cursor.moveToFirst();
path = cursor.getString(cursor.getColumnIndex(Media.DATA));
int orientation = cursor.getInt(cursor.getColumnIndex(ImageColumns.ORIENTATION));
this.orientation = new Matrix();
this.orientation.setRotate(orientation);
cursor.close();
return true;
}
/* Support for file managers and dropbox */
private boolean getInformationFromFileSystem() throws IOException {
path = uri.getPath();
if (path == null)
return false;
ExifInterface exif = new ExifInterface(path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
this.orientation = new Matrix();
switch(orientation) {
case ExifInterface.ORIENTATION_NORMAL:
/* Identity matrix */
break;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
this.orientation.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
this.orientation.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
this.orientation.setScale(1, -1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
this.orientation.setRotate(90);
this.orientation.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
this.orientation.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
this.orientation.setRotate(-90);
this.orientation.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
this.orientation.setRotate(-90);
break;
}
return true;
}
private boolean getStoredDimensions() throws IOException {
InputStream input = resolver.openInputStream(uri);
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);
/* The input stream could be reset instead of closed and reopened if it were possible
to reliably wrap the input stream on a buffered stream, but it's not possible because
decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
mark(1024) on the stream). */
input.close();
if (options.outHeight <= 0 || options.outWidth <= 0)
return false;
storedHeight = options.outHeight;
storedWidth = options.outWidth;
return true;
}
public Bitmap getBitmap() throws IOException {
if (!getInformation())
throw new FileNotFoundException();
if (!getStoredDimensions())
throw new InvalidObjectException(null);
RectF rect = new RectF(0, 0, storedWidth, storedHeight);
orientation.mapRect(rect);
int width = (int)rect.width();
int height = (int)rect.height();
int subSample = 1;
while (width > MAX_WIDTH || height > MAX_HEIGHT) {
width /= 2;
height /= 2;
subSample *= 2;
}
if (width == 0 || height == 0)
throw new InvalidObjectException(null);
Options options = new Options();
options.inSampleSize = subSample;
Bitmap subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);
Bitmap picture;
if (!orientation.isIdentity()) {
picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
orientation, false);
subSampled.recycle();
} else
picture = subSampled;
return picture;
}
}
อ้างอิง:
มีบทช่วยสอนสองอย่างที่เป็นประโยชน์เกี่ยวกับเครื่องมือเลือกรูปภาพพร้อมซอร์สโค้ดที่ดาวน์โหลดได้ที่นี่
วิธีสร้างตัวเลือกรูปภาพ Android
วิธีการเลือกและครอบตัดรูปภาพบน Android
อย่างไรก็ตามแอปจะถูกบังคับให้ปิดบางครั้งคุณสามารถแก้ไขได้โดยการเพิ่มคุณสมบัติ android: configChanges ลงในกิจกรรมหลักในไฟล์ Manifest เช่น:
<activity android:name=".MainActivity"
android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" >
ดูเหมือนว่า API ของกล้องจะสูญเสียการควบคุมในการวางแนวดังนั้นสิ่งนี้จะช่วยได้ :)
วิธีแก้ปัญหาด้านล่างใช้กับ 2.3 (Gingerbread) -4.4 (Kitkat), 5.0 (Lollipop) และ 6.0 (Marshmallow) เช่นกัน: -
ขั้นตอนที่ 1รหัสสำหรับเปิดแกลเลอรี่เพื่อเลือกรูป:
public static final int PICK_IMAGE = 1;
private void takePictureFromGalleryOrAnyOtherFolder()
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}
ขั้นตอนที่ 2รหัสสำหรับรับข้อมูลonActivityResult
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_IMAGE) {
Uri selectedImageUri = data.getData();
String imagePath = getRealPathFromURI(selectedImageUri);
//Now you have imagePath do whatever you want to do now
}//end of inner if
}//end of outer if
}
public String getRealPathFromURI(Uri contentUri) {
//Uri contentUri = Uri.parse(contentURI);
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = null;
try {
if (Build.VERSION.SDK_INT > 19) {
// Will return "image:x*"
String wholeID = DocumentsContract.getDocumentId(contentUri);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, sel, new String[] { id }, null);
} else {
cursor = context.getContentResolver().query(contentUri,
projection, null, null, null);
}
} catch (Exception e) {
e.printStackTrace();
}
String path = null;
try {
int column_index = cursor
.getColumnIndex(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
path = cursor.getString(column_index).toString();
cursor.close();
} catch (NullPointerException e) {
e.printStackTrace();
}
return path;
}
READ_EXTERNAL_STORAGE
ในการแสดงภาพและวิดีโอลองทำสิ่งนี้:
Intent intent = new Intent();
intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 1);
startActivityForResult(Intent.createChooser(intent,"Wybierz plik"), SELECT_FILE);
ในกรณีที่มันช่วย; ฉันทำเช่นนี้เพื่อรับบิตแมป:
InputStream is = context.getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
คำตอบข้างต้นถูกต้อง ฉันประสบปัญหาที่แตกต่างกันซึ่งใน HTC M8 แอปพลิเคชันของฉันขัดข้องเมื่อเลือกภาพจากแกลเลอรี่ ฉันได้รับค่า null สำหรับเส้นทางภาพ ฉันแก้ไขและปรับให้เหมาะสมด้วยวิธีแก้ไขปัญหาต่อไปนี้ ในวิธี onActivityResult
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if ((requestCode == RESULT_LOAD_IMAGE) && (resultCode == RESULT_OK)) {
if (data != null) {
Uri selectedImageUri = null;
selectedImageUri = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor imageCursor = mainActivity.getContentResolver().query(
selectedImageUri, filePathColumn, null, null, null);
if (imageCursor == null) {
return;
}
imageCursor.moveToFirst();
int columnIndex = imageCursor.getColumnIndex(filePathColumn[0]);
picturePath = imageCursor.getString(columnIndex);
if (picturePath == null) {
picturePath = selectedImageUri.getPath();
String wholeID = DocumentsContract
.getDocumentId(selectedImage);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = mainActivity.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[] { id }, null);
columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
picturePath = cursor.getString(columnIndex);
}
cursor.close();
}
picturePathAbs = new File(picturePath).getAbsolutePath();
imageCursor.close();
}
}
package com.ImageConvertingDemo;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.ImageView;
public class MyActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
EditText tv = (EditText)findViewById(R.id.EditText01);
ImageView iv = (ImageView)findViewById(R.id.ImageView01);
FileInputStream in;
BufferedInputStream buf;
try
{
in = new FileInputStream("/sdcard/smooth.png");
buf = new BufferedInputStream(in,1070);
System.out.println("1.................."+buf);
byte[] bMapArray= new byte[buf.available()];
tv.setText(bMapArray.toString());
buf.read(bMapArray);
Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
/*for (int i = 0; i < bMapArray.length; i++)
{
System.out.print("bytearray"+bMapArray[i]);
}*/
iv.setImageBitmap(bMap);
//tv.setText(bMapArray.toString());
//tv.setText(buf.toString());
if (in != null)
{
in.close();
}
if (buf != null)
{
buf.close();
}
}
catch (Exception e)
{
Log.e("Error reading file", e.toString());
}
}
}
public class BrowsePictureActivity extends Activity {
// this is the action code we use in our intent,
// this way we know we're looking at the response from our own action
private static final int SELECT_PICTURE = 1;
private String selectedImagePath;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.Button01))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
}
}
}
/**
* helper to retrieve the path of an image URI
*/
public String getPath(Uri uri) {
// just some safety built in
if( uri == null ) {
// TODO perform some logging or show user feedback
return null;
}
// try to retrieve the image from the media store first
// this will only work for images selected from gallery
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if( cursor != null ){
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
// this is our fallback here
return uri.getPath();
}
}
ตัวอย่างนี้จะได้รับสำเนาของภาพ
static final int REQUEST_IMAGE_GET = 1;
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_IMAGE_GET);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
Bitmap thumbnail = data.getParcelable("data");
Uri fullPhotoUri = data.getData();
// Do work with photo saved at fullPhotoUri
...
}
}
เมื่อทำงานบน 4.4 หรือสูงกว่าคุณขอให้เปิดไฟล์ที่จัดการโดยแอพอื่น
static final int REQUEST_IMAGE_OPEN = 1;
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test.
startActivityForResult(intent, REQUEST_IMAGE_OPEN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) {
Uri fullPhotoUri = data.getData();
// Do work with full size photo saved at fullPhotoUri
...
}
}
เพิ่มเติมจากคำตอบก่อนหน้าหากคุณมีปัญหากับการหาเส้นทางที่ถูกต้อง (เช่น AndroZip) คุณสามารถใช้สิ่งนี้:
public String getPath(Uri uri ,ContentResolver contentResolver) {
String[] projection = { MediaStore.MediaColumns.DATA};
Cursor cursor;
try{
cursor = contentResolver.query(uri, projection, null, null, null);
} catch (SecurityException e){
String path = uri.getPath();
String result = tryToGetStoragePath(path);
return result;
}
if(cursor != null) {
//HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
//THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
String filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
else
return uri.getPath(); // FOR OI/ASTRO/Dropbox etc
}
private String tryToGetStoragePath(String path) {
int actualPathStart = path.indexOf("//storage");
String result = path;
if(actualPathStart!= -1 && actualPathStart< path.length())
result = path.substring(actualPathStart+1 , path.length());
return result;
}
โปรดหาคำตอบสำหรับการเลือกภาพเดียวจากแกลเลอรี่
import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class PickImage extends Activity {
Button btnOpen, btnGet, btnPick;
TextView textInfo1, textInfo2;
ImageView imageView;
private static final int RQS_OPEN_IMAGE = 1;
private static final int RQS_GET_IMAGE = 2;
private static final int RQS_PICK_IMAGE = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_pick);
btnOpen = (Button)findViewById(R.id.open);
btnGet = (Button)findViewById(R.id.get);
btnPick = (Button)findViewById(R.id.pick);
textInfo1 = (TextView)findViewById(R.id.info1);
textInfo2 = (TextView)findViewById(R.id.info2);
imageView = (ImageView) findViewById(R.id.image);
btnOpen.setOnClickListener(btnOpenOnClickListener);
btnGet.setOnClickListener(btnGetOnClickListener);
btnPick.setOnClickListener(btnPickOnClickListener);
}
View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN_IMAGE);
}
};
View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN_IMAGE);
}
};
View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RQS_PICK_IMAGE);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == RQS_OPEN_IMAGE ||
requestCode == RQS_GET_IMAGE ||
requestCode == RQS_PICK_IMAGE) {
imageView.setImageBitmap(null);
textInfo1.setText("");
textInfo2.setText("");
Uri mediaUri = data.getData();
textInfo1.setText(mediaUri.toString());
String mediaPath = mediaUri.getPath();
textInfo2.setText(mediaPath);
//display the image
try {
InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
Bitmap bm = BitmapFactory.decodeStream(inputStream);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] byteArray = stream.toByteArray();
imageView.setImageBitmap(bm);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
วิธีที่เร็วที่สุดในการเปิดภาพจากแกลเลอรี่หรือกล้อง
การอ้างอิงเดิม: รับภาพจากแกลเลอรี่ใน Android โดยทางโปรแกรม
วิธีการต่อไปนี้จะรับภาพจากแกลเลอรี่หรือกล้องและจะแสดงใน ImageView ภาพที่เลือกจะถูกเก็บไว้ภายใน
รหัสสำหรับ xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.exampledemo.parsaniahardik.uploadgalleryimage.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Capture Image and upload to server" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Below image is fetched from server"
android:layout_marginTop="5dp"
android:textSize="23sp"
android:gravity="center"
android:textColor="#000"/>
<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_launcher"
android:id="@+id/iv"/>
</LinearLayout>
คลาส JAVA
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.androidquery.AQuery;
import org.json.JSONException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity implements AsyncTaskCompleteListener{
private ParseContent parseContent;
private Button btn;
private ImageView imageview;
private static final String IMAGE_DIRECTORY = "/demonuts_upload_camera";
private final int CAMERA = 1;
private AQuery aQuery;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
parseContent = new ParseContent(this);
aQuery = new AQuery(this);
btn = (Button) findViewById(R.id.btn);
imageview = (ImageView) findViewById(R.id.iv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA);
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == this.RESULT_CANCELED) {
return;
}
if (requestCode == CAMERA) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
String path = saveImage(thumbnail);
try {
uploadImageToServer(path);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void uploadImageToServer(final String path) throws IOException, JSONException {
if (!AndyUtils.isNetworkAvailable(MainActivity.this)) {
Toast.makeText(MainActivity.this, "Internet is required!", Toast.LENGTH_SHORT).show();
return;
}
HashMap<String, String> map = new HashMap<String, String>();
map.put("url", "https://demonuts.com/Demonuts/JsonTest/Tennis/uploadfile.php");
map.put("filename", path);
new MultiPartRequester(this, map, CAMERA, this);
AndyUtils.showSimpleProgressDialog(this);
}
@Override
public void onTaskCompleted(String response, int serviceCode) {
AndyUtils.removeSimpleProgressDialog();
Log.d("res", response.toString());
switch (serviceCode) {
case CAMERA:
if (parseContent.isSuccess(response)) {
String url = parseContent.getURL(response);
aQuery.id(imageview).image(url);
}
}
}
public String saveImage(Bitmap myBitmap) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File wallpaperDirectory = new File(
Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
// have the object build the directory structure, if needed.
if (!wallpaperDirectory.exists()) {
wallpaperDirectory.mkdirs();
}
try {
File f = new File(wallpaperDirectory, Calendar.getInstance()
.getTimeInMillis() + ".jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(this,
new String[]{f.getPath()},
new String[]{"image/jpeg"}, null);
fo.close();
Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());
return f.getAbsolutePath();
} catch (IOException e1) {
e1.printStackTrace();
}
return "";
}
}
นี่คือตัวอย่างของฉันอาจไม่ตรงกับกรณีของคุณ
สมมติว่าคุณได้รับรูปแบบ base64 จากผู้ให้บริการ API ของคุณตั้งชื่อไฟล์และนามสกุลไฟล์บันทึกไว้ในตำแหน่งที่แน่นอนในระบบไฟล์
public static void shownInBuiltInGallery(final Context ctx, String strBase64Image, final String strFileName, final String strFileExtension){
new AsyncTask<String, String, File>() {
@Override
protected File doInBackground(String... strBase64Image) {
Bitmap bmpImage = convertBase64StringToBitmap(strBase64Image[0], Base64.NO_WRAP);
if(bmpImage == null) {
cancel(true);
return null;
}
byte[] byImage = null;
if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_JPG) == 0) {
byImage = convertToJpgByte(bmpImage); // convert bitmap to binary for latter use
} else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_PNG) == 0){
byImage = convertToPngByte(bmpImage); // convert bitmap to binary for latter use
} else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_BMP) == 0){
byImage = convertToBmpByte(bmpImage); // convert bitmap to binary for latter use
} else {
cancel(true);
return null;
}
if(byImage == null) {
cancel(true);
return null;
}
File imageFolder = ctx.getExternalCacheDir();
if(imageFolder.exists() == false){
if(imageFolder.mkdirs() == false){
cancel(true);
return null;
}
}
File imageFile = null;
try {
imageFile = File.createTempFile(strFileName, strFileExtension, imageFolder);
} catch (IOException e){
e.printStackTrace();
}
if(imageFile == null){
cancel(true);
return null;
}
if (imageFile.exists() == true) {
if(imageFile.delete() == false){
cancel(true);
return null;
}
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageFile.getPath());
fos.write(byImage);
fos.flush();
fos.close();
} catch (java.io.IOException e) {
e.printStackTrace();
} finally {
fos = null;
}
return imageFile;
}
@Override
protected void onPostExecute(File file) {
super.onPostExecute(file);
String strAuthority = ctx.getPackageName() + ".provider";
Uri uriImage = FileProvider.getUriForFile(ctx, strAuthority, file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uriImage, "image/*");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
ctx.startActivity(intent);
}
}.execute(strBase64Image);}
อย่าลืมตั้งค่าผู้ให้บริการไฟล์ที่ถูกต้องตั้งแต่แรกใน AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
โดยที่ไฟล์พา ธ คือ xml ใน ... / res / xml / file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<external-files-path name="external_files" path="Accessory"/>
<external-path name="ex_Download" path="Download/" />
<external-path name="ex_Pictures" path="Pictures/" />
<external-files-path name="my_Download" path="Download/" />
<external-files-path name="my_Pictures" path="Pictures/" />
<external-cache-path name="my_cache" path="." />
<files-path name="private_Download" path="Download/" />
<files-path name="private_Pictures" path="Pictures/" />
<cache-path name="private_cache" path="." />
เรื่องสั้นสั้น ๆ เตรียมผู้ให้บริการไฟล์ไว้ตั้งแต่แรกส่ง Uri ไปยัง Intent เพื่อหาแหล่งรูปภาพที่รู้จักและเข้าถึงได้มิฉะนั้นให้บันทึกรูปภาพในตำแหน่งที่ต้องการแล้วส่งตำแหน่ง (เป็น Uri) ไปยัง Intent