Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.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 如何在我的资产中为SearchManager.SUGGEST\u COLUMN\u ICON\u 1 COLUMN工作的图像获取Uri?_Android_Search - Fatal编程技术网

Android 如何在我的资产中为SearchManager.SUGGEST\u COLUMN\u ICON\u 1 COLUMN工作的图像获取Uri?

Android 如何在我的资产中为SearchManager.SUGGEST\u COLUMN\u ICON\u 1 COLUMN工作的图像获取Uri?,android,search,Android,Search,我已经成功地将我的应用程序的国家搜索集成到全球搜索设施中,现在我正试图在搜索建议旁边显示每个国家的国旗。在我的应用程序中搜索是这样工作的,但当然我自己可以控制列表和它的视图绑定。所以我知道这些标志都在那里,我可以在我的应用程序的其余部分使用它们 当我试图为我的资产中的.gif文件提供Uri时,麻烦就来了。根据搜索文档,带有键的列的值SearchManager.SUGGEST\u column\u ICON\u 1应该是图像的Uri 下面是代码的样子。为了响应ContentProvider方法公共

我已经成功地将我的应用程序的国家搜索集成到全球搜索设施中,现在我正试图在搜索建议旁边显示每个国家的国旗。在我的应用程序中搜索是这样工作的,但当然我自己可以控制列表和它的视图绑定。所以我知道这些标志都在那里,我可以在我的应用程序的其余部分使用它们

当我试图为我的资产中的.gif文件提供Uri时,麻烦就来了。根据搜索文档,带有键的列的值
SearchManager.SUGGEST\u column\u ICON\u 1
应该是图像的Uri

下面是代码的样子。为了响应
ContentProvider
方法
公共游标查询(Uri Uri、字符串[]投影、字符串选择、字符串[]selectionArgs、字符串排序器)
我正在创建一个
MatrixCursor
,将我的国家/地区数据库中的列映射到搜索工具所需的列。国家名称显示良好,我可以选择它们并在我的应用程序中正确响应

我尝试了三种不同的方式形成Uri:

//                    String flagUri = "file:///android_asset/" + flagPath;
//                    String flagUri = "file:///assets/" + flagPath;
                    String flagUri = "android.resource://com.lesliesoftware.worldinfo.WorldInfoActivity/assets/" + flagPath;
                    columnValues.add (flagUri);
它们都指向同一件事——我的应用程序图标位于每个建议旁边,我可以使用空字符串值获得这些建议

有一个Uri可以工作吗?如何获取搜索建议旁边的国旗图标

谢谢你,伊恩

全文来源:

private Cursor search (String query, int limit)  {
    query = query.toLowerCase ();
    String[] requestedColumns = new String[]  {
            BaseColumns._ID, 
            SearchManager.SUGGEST_COLUMN_TEXT_1,
            SearchManager.SUGGEST_COLUMN_ICON_1,
    };
    String[] queryColumns = new String[]  {
            WorldInfoDatabaseAdapter.KEY_ROWID, 
            WorldInfoDatabaseAdapter.KEY_COUNTRYNAME,
            WorldInfoDatabaseAdapter.KEY_COUNTRYCODE
    };

    return packageResults (query, requestedColumns, queryColumns, limit);
}


private Cursor packageResults (String query, String[] requestedColumns, String[] queryMappedColumns, int limit)  {
    if (requestedColumns.length != queryMappedColumns.length)
        throw new IllegalArgumentException ("Internal error: requested columns do not map to query columns");

    MatrixCursor results = new MatrixCursor (requestedColumns);

    //  Query the country list returns columns: KEY_ROWID, KEY_COUNTRYNAME, KEY_COUNTRYCODE
    Cursor dbResults = myDbHelper.getCountryList (query);

    //  Verify that the query columns are available
    for (int index = 0; index < queryMappedColumns.length; index++)  {
        int col = dbResults.getColumnIndex (queryMappedColumns[index]);
        if (col == -1)
            throw new IllegalArgumentException ("Internal error: requested column '" + 
                    queryMappedColumns[index] + "' was not returned from the database.");
    }

    //  Loop over the database results building up the requested results
    int rowCount = 0;
    while (dbResults.moveToNext ()  &&  rowCount < limit)  {
        Vector<String> columnValues = new Vector<String> ();
        for (int index = 0; index < requestedColumns.length; index++)  {
            if (requestedColumns[index].compareTo (SearchManager.SUGGEST_COLUMN_ICON_1) == 0)  {
                String flagPath = "flags/small/" + dbResults.getString (
                        dbResults.getColumnIndexOrThrow (queryMappedColumns[index]))
                        + "-flag.gif";
//                    String flagUri = "file:///android_asset/" + flagPath;
//                    String flagUri = "file:///assets/" + flagPath;
                String flagUri = "android.resource://com.lesliesoftware.worldinfo.WorldInfoActivity/assets/" + flagPath;
                columnValues.add (flagUri);
            }  else  {
                //  Add the mapped query column values from the database
                String colValue = dbResults.getString (dbResults.getColumnIndexOrThrow (queryMappedColumns[index]));
                columnValues.add (colValue);
            }
        }

        results.addRow (columnValues);
        rowCount++;
    }

    return results;
}
唯一有效的uri是如果我将测试标志移动到我的drawable文件夹中:

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/" + 
    R.drawable.small_ca_flag;

