Android拍照保存在系统相册与照片不显示解决方法

 更新时间:2016年9月20日 19:59  点击:2144
现在几乎所有app应用都可以调用手机的照相功能了,但我在开始时碰到一个问题就是拍照之后在系统相册中找不到我拍照的照片怎么办?下面我来给各位同学一并分享一下。

系统已经有的东西,如果我们没有新的需求的话,直接调用是最直接的。下面讲讲调用系统相机拍照并保存图片和如何调用系统相册的方法。

首先看看调用系统相机的核心方法:

 代码如下 复制代码
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 startActivityForResult(camera, CAMERA);

相机返回的数据通过下面的回调方法取得,并处理:

 代码如下 复制代码

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
 
  if(requestCode == CAMERA && resultCode == Activity.RESULT_OK && null != data){
   String sdState=Environment.getExternalStorageState();
   if(!sdState.equals(Environment.MEDIA_MOUNTED)){
    GameLog.log(Tag, "sd card unmount");
    return;
   }
   new DateFormat();
   String name= DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA))+".jpg";
   Bundle bundle = data.getExtras();
   //获取相机返回的数据,并转换为图片格式
   Bitmap bitmap = (Bitmap)bundle.get("data");
   FileOutputStream fout = null;
   File file = new File("/sdcard/pintu/");
   file.mkdirs();
   String filename=file.getPath()+name;
   try {
    fout = new FileOutputStream(filename);
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
   } catch (FileNotFoundException e) {
    e.printStackTrace();
   }finally{
    try {
     fout.flush();
     fout.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   //显示图片
  
  }

}

 

下面是调用系统相册并取得照片的方法:

 代码如下 复制代码
Intent picture = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(picture, PICTURE);

下面是相应的回调方法:

 

 代码如下 复制代码

@Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
 
  if(requestCode == CAMERA && resultCode == Activity.RESULT_OK && null != data){
 

   Uri selectedImage = data.getData();
   String[] filePathColumns={MediaStore.Images.Media.DATA};
   Cursor c = this.getContentResolver().query(selectedImage, filePathColumns, null,null, null);
   c.moveToFirst();
   int columnIndex = c.getColumnIndex(filePathColumns[0]);
   String picturePath= c.getString(columnIndex);
   c.close();
   //获取图片并显示

  
  }


 
这样就完成了系统调用,很简单,但是有些朋友会碰到照片拍好了,在手机相册中发现照片不显示呀。


解决Android拍照保存在系统相册不显示的问题

MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");通过上面的那句代码就能插入到系统图库,这时候有一个问题,就是我们不能指定插入照片的名字,而是系统给了我们一个当前时间的毫秒数为名字,有一个问题郁闷了很久,我还是先把insertImage的源码贴出来吧

 代码如下 复制代码

 

 /**
             * Insert an image and create a thumbnail for it.
             *
             * @param cr The content resolver to use
             * @param source The stream to use for the image
             * @param title The name of the image
             * @param description The description of the image
             * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
             *              for any reason.
             */
            public static final String insertImage(ContentResolver cr, Bitmap source,
                                                   String title, String description) {
                ContentValues values = new ContentValues();
                values.put(Images.Media.TITLE, title);
                values.put(Images.Media.DESCRIPTION, description);
                values.put(Images.Media.MIME_TYPE, "image/jpeg");

                Uri url = null;
                String stringUrl = null;    /* value to be returned */

                try {
                    url = cr.insert(EXTERNAL_CONTENT_URI, values);

                    if (source != null) {
                        OutputStream imageOut = cr.openOutputStream(url);
                        try {
                            source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
                        } finally {
                            imageOut.close();
                        }

                        long id = ContentUris.parseId(url);
                        // Wait until MINI_KIND thumbnail is generated.
                        Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id,
                                Images.Thumbnails.MINI_KIND, null);
                        // This is for backward compatibility.
                        Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F,
                                Images.Thumbnails.MICRO_KIND);
                    } else {
                        Log.e(TAG, "Failed to create thumbnail, removing original");
                        cr.delete(url, null, null);
                        url = null;
                    }
                } catch (Exception e) {
                    Log.e(TAG, "Failed to insert image", e);
                    if (url != null) {
                        cr.delete(url, null, null);
                        url = null;
                    }
                }

                if (url != null) {
                    stringUrl = url.toString();
                }

                return stringUrl;
            }


上面方法里面有一个title,我刚以为是可以设置图片的名字,设置一下,原来不是,郁闷,哪位高手知道title这个字段是干嘛的,告诉下小弟,不胜感激!

