【问题标题】:Can I force my application to launch the default Camera rather than offering the 'Complete action using' list?我可以强制我的应用程序启动默认相机,而不是提供“使用完成操作”列表吗?
【发布时间】:2011-11-25 09:08:45
【问题描述】:

我正在使用意图 new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 来捕获图像以在我的应用程序中使用。我的设备上安装了两个可以执行此功能的应用程序,但希望我的应用程序仅使用默认相机。

有没有办法做到这一点?

【问题讨论】:

    标签: android camera android-intent


    【解决方案1】:

    正如 Dr_sulli 建议的那样,我只是将其转换为代码,它对我很有效,如果情况下访问直接相机应用程序,其他部分是允许用户选择其他相机应用程序以及系统相机。

    protected static final int CAMERA_ACTIVITY = 100;
    
    Intent mIntent = null;
            if(isPackageExists("com.google.android.camera")){
                mIntent= new Intent();
                mIntent.setPackage("com.google.android.camera");
                mIntent.setAction(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                mIntent.putExtra("output", Uri.fromFile(new File(Environment
                        .getExternalStorageDirectory(), "/myImage" + ".jpg")));
            }else{
            mIntent = new Intent(
                    android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            mIntent.putExtra("output", Uri.fromFile(new File(Environment
                    .getExternalStorageDirectory(), "/myImage" + ".jpg")));
    
            Log.i("in onMenuItemSelected",
                    "Result code = "
                            + Environment.getExternalStorageDirectory());
            }
            startActivityForResult(mIntent, CAMERA_ACTIVITY);
    

    在 onActivityResult 里面做你的事情

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        Log.i("in onActivityResult", "Result code = " + resultCode);
        if (resultCode == -1) {
            switch (requestCode) {
            case CAMERA_ACTIVITY:
                //do your stuff here, i am just calling the path of stored image
                String filePath = Environment.getExternalStorageDirectory()
                        + "/myImage" + ".jpg";
                        }
                         }
                     }
    

    isPackageExists 将确认包是否存在。

    public boolean isPackageExists(String targetPackage){
        List<ApplicationInfo> packages;
        PackageManager pm;
            pm = getPackageManager();        
            packages = pm.getInstalledApplications(0);
            for (ApplicationInfo packageInfo : packages) {
        if(packageInfo.packageName.equals(targetPackage)) return true;
        }        
        return false;
    }
    

    或者你可以用我的方式更容易做到这一点,这将过滤所有系统应用程序,然后你比较名称,因此它适用于所有手机,但由于硬编码,上述技术不适用于每部手机。稍后您可以使用此包名称启动相机活动,如上所述。

    PackageManager pm = this.getPackageManager();
    
        List<ApplicationInfo> list = getPackageManager().getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
        for (int n=0;n<list.size();n++) {
            if((list.get(n).flags & ApplicationInfo.FLAG_SYSTEM)==1)
            {
                Log.d("Installed Applications", list.get(n).loadLabel(pm).toString());
                Log.d("package name", list.get(n).packageName);
                if(list.get(n).loadLabel(pm).toString().equalsIgnoreCase("Camera"))
                    break;
            }
        }
    

    【讨论】:

    • 上述OR you can do it in my way its much easier 是否总是会在所有设备上返回正确的默认相机应用程序包名称?目前你在list.get(n).loadLabel(pm).toString().equalsIgnoreCase("Camera") 时打破循环,所有设备都会这样吗?
    • 不,这不起作用,一旦我更新了我的应用程序,我就开始看到崩溃
    【解决方案2】:
        List<ApplicationInfo> list = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
        for (int n=0;n<list.size();n++) {
            if((list.get(n).flags & ApplicationInfo.FLAG_SYSTEM)==1)
            {
                Log.d("TAG", "Installed Applications  : " + list.get(n).loadLabel(packageManager).toString());
                Log.d("TAG", "package name  : " + list.get(n).packageName);
                if(list.get(n).loadLabel(packageManager).toString().equalsIgnoreCase("Camera")) {
                    defaultCameraPackage = list.get(n).packageName;
                    break;
                }
            }
        }
    

    我发现以下解决方案及其完美运行。

    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePictureIntent.setPackage(defaultCameraPackage); 
    startActivityForResult(takePictureIntent, actionCode);
    

    您可以通过在上述意图中设置包来过滤默认相机。我通过安装两个应用程序 Line CameraPaper Camera 对其进行了测试,这两个应用程序都显示选择器,但过滤打包上面的代码只打开默认摄像头。

    【讨论】:

      【解决方案3】:

      我准备了一个几乎适用于所有解决方案的解决方案:

        private void openCamera() {
              String systemCamera;
              if (isPackageExists("com.google.android.camera")) {
                  systemCamera = "com.google.android.camera";
              } else {
                  systemCamera = findSystemCamera();
              }
      
              if (systemCamera != null) {
                  Log.d(TAG, "System Camera: " + systemCamera);
                  Intent mIntent = new Intent();
                  mIntent.setPackage(systemCamera);
                  File f = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), ("IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg"));
                  mIntent.setAction(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                  mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                  startActivityForResult(mIntent, IMAGE_CODE_PICKER);
              } else {
                  //Unable to find default camera app 
              }
          }
      
          @Override
          public void onActivityResult(int requestCode, int resultCode, Intent data) {
              super.onActivityResult(requestCode, resultCode, data);
              if (requestCode == IMAGE_CODE_PICKER && resultCode == RESULT_OK) {
      
              }
          }
      
          private boolean isPackageExists(String targetPackage) {
              List<ApplicationInfo> packages;
              PackageManager pm;
              pm = getPackageManager();
              packages = pm.getInstalledApplications(0);
              for (ApplicationInfo packageInfo : packages) {
                  if (packageInfo.packageName.equals(targetPackage)) {
                      return true;
                  }
              }
              return false;
          }
      
          private String findSystemCamera() {
              Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
              PackageManager packageManager = this.getPackageManager();
              List<ResolveInfo> listCam = packageManager.queryIntentActivities(intent, 0);
              for (ResolveInfo info :
                      listCam) {
                  if (isSystemApp(info.activityInfo.packageName)) {
                      return info.activityInfo.packageName;
                  }
              }
              return null;
          }
      
      
          boolean isSystemApp(String packageName) {
              ApplicationInfo ai;
              try {
                  ai = this.getPackageManager().getApplicationInfo(packageName, 0);
              } catch (PackageManager.NameNotFoundException e) {
                  e.printStackTrace();
                  return false;
              }
              int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
              return (ai.flags & mask) != 0;
          }
      

      您可能需要在 onCreate 方法中添加以下代码:

      StrictMode.VmPolicy.Builder newbuilder = new StrictMode.VmPolicy.Builder();
      StrictMode.setVmPolicy(newbuilder.build());
      

      【讨论】:

      • 您能否确认findSystemCamera() 将始终返回设备的默认相机应用程序,无论设备如何?
      • 不,这不起作用,一旦我更新了我的应用程序,我就开始看到崩溃
      【解决方案4】:

      我不确定您要实现的目标是否可以在所有设备上移植。 Android 的目标之一是允许轻松替换服务请求的活动,例如图像捕获。话虽如此,如果您只想为您的设备执行此操作,您可以简单地将意图中的组件名称设置为媒体捕获活动的名称。

      【讨论】:

      • 在这里添加一点,除了调用 setComponent 之外,你不会以任何方式改变你已经拥有的意图
      • 谢谢贾斯汀。我想我可以检查默认系统摄像头 (com.google.android.camera) 的组件名称,如果存在,则使用 setComponent 方法,否则请使用通常的方法。
      【解决方案5】:

      默认的相机应用是第一个安装的应用。因此,camlist 中的第一个元素是默认应用程序

          Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
          PackageManager packageManager = MapsActivity.this.getPackageManager();
          List<ResolveInfo> listCam = packageManager.queryIntentActivities(intent, 0);
          intent.setPackage(listCam.get(0).activityInfo.packageName);
          startActivityForResult(intent,INTENT_REQUESTCODE1);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-12
        • 2013-09-07
        • 2020-07-17
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 2010-12-13
        相关资源
        最近更新 更多