将联系人备份到.VCF文件不起作用

时间:2017-07-17 14:15:29

标签: android backup contact

作为我刚接触Java的人,我自己制作了这些代码,并从其他来源学到了一些部分。我想将所有联系人信息备份到主存储器或SD卡中的.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上运行了这个。任何想法为什么它不起作用?

3 个答案:

答案 0 :(得分:0)

public void shoro(View 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());


}

首先看看那些Toasts,我让他们找出应用程序继续前行。很奇怪第一次,我问这些问题,我忘了给我的联系人添加电话号码(我有3个联系人进行测试),当我运行应用程序时(当我没有添加号码)时,应用程序继续运行,没有任何错误,但是没有工作(我们之前的谈话是关于这个,我的错:D)。然后,当我检查Toasts时,我发现该应用程序永远不会到达&#34; ok3&#34;吐司。之后,当我向联系人添加号码时,现在应用程序甚至无法运行。当我按下按钮时,它会崩溃并关闭。我将运行中的线条放在下面链接的记事本中(API 17):

https://ufile.io/i3gu4

我在API 24和21上测试了这个,但同样的问题。可能是什么问题?

答案 1 :(得分:0)

public void terp(View v)抛出IOException {         Toast.makeText(此, “OK”,Toast.LENGTH_SHORT).show();

DB::table('users')->select('FirstName')->get();

shoro()是主要功能。

答案 2 :(得分:0)

Android不允许您在 Environment.getDataDirectoy()中创建文件。这指向/ data文件夹,供系统使用。如果要使用内部存储,可以使用/ data / data / your_app_package存储。要获得访问权限,您只需更改代码的一行 -

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

要验证您的文件是否已创建,您可以执行以下步骤

  1. 从工具中打开Android设备监视器 - &gt; Android - &gt; Android设备监视器
  2. 在左侧的“设备”标签中选择模拟器。
  3. 选择右侧部分的“文件资源管理器”选项卡
  4. 转到/ data / data / YOUR_PACKAGE_NAME文件夹。在其中,您将看到将在其中创建文件的“文件”部分
  5. 如果要使用外部存储,请使用 Environment.getExternalStorageDirectory()方法。

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

    更新1 讨论后,这里是更新的代码。有多个问题 - 1)我们需要接受多个权限,并为API&gt; = 23满足所有权限 2)AssetFileDescriptor为API提供长度为-1&gt; = 24 因此代码破灭了。

    所以在2个地方改变 - 改变你的获取方法 -

     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