Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/194.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android 7中,ContentResolver';方法openAssetFileDescriptor(vCardUri,“r”quot;)返回声明长度为-1的AssetFileDescriptor_Android_Android Contacts_Android Contentresolver_Vcf Vcard_Android 7.0 Nougat - Fatal编程技术网

在Android 7中,ContentResolver';方法openAssetFileDescriptor(vCardUri,“r”quot;)返回声明长度为-1的AssetFileDescriptor

在Android 7中,ContentResolver';方法openAssetFileDescriptor(vCardUri,“r”quot;)返回声明长度为-1的AssetFileDescriptor,android,android-contacts,android-contentresolver,vcf-vcard,android-7.0-nougat,Android,Android Contacts,Android Contentresolver,Vcf Vcard,Android 7.0 Nougat,在Android 7中,getContentResolver().openAssetFileDescriptor(vCardUri,“r”)返回AssetFileDescriptor的declaredLength为-1,由getDeclaredLength()返回 AssetFileDescriptor assetFileDescriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r"); FileInputS

在Android 7中,
getContentResolver().openAssetFileDescriptor(vCardUri,“r”)
返回
AssetFileDescriptor
的declaredLength为-1,由
getDeclaredLength()返回

AssetFileDescriptor assetFileDescriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
FileInputStream fis = assetFileDescriptor.createInputStream();
byte[] buf = new byte[(int) assetFileDescriptor.getDeclaredLength()];
正在尝试将联系人作为vCard导出到vcf文件中。我试过的代码如下

Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
AssetFileDescriptor fd = resolver.openAssetFileDescriptor(uri, "r");
FileInputStream fis = fd.createInputStream();
byte[] b = new byte[(int)fd.getDeclaredLength()];
fis.read(b);
AssetFileDescriptor assetFileDescriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
FileInputStream fis = assetFileDescriptor.createInputStream();
byte[] buf = new byte[(int) assetFileDescriptor.getDeclaredLength()];
上面的代码在Android 6或更低版本中运行得非常好。但是当使用Android 7运行时,创建字节[]的行会导致
NegativeByteArraySizeException
,因为declaredLength为-1。 当我调试下载安卓7的源代码时,我发现了这个问题。
任何一种健康都是非常可观的。

在@pskink的帮助下,我发现以下方法可以解决我的问题

String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
        Uri vCardUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
        AssetFileDescriptor assetFileDescriptor;
        FileInputStream inputStream;
        try {
            assetFileDescriptor = getActivity().getContentResolver().openAssetFileDescriptor(vCardUri, "r");
            if (assetFileDescriptor != null) {
                inputStream = assetFileDescriptor.createInputStream();
                return readAsByteArray(inputStream);
            }
        } 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);
        }
AssetFileDescriptor assetFileDescriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
FileInputStream fis = assetFileDescriptor.createInputStream();
byte[] buf = new byte[(int) assetFileDescriptor.getDeclaredLength()];
其中readAsByteArray()是使用中的代码编写的

AssetFileDescriptor assetFileDescriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
FileInputStream fis = assetFileDescriptor.createInputStream();
byte[] buf = new byte[(int) assetFileDescriptor.getDeclaredLength()];

谢谢@pskink

在您的代码中,您使用的是OpenAssetFileDescriptor,而不是openFileDescriptor,因为OpenAssetFileDescriptor用于读取资产文件夹中的文件,而不是文件Uri

    package com.daffo.stackoverflowtest;

    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.content.res.AssetFileDescriptor;
    import android.content.res.AssetManager;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.os.ParcelFileDescriptor;
    import android.provider.ContactsContract;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.Toast;

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.nio.channels.FileChannel;
    import java.util.ArrayList;
    import java.util.List;

public class MainActivity extends AppCompatActivity {
    Cursor cursor;
    ArrayList<String> vCard;
    String vfile;
    private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;

/**
 * Called when the activity is first created.
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    vfile = "Contacts" + "_" + System.currentTimeMillis() + ".vcf";
    /**This Function For Vcard And here i take one Array List in Which i store every Vcard String of Every Conatact
     * Here i take one Cursor and this cursor is not null and its count>0 than i repeat one loop up to cursor.getcount() means Up to number of phone contacts.
     * And in Every Loop i can make vcard string and store in Array list which i declared as a Global.
     * And in Every Loop i move cursor next and print log in logcat.
     * */
    addContactPermissions();

}

/**
 * Show the contacts in the ListView.
 */
private void addContactPermissions() {
    // Check the SDK version and whether the permission is already granted or not.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
        requestPermissions(new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_READ_CONTACTS);
        //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
    } else {
        // Android version is lesser than 6.0 or the permission is already granted.
        getVcardString();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission is granted
            getVcardString();
        } else {
            Toast.makeText(this, "Until you grant the permission, we canot display the names", Toast.LENGTH_SHORT).show();
        }
    }
}