当然Android还提供了一个插入系统相册的方法,可以指定保存图片的名字,我把源码贴出来吧

 

 代码如下 复制代码

   /**
             * Insert an image and create a thumbnail for it.
             *
             * @param cr The content resolver to use
             * @param imagePath The path to the image to insert
             * @param name The name of the image
             * @param description The description of the image
             * @return The URL to the newly created image
             * @throws FileNotFoundException
             */
            public static final String insertImage(ContentResolver cr, String imagePath,
                    String name, String description) throws FileNotFoundException {
                // Check if file exists with a FileInputStream
                FileInputStream stream = new FileInputStream(imagePath);
                try {
                    Bitmap bm = BitmapFactory.decodeFile(imagePath);
                    String ret = insertImage(cr, bm, name, description);
                    bm.recycle();
                    return ret;
                } finally {
                    try {
                        stream.close();
                    } catch (IOException e) {
                    }
                }
            }


啊啊,贴完源码我才发现,这个方法调用了第一个方法,这个name就是上面方法的title,晕死,这下更加郁闷了,反正我设置title无效果,求高手为小弟解答,先不管了,我们继续往下说

上面那段代码插入到系统相册之后还需要发条广播

 代码如下 复制代码

 

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory()))); 


上面那条广播是扫描整个sd卡的广播,如果你sd卡里面东西很多会扫描很久,在扫描当中我们是不能访问sd卡,所以这样子用户体现很不好,用过微信的朋友都知道,微信保存图片到系统相册并没有扫描整个SD卡,所以我们用到下面的方法

 

 代码如下 复制代码

Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);  
 Uri uri = Uri.fromFile(new File("/sdcard/image.jpg"));  
 intent.setData(uri);  
 mContext.sendBroadcast(intent); 


或者用MediaScannerConnection

 

 代码如下 复制代码

 

final MediaScannerConnection msc = new MediaScannerConnection(mContext, new MediaScannerConnectionClient() {  
  public void onMediaScannerConnected() {  
   msc.scanFile("/sdcard/image.jpg", "image/jpeg");  
  }  
  public void onScanCompleted(String path, Uri uri) {  
   Log.v(TAG, "scan completed");  
   msc.disconnect();  
  }  
 });  


也行你会问我,怎么获取到我们刚刚插入的图片的路径?呵呵,这个自有方法获取,insertImage(ContentResolver cr, Bitmap source,String title, String description),这个方法给我们返回的就是插入图片的Uri,我们根据这个Uri就能获取到图片的绝对路径

 

 代码如下 复制代码

private  String getFilePathByContentResolver(Context context, Uri uri) {
  if (null == uri) {
   return null;
  }
        Cursor c = context.getContentResolver().query(uri, null, null, null, null);
        String filePath  = null;
        if (null == c) {
            throw new IllegalArgumentException(
                    "Query on " + uri + " returns null result.");
        }
        try {
            if ((c.getCount() != 1) || !c.moveToFirst()) {
            } else {
             filePath = c.getString(
               c.getColumnIndexOrThrow(MediaColumns.DATA));
            }
        } finally {
            c.close();
        }
        return filePath;
    }

根据上面的那个方法获取到的就是图片的绝对路径

做一个输入框时发现android中ditView的默认焦点了,这种问题如果是在输入框还好,但在搜索页面或浏览页面这样就会影响用户体验了,那要如何取消EditView的默认焦点呢,下面我们来看看。

在网上找了好久,有点 监听软键盘事件,有点 调用 clearFouse()方法,但是测试了都没有! xml中也找不到相应的属性可以关闭这个默认行为

解决之道:在EditText的父级控件中找一个,设置成

 代码如下 复制代码

android:focusable="true"
android:focusableInTouchMode="true"

这样,就把EditText默认的行为截断了!

 代码如下 复制代码

<LinearLayout
style="@style/FillWrapWidgetStyle"
android:orientation="vertical"
android:background="@color/black"
android:gravity="center_horizontal"
android:focusable="true"
android:focusableInTouchMode="true"
>
<ImageView
android:id="@+id/logo"
style="@style/WrapContentWidgetStyle"
android:background="@drawable/dream_dictionary_logo"
/>
<RelativeLayout
style="@style/FillWrapWidgetStyle"
android:background="@drawable/searchbar_bg"
android:gravity="center_vertical"
>
<EditText
android:id="@+id/searchEditText"
style="@style/WrapContentWidgetStyle"
android:background="@null"
android:hint="Search"
android:layout_marginLeft="40dp"
android:singleLine="true"
/>
</RelativeLayout>
</LinearLayout>

查阅了很多资料后,发现以下方法最简单:

在xml中,在EditText控件之前
加入

 代码如下 复制代码

<LinearLayout
    android:id="@+id/linearLayout_focus"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:layout_width="0px"
    android:layout_height="0px"/>

这是一个虚假的LinearLayout,不会显示的,但是会抢走焦点

