日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

简单图库软件的实现(联网下载图片保存到sdcard在Listview中展示,并作为ContentProvider为其他软件提供图库数据)

發(fā)布時間:2025/4/5 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单图库软件的实现(联网下载图片保存到sdcard在Listview中展示,并作为ContentProvider为其他软件提供图库数据) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

先看效果圖:




這就是一個可以聯(lián)網(wǎng)的圖庫軟件,下面我們來看看需求


業(yè)務(wù)需求

1.判斷是否第一次運行,第一次運行,提示添加新條目

2.點擊添加按鈕,彈出對話框,輸入圖片網(wǎng)址和標(biāo)題

3.下載圖片保存到本地SD卡中

4.數(shù)據(jù)庫中保存圖片文件路徑和圖片標(biāo)題和URL地址

5.listview中列出已保存的所有條目,添加條目后,同步展現(xiàn)到listview中

6.選中l(wèi)istview中一個條目,點擊刪除,刪除存儲的條目,同步展現(xiàn)到listview

7.長按listview的條目,彈出刪除菜單項,點擊菜單項也可以刪除條目

8.提供contentprovider供其他軟件訪問數(shù)據(jù)庫


問題分析

雖然要求看起來挺多但是可以大致分為3部分去實現(xiàn)

  • 數(shù)據(jù)的下載保存,包括存儲到本地sdcard 和數(shù)據(jù)庫中
  • 數(shù)據(jù)的刪除
  • 為其他軟件提供數(shù)據(jù)庫接口

  • 主要代碼實現(xiàn)

    首先用戶輸入圖片地址我們應(yīng)該去下載圖片并保存到本地,此時下載圖片屬于耗時且需要聯(lián)網(wǎng)的操作所以不能在ui線程中實現(xiàn),我們創(chuàng)建異步任務(wù)AsyncTask完成圖片下載,并通知UI線程更新進度條界面。下載完成應(yīng)該返回圖片的保存地址準(zhǔn)備將數(shù)據(jù)寫入數(shù)據(jù)庫中 由于要展示下載的進度我們利用接口回調(diào)比較好實現(xiàn)。下面是下載圖片的異步任務(wù)代碼:

    import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL;import android.os.AsyncTask; import android.os.Environment;public class MyTask extends AsyncTask<String, Integer, String> {public interface CallBack {public void start(); //主界面展示一個進度條public void updataProgress(int progress); //更新進度條public void finish(String imgPath); //下載完成返回文件保存到絕對路徑}CallBack cb;public MyTask(CallBack cb) {super();this.cb = cb;}@Overrideprotected void onPreExecute() {super.onPreExecute();if (cb != null) {cb.start(); //準(zhǔn)備工作}}@Overrideprotected String doInBackground(String... params) {// 1.HttpURLConnectionHttpURLConnection conn = null;String imgPath = null;// 2.URLtry {URL url = new URL(params[0]);// 3.url.openConnectionconn = (HttpURLConnection) url.openConnection();// 4.InputStreamInputStream in = conn.getInputStream();// 獲取該文件的總長度int total = conn.getContentLength();// 5.獲取保存文件的路徑及文件 名/sdcard/imageString path_sdcard = Environment.getExternalStorageDirectory().getAbsolutePath() + "/image";File fileParent = new File(path_sdcard);// 判斷該目錄是否存在,如果不存在,創(chuàng)建該目錄if (!fileParent.exists()) {// 創(chuàng)建目錄fileParent.mkdirs();}String arr[] = params[0].split("/");String filenameString = arr[arr.length - 1];// 6.創(chuàng)建File對象,再拿到OutputStreamFile file = new File(path_sdcard, filenameString);if (file.exists()) {return file.getAbsolutePath();}// 用來返回該img路徑imgPath = file.getAbsolutePath();OutputStream out = new FileOutputStream(file);byte[] buffer = new byte[4096];int sum = 0;int len = 0;while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);// 累加sum = sum + len;// 計算百分比int per = (int) (sum * 100f / total);// 發(fā)布進度值publishProgress(per);}out.flush();out.close();in.close();// 返回當(dāng)前被保存的img的絕對路徑return imgPath;} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if (conn != null) {conn.disconnect();}}//下載異常返回NULLreturn null;}@Overrideprotected void onProgressUpdate(Integer... values) {// TODO Auto-generated method stubsuper.onProgressUpdate(values);if (cb != null) {cb.updataProgress(values[0]); //更新進度條}}/** result表示的是圖片所在的的路徑*/@Overrideprotected void onPostExecute(String result) {// TODO Auto-generated method stubsuper.onPostExecute(result);if (cb != null) {cb.finish(result); //返回圖片地址}}}

    圖片下載完成并且保存到本地了 此時我們應(yīng)該將圖片名稱 URL 絕對路徑 寫入數(shù)據(jù)庫。 那么此時我們應(yīng)該開始創(chuàng)建數(shù)據(jù)庫了,自定義MySqliteHelper 繼承SQLiteOpenHelper 就好了,代碼如下

    import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log;public class MySqliteHelper extends SQLiteOpenHelper {public MySqliteHelper(Context context) {super(context, "picture.db", null, 1);}@Overridepublic void onCreate(SQLiteDatabase db) {// 創(chuàng)表String sql = "create table img(_id integer primary key autoincrement,name text ,url text,path text)";db.execSQL(sql);Log.d("onCreateDataBase", "helper onCreate create table img");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// TODO Auto-generated method stub}}

    數(shù)據(jù)庫有著落了,那么我們應(yīng)該想著如何將數(shù)據(jù)展示到listview中,這里L(fēng)istView中的每個item包含了一張圖片一個文本 。 這里就用就靈活的BaseAdapter完成,我們自定義一個MyAdapter繼承自BaseAdapter。

    import java.io.File; import java.util.ArrayList; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;public class MyAdapter extends BaseAdapter {ArrayList<Picture> data;Context context;LayoutInflater inflater;int progress;public MyAdapter(ArrayList<Picture> data, Context context) {super();this.data = data;this.context = context;inflater = LayoutInflater.from(context);}@Overridepublic int getCount() {return data.size();}@Overridepublic Object getItem(int position) {return data.get(position);}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder holder = null;if (convertView == null) {holder = new ViewHolder();convertView = inflater.inflate(R.layout.list_item, null);holder.tv_1 = (TextView) convertView.findViewById(R.id.tv);holder.iv = (ImageView) convertView.findViewById(R.id.img);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}Picture picture = data.get(position);File file = new File(picture.path);if (file.exists()) { // 如果sd卡的圖片存在去設(shè)置圖片holder.tv_1.setText(picture.name);Bitmap bitmap = BitmapFactory.decodeFile(picture.path);holder.iv.setImageBitmap(bitmap);} else { // 圖片不存在提示用戶Toast.makeText(context, picture.name + "好像出了點問題,圖片是否被你刪除?",Toast.LENGTH_SHORT).show();// 本地圖片被刪除 刪除數(shù)據(jù)庫中的數(shù)據(jù)MySqliteHelper helper = new MySqliteHelper(context);SQLiteDatabase db = helper.getWritableDatabase();String sql = "DELETE FROM img WHERE path = '" + picture.path + "'";db.execSQL(sql);}return convertView;}class ViewHolder {TextView tv_1;ImageView iv;}}

    數(shù)據(jù)展示問題也解決了,那么 接下來就是刪除事件,點擊listview 或者長按listview中的item都有對應(yīng)的監(jiān)聽事件分別是setOnItemClickListener、 setOnItemLongClickListener
    刪除事件的實現(xiàn):

    lv.setOnItemLongClickListener(new OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view,final int position, long id) {AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setTitle("刪除" + data.get(position).name).setMessage("此操作不可逆,是否繼續(xù)?");// 相當(dāng)于確定builder.setPositiveButton("確定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {/** 注釋部分為普通sql查詢語句 String sql =* "delete from img where url='" +* data.get(position).url + "'";* db.execSQL(sql);*/// 1.獲取連接服務(wù)地址Uri uri = Uri.parse("content://com.picture.provider");// 2.獲取ContentResolverContentResolver cr = getContentResolver();// 3.根據(jù)位置獲取到數(shù)據(jù)庫中相應(yīng)的url 作為條件刪除相應(yīng)的數(shù)據(jù)cr.delete(uri, "url='" + data.get(position).url+ "'", null);File file = new File(data.get(position).path);if (file.exists()) { // 如果存在那么刪除本地文件file.delete();}data = readDataBase(); // 讀取數(shù)據(jù)庫中的內(nèi)容MainActivity.this.position = -1;// 每次刪除完畢設(shè)置當(dāng)前位置為-1 為下一次點擊做準(zhǔn)備adapter.notifyDataSetChanged();// 提示更新界面}});// 相當(dāng)于取消 這里啥都不干builder.setNegativeButton("取消",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {}});builder.show();return false;}});
    public void del(View view) {// 刪除圖片if (position != -1) {AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setTitle("刪除" + data.get(position).name).setMessage("此操作不可逆,是否繼續(xù)?");// 相當(dāng)于確定builder.setPositiveButton("確定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {/** String sql = "delete from img where url='" +* data.get(position).url + "'"; db.execSQL(sql);*/Uri uri = Uri.parse("content://com.picture.provider");// 獲取ContentResolverContentResolver cr = getContentResolver();// 準(zhǔn)備數(shù)據(jù)cr.delete(uri, "url='" + data.get(position).url+ "'", null);File file = new File(data.get(position).path);if (file.exists()) { // 如果存在那么刪除本地文件file.delete();}data = readDataBase(); // 讀取數(shù)據(jù)庫中的內(nèi)容if (data.size() == 0) { // 沒有東西那么接下的鏈接可以直接下載flag = true;MainActivity.this.position = -1;}adapter.notifyDataSetChanged();// 提示更新界面}});// 相當(dāng)于取消builder.setNegativeButton("取消",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {}});builder.show();} else {Toast.makeText(this, "當(dāng)前沒有選中任何圖片!", Toast.LENGTH_LONG).show();}}

    刪除功能也實現(xiàn)了,接下來我們實現(xiàn)ContentProvider功能其實也簡單,寫一個類繼承自ContentProvider

    import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log;public class MyContentProvider extends ContentProvider {MySqliteHelper helper;@Overridepublic boolean onCreate() {helper = new MySqliteHelper(getContext());if (helper != null) {return true;}return false;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {SQLiteDatabase db = helper.getWritableDatabase();Cursor cursor = db.query("img", projection, selection, selectionArgs,null, null, sortOrder);cursor.setNotificationUri(getContext().getContentResolver(), uri); // 通知界面更新return cursor;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues values) {Log.e("insert", " " + uri.getAuthority());SQLiteDatabase db = helper.getWritableDatabase();long id = -1;id = db.insert("img", null, values);db.close();getContext().getContentResolver().notifyChange(uri, null);return ContentUris.withAppendedId(uri, id); }@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {Log.e("delete", "delete");SQLiteDatabase db = helper.getWritableDatabase();int count = db.delete("img", selection, selectionArgs);getContext().getContentResolver().notifyChange(uri, null);return count; //返回刪除的條數(shù)}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {Log.e("update", "update"+selection);SQLiteDatabase db = helper.getWritableDatabase();int count = db.update("img", values, selection, selectionArgs);getContext().getContentResolver().notifyChange(uri, null);return count;}}

    在xml中注冊provider提供給其他程序

    <provider android:name="com.wenxiangli.MyContentProvider"android:authorities="com.picture.provider"android:exported="true" ></provider>

    至此我們需要的功能都實現(xiàn)了。接下來說幾個遇到的問題注意點:

    1.權(quán)限一定不要忘記了

    <!-- 聯(lián)網(wǎng)權(quán)限 --><uses-permission android:name="android.permission.INTERNET" /><!-- SDcard的讀寫權(quán)限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!-- 讀取Sdcard狀態(tài)權(quán)限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    2.為了完成第二次啟動加載本地圖片,我們應(yīng)該先從數(shù)據(jù)庫讀出數(shù)據(jù)然后綁定到集合中去通知adapter更新
    3.刪除特別注意越界問題,這里我是通過每次刪除結(jié)束設(shè)置positon為-1,當(dāng)點擊事件產(chǎn)生將改變position的值去判斷是否刪除。
    4.保證圖庫中的數(shù)據(jù)唯一,所以每次下載前判斷圖片是否存在,存在就不去下載。直接提示是否更改文件的名字


    下面附上完整源碼地址需要的可以在這下載
    鏈接:http://pan.baidu.com/s/1dEW5JBr 密碼:m3jb

    寫這么長不容易啊,如果對你有幫助賞給回復(fù) 啊哈哈

    總結(jié)

    以上是生活随笔為你收集整理的简单图库软件的实现(联网下载图片保存到sdcard在Listview中展示,并作为ContentProvider为其他软件提供图库数据)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美成人三级伦在线观看 | 国产日韩欧美 | 天天鲁一鲁摸一摸爽一爽 | 久久男人的天堂 | 碧蓝之海动漫在线观看免费高清 | 一区二区黄色片 | 人人干在线视频 | 曰本不卡视频 | av片免费在线播放 | 国产欧美日韩在线播放 | 天天视频入口 | 欧美一级爱爱视频 | 中文字幕无线精品亚洲乱码一区 | 欧美aⅴ在线观看 | 人妻精品久久久久中文字幕69 | 国产夜夜夜 | 777久久久 | 亚欧美| 色xxxx| 日本三级片在线观看 | 欧美成人aa | 91蝌蚪网 | 四虎婷婷 | 超碰狠狠| 性爱免费视频 | 欧美精品一区三区 | 欧美三个黑人玩3p | 日本成人一区二区三区 | 丰满大乳露双乳呻吟 | 91九色网 | 亚洲熟妇一区 | 国产精品美女久久久久久久 | 黑人玩弄人妻一区二区三区免费看 | 青青草成人影视 | 求个黄色网址 | 黄网站免费视频 | 色哟哟免费 | 久艹在线观看视频 | 激情第四色 | 欧美黄片一区二区三区 | 国产精品一区二区久久国产 | 大尺度网站在线观看 | 好紧好爽再浪一点视频 | 放几个免费的毛片出来看 | 国内精品国产成人国产三级 | 超碰1000| 亚洲图片 自拍偷拍 | 欧美综合激情 | 国产免费看 | 黄色91视频 | 免费h片网站 | 精品一二三四 | 精品久久中文字幕 | 99热这里只有精 | 日韩人妻一区二区三区蜜桃 | 中文字幕乱码一区二区 | 99无码熟妇丰满人妻啪啪 | 朝桐光av在线一区二区三区 | 日日操影院 | 麻豆久久久9性大片 | 成人涩涩软件 | av免费观看不卡 | 国产精品福利导航 | 99re免费视频 | 人妻互换免费中文字幕 | 天堂视频一区 | 欧美性视频一区二区 | 日韩精品一区二区av | 欧美成人影音 | 一出一进一爽一粗一大视频 | 亚洲激情视频在线 | 九色视频在线观看 | 台湾色综合 | 久久久久久少妇 | 欧美日韩国产二区 | 九九少妇 | 亚洲AV综合色区无码国产播放 | 国产成人自拍网站 | cao久久 | 国产一级影院 | 欧美精品三区 | 国产黄色自拍视频 | 黄色资源在线 | 天天躁日日躁aaaaxxxx | 美日韩在线 | 97自拍偷拍视频 | 91无打码| 欧美一区精品 | 好吊日在线观看 | 黄色一级小说 | 在线播放你懂的 | 国产乱人乱偷精品视频 | 亚洲一级在线播放 | 成人一级片在线观看 | av久久久| 久久激情综合网 | 国产91免费观看 | 美国成人av | 加勒比精品在线 |