2017-07-17 44 views
0

由于我是Java新手,我自己创建了这些代码,并从其他来源获取了一些部分。我想将所有联系人信息备份到主存储或SD卡中的.vcf文件中(无所谓),最后将其恢复。但在这个代码,你只能看到备份的部分:将联系人备份到.VCF文件不起作用

public class MainActivity extends Activity 
{ 
    Cursor cursor; 
    ArrayList<String> vCard ; 
    String vfile; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     vfile = "Contacts" + "_" + System.currentTimeMillis()+".vcf"; 
     getVcardString(); 

    } 
    private void getVcardString() { 
     vCard = new ArrayList<String>(); 
     cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); 
     if(cursor!=null&&cursor.getCount()>0) 
     { 
      cursor.moveToFirst(); 
      for(int i =0;i<cursor.getCount();i++) 
      { 

       get(cursor); 
       Log.d("TAG", "Contact "+(i+1)+"VcF String is"+vCard.get(i)); 
       cursor.moveToNext(); 
      } 

     } 
     else 
     { 
      Log.d("TAG", "No Contacts in Your Phone"); 
     } 

    } 

    public void get(Cursor cursor) 
    { 

     String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); 
     Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey); 
     AssetFileDescriptor fd; 
     try { 
      fd = this.getContentResolver().openAssetFileDescriptor(uri, "r"); 

      FileInputStream fis = fd.createInputStream(); 
      byte[] buf = new byte[(int) fd.getDeclaredLength()]; 
      fis.read(buf); 
      String vcardstring= new String(buf); 
      vCard.add(vcardstring); 

      String storage_path = Environment.getRootDirectory().toString() + File.separator + vfile; 
      FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false); 
      mFileOutputStream.write(vcardstring.toString().getBytes()); 

     } catch (Exception e1) 
     { 
      e1.printStackTrace(); 
     } 
    } 

}

问题是代码不工作,没有得到异常或任何错误。我搜索了根目录和所有文件夹,但没有.vcf文件。我的权限是:<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> 我在API 17和24上运行了这个任何想法,为什么它不起作用?

+0

要获得SD卡路径,您必须使用Environment.getExternalStorageDirectory() Environment.getRootDirectory()返回设备根目录“/” - 您无法在此目录中写入(或读取)非根-设备。 –

+0

你还采用了写入外部存储权限吗?

+0

@kapsym嗯,我不知道我应该使用该权限,但我的优先级是将该文件保存在设备的存储中。如果Environment.getRootDirectory()不起作用,那么我应该如何将它保存在设备内存上? (不是外部存储器) – Magasvazn

回答

0

公共无效shoro(视图V)抛出IOException异常{

Toast.makeText(this,"ok2",Toast.LENGTH_SHORT).show(); 
    vfile = "Contacts" + "_" + System.currentTimeMillis()+".vcf"; 
    vCard = new ArrayList<String>(); 
    cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); 
    if(cursor!=null&&cursor.getCount()>0) 
    { 
     Toast.makeText(this,"ok3",Toast.LENGTH_SHORT).show(); 
     cursor.moveToFirst(); 
     for(int i =0;i<cursor.getCount();i++) 
     { 

      get(cursor); 
      Log.d("TAG", "Contact "+(i+1)+"VcF String is"+vCard.get(i)); 
      cursor.moveToNext(); 
     } 

    } 
    else 
    { 
     Log.d("TAG", "No Contacts in Your Phone"); 
    } 

} 

public void get(Cursor cursor) throws IOException { 
    Toast.makeText(this,"ok4",Toast.LENGTH_SHORT).show(); 

    String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); 
    Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey); 
    AssetFileDescriptor fd; 

    fd = this.getContentResolver().openAssetFileDescriptor(uri, "r"); 

    FileInputStream fis = fd.createInputStream(); 
    byte[] buf = new byte[(int) fd.getDeclaredLength()]; 
    fis.read(buf); 
    String vcardstring= new String(buf); 
    vCard.add(vcardstring); 

    String storage_path = Environment.getDataDirectory().toString() + File.separator + vfile; 
    FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false); 
    mFileOutputStream.write(vcardstring.toString().getBytes()); 


} 