遗憾的是,在进行了大量搜索之后,我得出了一个结论:您无法将图像资产的uri返回到搜索工具。我所做的是将我的标志图像移动到资源中(这样它们就不会把我的应用程序的资源弄得乱七八糟,我为标志图像创建了一个库)并使用资源uri。因此,在我的提供者中,我的代码在将数据库结果映射到搜索结果的循环中如下所示:

            if (requestedColumns[index].compareTo (SearchManager.SUGGEST_COLUMN_ICON_1) == 0)  {
                //  Translate the country code into a flag icon uri
                String countryCode = dbResults.getString (
                        dbResults.getColumnIndexOrThrow (queryMappedColumns[index]));

                int flagImageID = FlagLookup.smallFlagResourceID (countryCode);
                String flagUriStr = "android.resource://com.lesliesoftware.worldinfo/" + flagImageID;
                columnValues.add (flagUriStr);
            }  
并查找如下所示的代码:

static public int smallFlagResourceID (String countryCode)  {
    if (countryCode == null || countryCode.length () == 0)
        return R.drawable.flag_small_none;

    if (countryCode.equalsIgnoreCase ("aa"))
        return R.drawable.flag_small_aa;
    else if (countryCode.equalsIgnoreCase ("ac"))
        return R.drawable.flag_small_ac;
    else if (countryCode.equalsIgnoreCase ("ae"))
        return R.drawable.flag_small_ae;
    ...
content://com.example.assets/my_folder_inside_assets/myfile.png

我只需确保我创建了一个测试,以验证所有具有标志的国家/地区都返回了预期的结果。

您首先要创建一个
AssetProvider
。稍后我们将创建将由此类处理的URI

public class AssetsProvider extends ContentProvider {

    private AssetManager assetManager;
    public static final Uri CONTENT_URI = 
            Uri.parse("content://com.example.assets");

    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) { return 0; }

    @Override
    public String getType(Uri uri) { return null; }

    @Override
    public Uri insert(Uri uri, ContentValues values) { return null; }

    @Override
    public boolean onCreate() {
        assetManager = getContext().getAssets();
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; }

    @Override
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
        String path = uri.getPath().substring(1);
        try {
            AssetFileDescriptor afd = assetManager.openFd(path);
            return afd;
        } catch (IOException e) {
            throw new FileNotFoundException("No asset found: " + uri, e);
        }
    }
}
里面有很多样板。基本方法当然是
openAssetFile
,它只是将传递给它的uri路径转换为
assetfile描述符
。为了让Android能够将URI传递给此提供商,请记住将其包含在应用程序标记内的AndroidManifest.xml文件中:

    <provider
        android:name=".AssetsProvider"
        android:authorities="com.example.assets" />

只是想补充一下vidstige的回答:我想提供我先前下载到临时缓存目录的文件,这样我就可以从我的搜索内容提供者中的URL向SearchView建议提供外部图像缩略图。我使用了这个函数:

@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
        String filename = uri.getLastPathSegment();

        try {
            File file = new File(getContext().getCacheDir(), filename);

            // image downloading has to be done in the search results provider, since it's not on the UI thread like this guy.
            //downloadAndSaveFile("http://urdomain/urfile.png", filename);

            AssetFileDescriptor afd = new AssetFileDescriptor(
                        ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY | ParcelFileDescriptor.MODE_WORLD_READABLE),
                    0, AssetFileDescriptor.UNKNOWN_LENGTH);

            return afd;
        } catch (IOException e) {
            throw new FileNotFoundException("No asset found: " + uri);
        }
    }

我能够使用以下uri引用SearchRecentSuggestionsProvider中drawable中的图像

"android.resource://your.package.here/drawable/image_name

谢谢,这对我有用!有一些陷阱(比如我认为CONTENT_URI必须存在?没有的时候遇到了麻烦)是的,CONTENT_URI必须存在,它将由Andoid读取,并与清单中的
android:authorities
属性匹配。嘿!回答得好!由于已加载的资产映像的大小,我遇到一些问题。我知道这是因为从资源文件夹加载的图像没有基于屏幕密度的“缩放”功能,而从资源文件夹加载的图像没有。关于如何解决这个问题有什么想法吗?@acrespo是的,你是正确的,这将不会选择不同的文件等,这取决于解决方案。但是,如果您认为合适,UI将缩放图像。如果您需要对每像素的外观和/或性能进行更多控制,我建议您改用drawables。您可能还将此逻辑添加到
openAssetFile
函数中。@vidstige您将如何执行此操作?我考虑过在
openAssetFile
函数中处理图像大小,但我不知道如何使用
AssetFileDescriptor
。我认为这是不可能实现的:SDR和资产不是一回事
"android.resource://your.package.here/drawable/image_name