本文章来给各位同学介绍一个微信开发实现一键拨号出现屏蔽问题的解决方案,如果你碰到此问题不防进入参考一下。

在微信中出现无法拨号的情况,原先操作的时候,的确是OK的,现在微信版本升级了,我试了一下,果然拨号不行了,在首页的web页面中是没有问题的,但是在微信中就是拨打不了,找了很多,后来发现是微信做了屏蔽,解决方法如下:

1、拨号的代码还是不变,和原先的一样,

2、打开拨号页面要做下处理,在网址后面增加一个锚节点mp.weixin.qq.com。

实例如下:

如:<a href="tel:13764567708">移动WEB页面JS一键拨打号码咨询功能</a> 上需要拨号代码,操作如下

在有这个代码的页面URl后边加上“#mp.weixin.qq.com” 如:http://www.111cn.net /#mp.weixin.qq.com


这样,微信里面的一键拨号功能就OK了

本文章来给大家介绍关于Android开发之WebView的使用进阶,希望有兴趣的同学可进入参考,并对你有所帮助哦。

1、当打开WebView所显示网页上的超链接时,会调用系统的浏览器打开,而不是在原先的WebView上显示。
2、当我按下返回键时,并不是返回的上次打开的网页,而是直接退出程序。下面说明如果解决上面的两个问题

在原WebView上显示打开的链接需要自定义一个类,继承自WebViewClient,并设置WebView的WebViewClient即可:

 代码如下 复制代码
class MyWebViewClient extends WebViewClient
{
   public boolean shouldOverrideUrlLoading(WebView view, String url)
   {
       //重写此方法表明点击链接是在当前的webview里跳转,不跳到浏览器那边
       view.loadUrl(url);
       return true;
   }
}
 
webview = (WebView)this.findViewById(R.id.webView);
 
MyWebViewClient mwvc = new MyWebViewClient();
webview.setWebViewClient(mwvc);
 
webview.loadUrl("/index.php");


这样,当点击网页里的超链接时,就会在当前的WebView中显示,而不是打开浏览器去显示该网页。

响应返回键退回上一个网页第一个问题解决了之后,又引发一个新的问题,那就是当点击了好几层链接后,按下返回按钮并不是按预想的那样回退到上一个网页,而是直接退出了程序。

解决这个问题就需要重写onKeyDown方法,当按下返回键时,判断当前打开的网页是不是顶级页面,如果是,则退出Activity,如果不是,则退回上一个页面:

 代码如下 复制代码

String topPage = "/index.php";
public boolean onKeyDown(int keyCode, KeyEvent event)
{
   if ((keyCode == KeyEvent.KEYCODE_BACK))
   {
      String currentUrl = webview.getUrl();
      if(currentUrl.equals(topPage))
      {
          this.finish();
      }
      else
      {
          webview.goBack();
      }
      return true;
   }
   return false;
}

本文章给各位同学介绍一个简单的Android 自定义弹出对话框界面实例,如果你对此有了解不防进入参考。

在安卓开发中,时常遇到要弹窗提醒的情况。而系统自带的弹出对话框由不是很美观,可以通过自己继承对话框类(Dialog),并设置自定义的布局文件,来达到美化弹出式对话框的目的。

首先是自定义一个对话框类,继承自Dialog,然后再构造函数中传入对话框显示内容、按钮响应函数等参数:

 代码如下 复制代码

public UserDefinedDialog(Context context, String message,
                         View.OnClickListener onclicklistener,
                         View.OnClickListener cancelListener)
{
  super(context,R.style.Theme_Dialog);
  this.ctx = context;
  this.msg = message;
  if (onclicklistener != null)
  {
    this.okListener=onclicklistener;
  }
  if(cancelListener != null)
  {
    IsTwoButton=true;
    this.cancelListener=cancelListener;
  }
}

然后,在自定义对话框类的OnCreate函数中,设置对话框的布局,以及显示风格:

 代码如下 复制代码

protected void onCreate(Bundle savedInstanceState)
{
   super.onCreate(savedInstanceState);
 
   requestWindowFeature(Window.FEATURE_NO_TITLE);
   setContentView(R.layout.alertdialog);
 
   tvtitle = (TextView) findViewById(R.id.dialogtitle);
   tvcontent = (TextView) findViewById(R.id.dialogcontent);
 
   btnleft = (Button) findViewById(R.id.btnleft);
   btnright = (Button) findViewById(R.id.btnright);
 
   btnleft.setOnClickListener(this);
   btnright.setOnClickListener(this);
 
   btncenter = (Button) findViewById(R.id.btncenter);
   btncenter.setOnClickListener(this);
   if(IsTwoButton)
   {
     btnleft.setVisibility(View.VISIBLE);
     btnright.setVisibility(View.VISIBLE);
     btncenter.setVisibility(View.GONE);
   }
   tvtitle.setText("提示");
   tvcontent.setText(msg);
 
   WindowManager m;
   m = (WindowManager)ctx.getSystemService(Context.WINDOW_SERVICE);
   Display d = m.getDefaultDisplay();
   LayoutParams p = getWindow().getAttributes();
   //设置对话框宽高
   p.height = (int) (d.getHeight() * 0.3);
   p.width = (int) (d.getWidth() * 0.9);
   //设置对话框透明度
   p.alpha = 0.8f;
   //让背景变黑
   p.dimAmount = 0.7f;
   getWindow().setAttributes(p);
   getWindow().setGravity(Gravity.CENTER);
}

