2017-07-17 75 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分鐘 –

相關問題