首先看看那些敬酒,我把他们找出来,直到其中一线应用不胜枚举。奇怪的是,我第一次问这些问题,我忘了给我的联系人添加电话号码(我有3个联系人进行测试),当我运行应用程序(当我没有添加号码时),该应用程序没有任何错误,但没有(我们以前的谈话是关于这个的,我的错:D)。然后当我检查吐司,我发现该应用程序永远不会达到“OK3”吐司。之后,当我给联系人添加号码时,现在应用程序甚至无法运行。当我按下按钮,它崩溃和close.i把线从运行在一个记事本是在下面的链接(API 17):

https://ufile.io/i3gu4

我测试此上API 24和21也但同样的问题。可能是什么问题呢?

+0

@ Magasvazn我能够找出问题。看到更新的答案 –

0

public void terp(View v)throws IOException Toast.makeText(this,“ok”,Toast.LENGTH_SHORT).show();

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(this,new String[]{ Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS }, 12345); 
    } else { 
     // WE ALREADY HAVE PERMISSION, RUN THE MAIN FUNCTION 
     shoro(); 
    } 

} 


public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
    Toast.makeText(this,"salam1",Toast.LENGTH_SHORT).show(); 
    if ((requestCode == 12345) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { 
     Toast.makeText(this,"salam2",Toast.LENGTH_SHORT).show(); 
     // WE GOT THE PERMISSION, RUN THE MAIN FUNCTION 
     try { 
      shoro(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

shoro()是主要功能。

0

Android不允许您在环境中创建文件Environment.getDataDirectoy()。这指向系统使用的/ data文件夹。如果你想使用内部存储,你可以使用/ data/data/your_app_package存储。要访问此你只需更改1线你的代码 -

String storage_path = getFilesDir().getAbsolutePath() + File.separator + vfile; 

要验证你的文件被创建,你可以做以下步骤

  1. 打开Android设备监视器从工具 - > Android - > Android设备监视器
  2. 在左侧的设备选项卡中选择模拟器。
  3. 选择右侧部分的文件资源管理器选项卡
  4. 转到/ data/data/YOUR_PACKAGE_NAME文件夹。里面你会看到如果你想使用外部存储使用Environment.getExternalStorageDirectory()方法您的文件将被创建

文件部分。

要了解Android设备的不同路径,看看here

更新1 后这里讨论的是更新的代码。有多个问题 - 1)我们需要接受多个权限并满足所有这些API> = 23 2)AssetFileDescriptor给出的长度为-1,API> = 24 因此代码被破坏。

因此改变在2个地方 - 改变你的get方法 -

public void get(Cursor cursor) throws IOException { 
    Toast.makeText(this,"ok4",Toast.LENGTH_SHORT).show(); 

    String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); 
    Uri vCardUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey); 
    AssetFileDescriptor assetFileDescriptor; 
    String vcardstring=""; 
    if (Build.VERSION.SDK_INT >= 24) { 

     FileInputStream inputStream=null; 
     byte[] buffer = new byte[4096]; 
     ByteArrayOutputStream ous = null; 
     try { 
      assetFileDescriptor = this.getContentResolver().openAssetFileDescriptor(vCardUri, "r"); 

      if (assetFileDescriptor != null) { 
       ous = new ByteArrayOutputStream(); 
       int read = 0; 
       inputStream = assetFileDescriptor.createInputStream(); 
       while ((read = inputStream.read(buffer)) != -1) { 
        ous.write(buffer, 0, read); 
       } 
      } 
     } catch (FileNotFoundException e) { 
      Log.e(TAG, "Vcard for the contact " + lookupKey + " not found", e); 
     } catch (IOException e) { 
      Log.e(TAG, "Problem creating stream from the assetFileDescriptor.", e); 
     }finally { 
      try { 
       if (ous != null) 
        ous.close(); 
      } catch (IOException e) { 
      } 

      try { 
       if (inputStream != null) 
        inputStream.close(); 
      } catch (IOException e) { 
      } 
     } 
     vcardstring= new String(ous.toByteArray()); 

    }else{ 

     assetFileDescriptor = this.getContentResolver().openAssetFileDescriptor(vCardUri, "r"); 

     FileInputStream fis = assetFileDescriptor.createInputStream(); 
     byte[] buf = new byte[(int) assetFileDescriptor.getDeclaredLength()]; 
     fis.read(buf); 
     vcardstring= new String(buf); 

    } 


    vCard.add(vcardstring); 
    Log.i("File Kapil", "path "+getFilesDir().getAbsolutePath().toString()); 
    String storage_path = getFilesDir().getAbsolutePath() + File.separator + vfile; 
    FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false); 
    mFileOutputStream.write(vcardstring.toString().getBytes()); 

} 