另外,自定义的对话框类UserDefinedDialog同时实现了OnClickListener接口,用于实现对点击对话框上按钮的响应,在响应函数中,会判断在构造该类的时候是否传入了相应的响应函数,并交由该函数处理:

 代码如下 复制代码

public void onClick(View v)
{
  switch (v.getId())
  {
    case R.id.btnleft:
        if(cancelListener != null){
           cancelListener.onClick(v);
        }
        break;
    case R.id.btncenter:
        if(okListener != null){
           okListener.onClick(v);
        }
        break;
    case R.id.btnright:
        if(okListener != null){
           okListener.onClick(v);
        }
        break;
  }
  this.cancel();
}

最后,调用的时候非常简单:

 代码如下 复制代码

new UserDefinedDialog(this,
                     "我是一个按钮的对话框,默认效果取消",
                     null, null).show();
 
new UserDefinedDialog(this, "我是两个按钮的对话框",
    new OnClickListener() {
        public void onClick(View v) {
              //dosomething
        }
    },
    new OnClickListener() {
        public void onClick(View v) {
              //dosomething}
    }).show();

美化之后的对话框如下图所示:

自定义对话框-单个按钮

[!--infotagslink--]

相关文章

  • php 中file_get_contents超时问题的解决方法

    file_get_contents超时我知道最多的原因就是你机器访问远程机器过慢,导致php脚本超时了,但也有其它很多原因,下面我来总结file_get_contents超时问题的解决方法总结。...2016-11-25
  • HTTP 408错误是什么 HTTP 408错误解决方法

    相信很多站长都遇到过这样一个问题,访问页面时出现408错误,下面一聚教程网将为大家介绍408错误出现的原因以及408错误的解决办法。 HTTP 408错误出现原因: HTT...2017-01-22
  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • PHP 验证码不显示只有一个小红叉的解决方法

    最近想自学PHP ,做了个验证码,但不知道怎么搞的,总出现一个如下图的小红叉,但验证码就是显示不出来,原因如下 未修改之前,出现如下错误; (1)修改步骤如下,原因如下,原因是apache权限没开, (2)点击打开php.int., 搜索extension=ph...2013-10-04
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 安卓手机wifi打不开修复教程,安卓手机wifi打不开解决方法

    手机wifi打不开?让小编来告诉你如何解决。还不知道的朋友快来看看。 手机wifi是现在生活中最常用的手机功能,但是遇到手机wifi打不开的情况该怎么办呢?如果手机wifi...2016-12-21
  • 连接MySql速度慢的解决方法(skip-name-resolve)

    最近在Linux服务器上安装MySql5后,本地使用客户端连MySql速度超慢,本地程序连接也超慢。 解决方法:在配置文件my.cnf的[mysqld]下加入skip-name-resolve。原因是默认安装的MySql开启了DNS的反向解析。如果禁用的话就不能...2015-10-21
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • Android用MemoryFile文件类读写进行性能优化

    java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
  • Android设置TextView竖着显示实例

    TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
  • 总结android studio注意事项及打不开等问题解决方法

    经过一段时间的使用,总结了android studio打不开等问题的6种解决方法及android studio注意事项,希望对大家有所帮助。 1 首次运行,建立好项目需要下载一些东西,如果...2016-09-20
  • MySQL ERROR 2013 (HY000)错误解决方法

    当通过 TCP/IP 连接 MySQL 远程主机时,出现 ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 104 。如果是在linux shell命令行中直接打 mysql 命令,...2015-03-15
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • IE6-IE9中tbody的innerHTML不能赋值的解决方法

    IE6-IE9中tbody的innerHTML不能赋值,重现代码如下 复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>IE6-IE9中tbody的innerHTML不能复制bug</title> </head> <body style="height:3...2014-06-07
  • Mysql修改datadir导致无法启动问题解决方法

    centos6.2,停止mysqld然后修改/etc/my.cnf datadir的位置,启动mysqld提示FAILED,查看日志 复制代码 代码如下: 120609 11:31:31 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended 120609 11:35:12 my...2015-03-15