将画廊中的所有图像加载到android中的应用程序中
Posted
技术标签:
【中文标题】将画廊中的所有图像加载到android中的应用程序中【英文标题】:Loading all the images from gallery into the Application in android 【发布时间】:2013-09-06 14:00:29 【问题描述】:我正在创建一个应用程序,其中我需要将图库中的所有图像放入我的应用程序中,其中包含一个 girdview。我希望所有文件夹中的所有图像都出现在 gridview 中。
String[] proj = MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID ;
actualimagecursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj,
null, null, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
actualimagecursor.moveToPosition(position);
String i = actualimagecursor.getString(actual_image_column_index);
我已将此代码添加到我的代码中,但我只获得了 sd 卡图像,没有获得其他文件夹图像。 如何从图库中获取所有图像?
提前致谢。
【问题讨论】:
试试这些例子。android-er.blogspot.in/2012/07/…***.com/questions/6855399/…github.com/nostra13/Android-Universal-Image-Loadermobile.dzone.com/news/displaying-images-sd-cardanusreeanair.blogspot.in/2012/09/… 【参考方案1】:在 Glide 的帮助下工作的解决方案。奖励部分是 Glide 会自动播放 Gif。
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
/**
* The Class GallarySample.
*/
public class GallarySample extends Activity
/** The images. */
private ArrayList<String> images;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery_activity);
GridView gallery = (GridView) findViewById(R.id.galleryGridView);
gallery.setAdapter(new ImageAdapter(this));
gallery.setOnItemClickListener(new OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3)
if (null != images && !images.isEmpty())
Toast.makeText(
getApplicationContext(),
"position " + position + " " + images.get(position),
300).show();
;
);
/**
* The Class ImageAdapter.
*/
private class ImageAdapter extends BaseAdapter
/** The context. */
private Activity context;
/**
* Instantiates a new image adapter.
*
* @param localContext
* the local context
*/
public ImageAdapter(Activity localContext)
context = localContext;
images = getAllShownImagesPath(context);
public int getCount()
return images.size();
public Object getItem(int position)
return position;
public long getItemId(int position)
return position;
public View getView(final int position, View convertView,
ViewGroup parent)
ImageView picturesView;
if (convertView == null)
picturesView = new ImageView(context);
picturesView.setScaleType(ImageView.ScaleType.FIT_CENTER);
picturesView
.setLayoutParams(new GridView.LayoutParams(270, 270));
else
picturesView = (ImageView) convertView;
Glide.with(context).load(images.get(position))
.placeholder(R.drawable.ic_launcher).centerCrop()
.into(picturesView);
return picturesView;
/**
* Getting All Images Path.
*
* @param activity
* the activity
* @return ArrayList with images Path
*/
private ArrayList<String> getAllShownImagesPath(Activity activity)
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
ArrayList<String> listOfAllImages = new ArrayList<String>();
String absolutePathOfImage = null;
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME ;
cursor = activity.getContentResolver().query(uri, projection, null,
null, null);
column_index_data = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
column_index_folder_name = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext())
absolutePathOfImage = cursor.getString(column_index_data);
listOfAllImages.add(absolutePathOfImage);
return listOfAllImages;
gridView 的布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_ >
<GridView
android:id="@+id/galleryGridView"
android:layout_
android:layout_
android:columnWidth="280dp"
android:gravity="center"
android:horizontalSpacing="2dp"
android:numColumns="2"
android:padding="2dp"
android:stretchMode="columnWidth"
android:verticalSpacing="2dp" >
</GridView>
</RelativeLayout>
2019 年更新,Kotlin
和 LoderManager
:
** 2) 使用 LoderManager 加载异步加载图片。**
在您的活动或片段类中实现LoaderManager.LoaderCallbacks<Cursor>
重写 LoaderCallbacks 这个:
private val IMAGE_LOADER_ID = 1
private val listOfAllImages = ArrayList<String>()
override fun onCreateLoader(p0: Int, p1: Bundle?): Loader<Cursor>
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
val selection: String? = null //Selection criteria
val selectionArgs = arrayOf<String>() //Selection criteria
val sortOrder: String? = null
return CursorLoader(
activity!!.applicationContext,
uri,
projection,
selection,
selectionArgs,
sortOrder)
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor?)
cursor?.let
val columnIndexData = it.getColumnIndexOrThrow(MediaColumns.DATA);
while (it.moveToNext())
listOfAllImages.add(it.getString(columnIndexData));
override fun onLoaderReset(loader: Loader<Cursor>)
最后是 onCreate 方法初始化加载器:
loaderManager.initLoader(IMAGE_LOADER_ID,
null,
this)
3) 使用Kotlin Coroutine
& ViewModel
实现'androidx.core:core-ktx:1.0.2'
实现'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M2'
实现“org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-M2”
使用Coroutine
上下文创建视图模型
/**
* Use Coroutines To Load Images
*/
class ImageViewModel : ViewModel(), CoroutineScope
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
private var imagesLiveData: MutableLiveData<List<String>> = MutableLiveData()
fun getImageList(): MutableLiveData<List<String>>
return imagesLiveData
/**
* Getting All Images Path.
*
* Required Storage Permission
*
* @return ArrayList with images Path
*/
internal fun loadImagesfromSDCard(): ArrayList<String>
val uri: Uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val cursor: Cursor?
val column_index_data: Int
val column_index_folder_name: Int
val listOfAllImages = ArrayList<String>()
var absolutePathOfImage: String? = null
val projection = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
cursor = AppController.globalContentResolvere!!.query(uri, projection, null, null, null)
column_index_data = cursor!!.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
column_index_folder_name = cursor!!
.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
while (cursor!!.moveToNext())
absolutePathOfImage = cursor!!.getString(column_index_data)
listOfAllImages.add(absolutePathOfImage)
return listOfAllImages
fun getAllImages()
launch(Dispatchers.Main)
imagesLiveData.value = withContext(Dispatchers.IO)
loadImagesfromSDCard()
然后使用viewModel
val imageViewModel = ViewModelProviders.of(this).get(ImageViewModel::class.java)
imageViewModel.getImageList().observe(this, Observer<List<String>> listOfImage ->
imageWidgetStatus.text = """ Found $listOfImage.size Images"""
// load images
imageViewModel.getAllImages()
【讨论】:
有没有办法对图像进行排序并逐月显示?以及如何将视频与图像一起显示。 有一个 MediaStore.Images.Media.DEFAULT_SORT_ORDER.. 这是查询的参数... cursor = activity.getContentResolver().query(uri, projection, null, null, MediaStore.图片.Media.DEFAULT_SORT_ORDER); 访问 DATA 路径似乎已被弃用 你为什么要在另一个协程中启动一个协程。可以删除 getAllImages() 中的外部启动以防止不必要的上下文切换 ImageViewModel 类 kotlin 中的 AppController 是什么?【参考方案2】:您正在使用MediaStore.Images.Media.EXTERNAL_CONTENT_URI
,这只是外部存储。对于内部有MediaStore.Images.Media.INTERNAL_CONTENT_URI
。
您可以使用MergeCursor 来合并两个查询结果。
【讨论】:
我也尝试过这样做,但可以做到。对于 INTERNAL_CONTENT_URI 它说没有可用的数据。虽然我的手机内存里也有图片 你所说的内部存储是什么意思? 内部存储是您的应用程序可以存储文件的默认位置。它对您的应用是私有的。 例如 +1【参考方案3】:Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
【讨论】:
它将允许您从手机中的任何位置选择图像 嘿朋友 Onik 我已经代表如何从画廊或 android 手机中的任何位置获取图像给出了答案【参考方案4】: public static ArrayList<String> fetchGalleryImages(Activity context)
ArrayList<String> galleryImageUrls;
final String[] columns = MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID;//get all columns of type images
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;//order data by date
Cursor imagecursor = context.managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
null, orderBy + " DESC");//get all data in Cursor by sorting in DESC order
galleryImageUrls = new ArrayList<String>();
for (int i = 0; i < imagecursor.getCount(); i++)
imagecursor.moveToPosition(i);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);//get column index
galleryImageUrls.add(imagecursor.getString(dataColumnIndex));//get Image from column index
Log.e("fatch in","images");
return galleryImageUrls;
【讨论】:
【参考方案5】:你不能只用一个查询得到结果,尝试实例化两个不同的游标。 既然你已经添加了EXTERNAL_CONTENT_URI,这里还有一个:
actualimagecursor2 = managedQuery(MediaStore.Images.Media.INTERNAL_CONTENT_URI, proj,
null, null, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
【讨论】:
【参考方案6】:从这里下载源代码 (Get all images from gallery in android programmatically)
activity_main.xml
<RelativeLayout android:layout_
android:layout_
android:background="#ffffff"
xmlns:android="http://schemas.android.com/apk/res/android">
<GridView
android:layout_
android:layout_
android:id="@+id/gv_folder"
android:numColumns="2"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"></GridView>
</RelativeLayout>
MainActivity.java
package galleryimages.galleryimages;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity
public static ArrayList<Model_images> al_images = new ArrayList<>();
boolean boolean_folder;
Adapter_PhotosFolder obj_adapter;
GridView gv_folder;
private static final int REQUEST_PERMISSIONS = 100;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gv_folder = (GridView)findViewById(R.id.gv_folder);
gv_folder.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
Intent intent = new Intent(getApplicationContext(), PhotosActivity.class);
intent.putExtra("value",i);
startActivity(intent);
);
if ((ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED))
if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) && (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)))
else
ActivityCompat.requestPermissions(MainActivity.this,
new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
REQUEST_PERMISSIONS);
else
Log.e("Else","Else");
fn_imagespath();
public ArrayList<Model_images> fn_imagespath()
al_images.clear();
int int_position = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
String absolutePathOfImage = null;
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME;
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = getApplicationContext().getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext())
absolutePathOfImage = cursor.getString(column_index_data);
Log.e("Column", absolutePathOfImage);
Log.e("Folder", cursor.getString(column_index_folder_name));
for (int i = 0; i < al_images.size(); i++)
if (al_images.get(i).getStr_folder().equals(cursor.getString(column_index_folder_name)))
boolean_folder = true;
int_position = i;
break;
else
boolean_folder = false;
if (boolean_folder)
ArrayList<String> al_path = new ArrayList<>();
al_path.addAll(al_images.get(int_position).getAl_imagepath());
al_path.add(absolutePathOfImage);
al_images.get(int_position).setAl_imagepath(al_path);
else
ArrayList<String> al_path = new ArrayList<>();
al_path.add(absolutePathOfImage);
Model_images obj_model = new Model_images();
obj_model.setStr_folder(cursor.getString(column_index_folder_name));
obj_model.setAl_imagepath(al_path);
al_images.add(obj_model);
for (int i = 0; i < al_images.size(); i++)
Log.e("FOLDER", al_images.get(i).getStr_folder());
for (int j = 0; j < al_images.get(i).getAl_imagepath().size(); j++)
Log.e("FILE", al_images.get(i).getAl_imagepath().get(j));
obj_adapter = new Adapter_PhotosFolder(getApplicationContext(),al_images);
gv_folder.setAdapter(obj_adapter);
return al_images;
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
case REQUEST_PERMISSIONS:
for (int i = 0; i < grantResults.length; i++)
if (grantResults.length > 0 && grantResults[i] == PackageManager.PERMISSION_GRANTED)
fn_imagespath();
else
Toast.makeText(MainActivity.this, "The app was not allowed to read or write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
adapter_photosfolder.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical">
<LinearLayout
android:layout_
android:orientation="vertical"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:background="@drawable/drawable_photofolder"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_>
<ImageView
android:layout_
android:layout_gravity="center"
android:layout_
android:id="@+id/iv_image"/>
<TextView
android:layout_
android:layout_
android:id="@+id/tv_folder"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginLeft="10dp"
android:textSize="15dp"/>
<TextView
android:layout_
android:layout_
android:id="@+id/tv_folder2"
android:textColor="#dfdfdf"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:textSize="15dp"/>
</LinearLayout>
<RelativeLayout
android:layout_
android:id="@+id/rl_select"
android:alpha="0.5"
android:layout_>
</RelativeLayout>
</RelativeLayout>
Adapter_PhotosFolder.java
package galleryimages.galleryimages;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.util.ArrayList;
public class Adapter_PhotosFolder extends ArrayAdapter<Model_images>
Context context;
ViewHolder viewHolder;
ArrayList<Model_images> al_menu = new ArrayList<>();
public Adapter_PhotosFolder(Context context, ArrayList<Model_images> al_menu)
super(context, R.layout.adapter_photosfolder, al_menu);
this.al_menu = al_menu;
this.context = context;
@Override
public int getCount()
Log.e("ADAPTER LIST SIZE", al_menu.size() + "");
return al_menu.size();
@Override
public int getItemViewType(int position)
return position;
@Override
public int getViewTypeCount()
if (al_menu.size() > 0)
return al_menu.size();
else
return 1;
@Override
public long getItemId(int position)
return position;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
if (convertView == null)
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.adapter_photosfolder, parent, false);
viewHolder.tv_foldern = (TextView) convertView.findViewById(R.id.tv_folder);
viewHolder.tv_foldersize = (TextView) convertView.findViewById(R.id.tv_folder2);
viewHolder.iv_image = (ImageView) convertView.findViewById(R.id.iv_image);
convertView.setTag(viewHolder);
else
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.tv_foldern.setText(al_menu.get(position).getStr_folder());
viewHolder.tv_foldersize.setText(al_menu.get(position).getAl_imagepath().size()+"");
Glide.with(context).load("file://" + al_menu.get(position).getAl_imagepath().get(0))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(viewHolder.iv_image);
return convertView;
private static class ViewHolder
TextView tv_foldern, tv_foldersize;
ImageView iv_image;
**PhotosActivity.java**
package galleryimages.galleryimages;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.GridView;
public class PhotosActivity extends AppCompatActivity
int int_position;
private GridView gridView;
GridViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = (GridView)findViewById(R.id.gv_folder);
int_position = getIntent().getIntExtra("value", 0);
adapter = new GridViewAdapter(this,MainActivity.al_images,int_position);
gridView.setAdapter(adapter);
**GridViewAdapter.java**
package galleryimages.galleryimages;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.util.ArrayList;
import java.util.List;
public class GridViewAdapter extends ArrayAdapter<Model_images>
Context context;
ViewHolder viewHolder;
ArrayList<Model_images> al_menu = new ArrayList<>();
int int_position;
public GridViewAdapter(Context context, ArrayList<Model_images> al_menu,int int_position)
super(context, R.layout.adapter_photosfolder, al_menu);
this.al_menu = al_menu;
this.context = context;
this.int_position = int_position;
@Override
public int getCount()
Log.e("ADAPTER LIST SIZE", al_menu.get(int_position).getAl_imagepath().size() + "");
return al_menu.get(int_position).getAl_imagepath().size();
@Override
public int getItemViewType(int position)
return position;
@Override
public int getViewTypeCount()
if (al_menu.get(int_position).getAl_imagepath().size() > 0)
return al_menu.get(int_position).getAl_imagepath().size();
else
return 1;
@Override
public long getItemId(int position)
return position;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
if (convertView == null)
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.adapter_photosfolder, parent, false);
viewHolder.tv_foldern = (TextView) convertView.findViewById(R.id.tv_folder);
viewHolder.tv_foldersize = (TextView) convertView.findViewById(R.id.tv_folder2);
viewHolder.iv_image = (ImageView) convertView.findViewById(R.id.iv_image);
convertView.setTag(viewHolder);
else
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.tv_foldern.setVisibility(View.GONE);
viewHolder.tv_foldersize.setVisibility(View.GONE);
Glide.with(context).load("file://" + al_menu.get(int_position).getAl_imagepath().get(position))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(viewHolder.iv_image);
return convertView;
private static class ViewHolder
TextView tv_foldern, tv_foldersize;
ImageView iv_image;
Model_images.java
package galleryimages.galleryimages;
import java.util.ArrayList;
public class Model_images
String str_folder;
ArrayList<String> al_imagepath;
public String getStr_folder()
return str_folder;
public void setStr_folder(String str_folder)
this.str_folder = str_folder;
public ArrayList<String> getAl_imagepath()
return al_imagepath;
public void setAl_imagepath(ArrayList<String> al_imagepath)
this.al_imagepath = al_imagepath;
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="galleryimages.galleryimages">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".PhotosActivity"></activity>
</application>
</manifest>
【讨论】:
看图不需要android.permission.WRITE_EXTERNAL_STORAGE 很抱歉,这段代码写得很糟糕……读起来很痛苦,或者我只是习惯了 java 风格。还是谢谢【参考方案7】:这就是我在 Kotlin 中使用 Coroutines 和 Flow 的方式(但 Flow 可以轻松更改为 LivaData)。
依赖关系:
def lifecycle_version = "2.2.0"
def coroutines_version = "1.4.2"
def glide_version = "4.11.0"
// Coroutines https://github.com/Kotlin/kotlinx.coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
// Lifecycle https://developer.android.com/jetpack/androidx/releases/lifecycle#declaring_dependencies
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// Glide https://github.com/bumptech/glide (OPTIONALLY)
implementation "com.github.bumptech.glide:glide:$glide_version"
视图模型:
import android.app.Application
import android.content.ContentUris
import android.net.Uri
import android.provider.MediaStore
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AddViewModel(
application: Application
) : AndroidViewModel(application)
private val _allImagesFromGallery: MutableStateFlow<List<Uri>> = MutableStateFlow(listOf())
val allImagesFromGallery: StateFlow<List<Uri>> = _allImagesFromGallery
private fun getAllImages(): List<Uri>
val allImages = mutableListOf<Uri>()
val imageProjection = arrayOf(
MediaStore.Images.Media._ID
)
val imageSortOrder = "$MediaStore.Images.Media.DATE_ADDED DESC"
val cursor = getApplication<Application>().contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageProjection,
null,
null,
imageSortOrder
)
cursor.use
if (cursor != null)
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (cursor.moveToNext())
allImages.add(
ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
cursor.getLong(idColumn)
)
)
else
Log.d("AddViewModel", "Cursor is null!")
return allImages
fun loadAllImages()
viewModelScope.launch
_allImagesFromGallery.value = withContext(Dispatchers.IO)
getAllImages()
在片段(或活动)中:
import android.os.Bundle
import android.view.View
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
import kotlinx.coroutines.flow.collectLatest
class AddFragment : Fragment(R.layout.fragment_add)
private lateinit var binding: FragmentAddBinding
private val viewModel: AddViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
binding = DataBindingUtil.bind(view)!!
viewModel.loadAllImages()
setupCollecting()
private fun setupCollecting()
lifecycleScope.launchWhenStarted
viewModel.allImagesFromGallery.collectLatest
// simple test, take first image and load it to ImageView using Glide
if (it.isNotEmpty())
Glide.with(requireContext())
.load(it[0])
.into(binding.imgSelected)
在从图库中加载所有图片之前,Manifest.permission.READ_EXTERNAL_STORAGE
必须获得授权。
当在 Manifest 中使用 Glide
时,还应该有:android:requestLegacyExternalStorage="true"
【讨论】:
以上是关于将画廊中的所有图像加载到android中的应用程序中的主要内容,如果未能解决你的问题,请参考以下文章