private void getVcardString() {
    // TODO Auto-generated method stub
    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);
            if (vCard.size() > 0) {
                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) {


    //cursor.moveToFirst();
    String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
    Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
    ParcelFileDescriptor fd;
    try {

        fd = this.getContentResolver().openFileDescriptor(uri, "r");
        // Your Complex Code and you used function without loop so how can you get all Contacts Vcard.??


       /* FileInputStream fis = fd.createInputStream();
        byte[] buf = new byte[(int) fd.getDeclaredLength()];
        fis.read(buf);
        String VCard = new String(buf);
        String path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
        FileOutputStream out = new FileOutputStream(path);
        out.write(VCard.toString().getBytes());
        Log.d("Vcard",  VCard);*/

        FileInputStream fis = new FileInputStream(fd.getFileDescriptor());
        byte[] buf = new byte[fis.available()];
        fis.read(buf);
        String vcardstring = new String(buf);
        vCard.add(vcardstring);

        String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
        FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false);
        mFileOutputStream.write(vcardstring.toString().getBytes());
    } catch (Exception e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}
}
AssetFileDescriptor assetFileDescriptor = activity.getContentResolver().openAssetFileDescriptor(uri, "r");
FileInputStream fis = assetFileDescriptor.createInputStream();
byte[] buf = new byte[(int) assetFileDescriptor.getDeclaredLength()];
package com.daffo.stackoverflowtest;
导入android.Manifest;
导入android.content.pm.PackageManager;
导入android.content.res.AssetFileDescriptor;
导入android.content.res.AssetManager;
导入android.database.Cursor;
导入android.net.Uri;
导入android.os.Build;
导入android.os.Environment;
导入android.os.ParcelFileDescriptor;
导入android.provider.contacts合同;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入android.util.Log;
导入android.widget.Toast;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
导入java.nio.channels.FileChannel;
导入java.util.ArrayList;
导入java.util.List;
公共类MainActivity扩展了AppCompatActivity{
光标;
ArrayList vCard;
字符串vfile;
私有静态最终整数权限\请求\读取\联系人=100;
/**
*在首次创建活动时调用。
*/
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vfile=“Contacts”+“\u”+System.currentTimeMillis()+”.vcf”;
/**此函数用于Vcard,这里我使用一个数组列表,其中存储每个Conatact的每个Vcard字符串
*这里我取一个游标,这个游标不是空的,它的计数>0,然后我重复一个循环到游标。getcount()表示最多有多少个电话联系人。
*在每个循环中,我可以生成vcard字符串并存储在数组列表中,我将其声明为全局数组。
*在每个循环中,我移动光标,然后在logcat中打印日志。
* */
addContactPermissions();
}
/**
*在列表视图中显示联系人。
*/
私有void addContactPermissions(){
//检查SDK版本以及权限是否已授予。
if(Build.VERSION.SDK_INT>=Build.VERSION_code.M&&(checkSelfPermission(Manifest.permission.READ_CONTACTS)!=PackageManager.permission| | checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.permission|{
requestPermissions(新字符串[]{Manifest.permission.READ_CONTACTS,Manifest.permission.WRITE_EXTERNAL_STORAGE},PERMISSIONS_REQUEST_READ_CONTACTS);
//在此之后,您将等待onRequestPermissionsResult(int,String[],int[])重写方法中的回调
}否则{
//Android版本低于6.0或已授予权限。
getVcardString();
}
}
@凌驾
public void onRequestPermissionsResult(int-requestCode,字符串[]权限,
int[]格兰特结果){
if(requestCode==权限\请求\读取\联系人){
if(grantResults[0]==已授予PackageManager.权限){
//许可被授予
getVcardString();
}否则{
Toast.makeText(这是“在您授予许可之前,我们不能显示名称”,Toast.LENGTH_SHORT.show();
}
}
}
私有void getVcardString(){
//TODO自动生成的方法存根
vCard=新的ArrayList();
cursor=getContentResolver().query(ContactsContract.CommonDataTypes.Phone.CONTENT\u URI,null,null,null);
if(cursor!=null&&cursor.getCount()>0){
cursor.moveToFirst();
对于(int i=0;i0){
Log.d(“TAG”,“Contact”+(i+1)+“VcF字符串是”+vCard.get(i));
}
cursor.moveToNext();
}
}否则{
Log.d(“标签”,“手机中没有联系人”);
}
}
公共void get(光标){
//cursor.moveToFirst();
String lookupKey=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri=Uri.withAppendedPath(ContactsContract.Contacts.CONTENT\u VCARD\u Uri,查找键);
帕塞尔菲勒;
试一试{
fd=this.getContentResolver().openFileDescriptor(uri,“r”);
//你的复杂代码和你使用的函数没有循环,那么你怎么能得到所有的联系人Vcard。??
/*FileInputStream fis=fd.createInputStream();
字节[]buf=新字节[(int)fd.getDeclaredLength()];
财政司司长(财政司司长);
字符串VCard=新字符串(buf);
字符串路径=Environment.getExternalStorageDirectory().toString()+File.separator+vfile;
FileOutputStream out=新的FileOutputStream(路径);
out.write(VCard.toString().getBytes());
Log.d(“Vcard”,Vcard)*/
FileInputStream fis=新的FileInputStream(fd.getFileDescriptor());
字节[]buf=新字节[fis.available()];
财政司司长(财政司司长);
字符串vcardstring=新字符串(buf);
添加(vcardstring);
字符串存储\u path=Environment.getExternalStorageDire