而对于请求允许变化 -

public boolean isStoragePermissionGranted() { 
    if (Build.VERSION.SDK_INT >= 23) { 

     if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) 
       == PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.WRITE_CONTACTS) 
       == PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.READ_CONTACTS) 
       == PackageManager.PERMISSION_GRANTED) { 
      Log.v(TAG,"Permission is granted"); 
      return true; 
     } else { 

      Log.v(TAG,"Permission is revoked"); 
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS}, 1); 
      return false; 
     } 
    } 
    else { //permission is automatically granted on sdk<23 upon installation 
     Log.v(TAG,"Permission is granted"); 
     return true; 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { 
    switch (requestCode) { 
     case 0: 
      boolean isPerpermissionForAllGranted = false; 
      if (grantResults.length > 0 && permissions.length==grantResults.length) { 
       for (int i = 0; i < permissions.length; i++){ 
        if (grantResults[i] == PackageManager.PERMISSION_GRANTED){ 
         isPerpermissionForAllGranted=true; 
        }else{ 
         isPerpermissionForAllGranted=false; 
        } 
       } 

       Log.e("value", "Permission Granted, Now you can use local drive ."); 
      } else { 
       isPerpermissionForAllGranted=true; 
       Log.e("value", "Permission Denied, You cannot use local drive ."); 
      } 
      if(isPerpermissionForAllGranted){ 
       shoro(); 
      } 
      break; 
    } 
} 

而在你Shoro方法修改代码以位

public void shoro(){ 
    boolean isPermissionGiven = isStoragePermissionGranted(); 
    Toast.makeText(this,"ok2",Toast.LENGTH_SHORT).show(); 
    if (isPermissionGiven){ 
     // Do stuff 
    } 
} 

完整的代码可以发现 - Here

+0

谢谢你,这个问题似乎只解决了不需要权限的API(我认为这个问题比22岁早了),在新的API上的应用程序再次崩溃,在运行部分出现这个错误:'java.lang.RuntimeException:Failure将结果ResultInfo {who = @ android:requestPermissions :, request = 12345,result = -1,data = Intent {act = android.content.pm.action.REQUEST_PERMISSIONS(has extras)}}传递给activity {com.example.k .backup2/com.example.k.backup2.MainActivity}:java.lang.NegativeArraySizeException:-1' – Magasvazn

+0

另外我改变了下面的代码的第四行到这个:'ActivityCompat.requestPermissions(this,new String [] {Manifest .permission.READ_CONTACTS,Manifest.permission.WRITE_CONTACTS,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},12345); “ '没有再次工作。也许我错了,但是idk现在该怎么做。顺便说一句,应用程序工作正常其他API(不需要权限),我可以看到.vcf文件,如你所说。 – Magasvazn

+0

我正在寻找更高的API版本。给我15分钟 –

相关问题