使用改造从(本地)android资产文件夹获取Json数据

Posted

技术标签:

【中文标题】使用改造从(本地)android资产文件夹获取Json数据【英文标题】:Getting Json data from (Local) android assets folder using retrofit 【发布时间】:2017-09-16 14:15:39 【问题描述】:

我正在开发一个需要从本地 android 资产目录 访问 Json 数据的项目。我可以使用 Volley Library 从 assets 文件夹中读取 json 数据,但我想使用 Retrofit 做同样的事情。下面是我的 json 文件 - myfile.json


    "formules": [
    
      "formule": "Linear Motion",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Constant Acceleration Motion",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Projectile Motion",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Force",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Work, Power, Energy",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Rotary Motion",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Harmonic Motion",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Gravity",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Lateral and Longitudinal Waves",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Sound Waves",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Electrostatics",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Direct Current",
      "url": "<html><body>You scored <b>192</b> points. <img src=\"http://192.168.1.46/shanta_holdings/img/images/project-thumbs/Glasshouse-1.jpg\" alt=\"Smiley face\"/></body></html> ",
      "des":"Here is a description"
    ,
    
      "formule": "Magnetic Field",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Alternating Current",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Thermodynamics",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Hydrogen Atom",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Optics",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Modern Physics",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Hydrostatics",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    ,
    
      "formule": "Astronomy",
      "url": "https://www.google.com/",
      "des":"Here is a description"
    
  ]

我已经搜索了一周,但没有找到任何合适的改造解决方案。我可以使用 Retrofit 从服务器读取数据。有没有办法使用改造来实现要求。

【问题讨论】:

我认为 Volly 和 Retrofit 用于 rest API 不用于从资产文件夹转换 JSON,使用 GSON 进行解析。 我有一个问题:为什么? 为什么要在不应该​​使用 Volley 和 Retrofit 的地方使用它们?为什么不想直接加载文件? 【参考方案1】:

正如 Dheerubhai 所写,Retrofit 不用于解析 JSON 对象。您可以使用 GSON,请参阅 this thread 以了解如何使其与 Retrofit 一起使用,您可以参阅 this tutorial。

【讨论】:

我可以通过改造从服务器检索数据。你可能不清楚我的问题。我想从本地文件而不是 url 中检索 json 数据。 我明白了,但第一个链接包含一个从本地存储的 JSON 文件中检索数据的示例。【参考方案2】:

您正在尝试在您的项目中实现存根。

将您的 .json 文件添加到 res/raw/filename.json

上面的示例显示了两个 Web 服务端点的本地存根文件 - /some/web/service、/another/web/service)和两个场景 - 空和默认(默认存根没有前缀,空存根以“空的_”)。这些文件的内容通常是 JSON。

接下来我们编写一个自定义 HTTP 客户端来从这些本地文件而不是网络中获取。以下示例实现了 Square 的 Retrofit 库中的 Client 对象。如果你不熟悉 Retrofit,默认的 Client 实现是 OkClient。它发出标准的 HTTP 网络请求。我们正在编写一个自定义客户端来伪造网络请求并从本地文件而不是网络服务器获取响应数据。

上面的示例显示了两个 Web 服务端点的本地存根文件 - /some/web/service、/another/web/service)和两个场景 - 空和默认(默认存根没有前缀,空存根以“空的_”)。这些文件的内容通常是 JSON。

接下来我们编写一个自定义 HTTP 客户端来从这些本地文件而不是网络中获取。以下示例实现了 Square 的 Retrofit 库中的 Client 对象。如果你不熟悉 Retrofit,默认的 Client 实现是 OkClient。它发出标准的 HTTP 网络请求。我们正在编写一个自定义客户端来伪造网络请求并从本地文件而不是网络服务器获取响应数据。

public class LocalStubClient implements Client 
    private Context context;
    private String scenario;

    public LocalStubClient(Context context, String scenario) 
        this.context = context;
        this.scenario = scenario;
    

    public LocalStubClient(Context context) 
        this.context = context;
    

    public void setScenario(String scenario) 
        this.scenario = scenario;
    

    @Override
    public Response execute(Request request) throws IOException 
        //get resource id for local file
        String fileName = createFilename(request, scenario);
        int resourceId = getResourceId(fileName);
        if (resourceId == 0)  //fallback to default filename
            fileName = createFilename(request, null);
            resourceId = getResourceId(fileName);
            if (resourceId == 0) 
                throw new IOException("Could not find res/raw/" + fileName + ".stub");
            
        

        //get input stream & mime for local file
        InputStream inputStream = context.getResources().openRawResource(resourceId);
        String mimeType = URLConnection.guessContentTypeFromStream(inputStream);

        //wrap local stream in retrofit objects
        TypedInput body = new TypedInputStream(mimeType, inputStream.available(), inputStream);
        Response response = new Response(request.getUrl(), 200, "Stub from res/raw/" + fileName, new ArrayList<Header>(), body);
        return response;
    

    private String createFilename(Request request, String scenario) throws IOException 
        URL requestedUrl = new URL(request.getUrl());
        String requestedMethod = request.getMethod();
        String prefix = scenario == null ?  "" : scenario + "_";
        String filename = prefix + requestedMethod + requestedUrl.getPath();
        filename = filename.replace("/", "_").replace("-", "_").toLowerCase();
        return filename;
    

    private int getResourceId(String filename) 
        return context.getResources().getIdentifier(filename, "raw", context.getPackageName());
    

    private static class TypedInputStream implements TypedInput 
        private final String mimeType;
        private final long length;
        private final InputStream stream;

        private TypedInputStream(String mimeType, long length, InputStream stream) 
            this.mimeType = mimeType;
            this.length = length;
            this.stream = stream;
        

        @Override
        public String mimeType() 
            return mimeType;
        

        @Override
        public long length() 
            return length;
        

        @Override
        public InputStream in() throws IOException 
            return stream;
        
    

最后,我们检查我们的“后端环境”设置,以确定我们应该使用 LocalStubClient 还是默认的 OkClient:

RestAdapter.Builder builder = new RestAdapter.Builder();

String selectedBackend = getSharedPreference(R.string.pref_backend, "");
switch (Integer.parseInt(selectedBackend)) 
    case R.string.test_server:
    case default:
        builder.setClient(new OkClient());
        builder.setEndpoint("http://test.api.mydomain.com");
        break;
    case R.string.demo_server:
        builder.setClient(new OkClient());
        builder.setEndpoint("http://demo.api.mydomain.com");
        break;
    case R.string.default_local_stubs:
        builder.setClient(new LocalStubClient(app));
        break;
    case R.string.empty_local_stubs:
        builder.setClient(new LocalStubClient(app, "empty"));
        break;


RestAdapter adapter = builder.build();

模拟网络延迟和故障 Retrofit 还允许我们模拟网络延迟、方差和故障。下面是根据我们的第二个 Dev 设置启用/禁用模拟网络适配器的代码:

RestAdapter.Builder builder = new RestAdapter.Builder();

//...

RestAdapter adapter = builder.build();

if (getSharedPreference(R.string.pref_mock_network, false)) 
    MockRestAdapter mockRestAdapter = MockRestAdapter.from(adapter);
    mockRestAdapter.setDelay(1000);
    mockRestAdapter.setVariancePercentage(50);
    mockRestAdapter.setErrorPercentage(10);
    return mockRestAdapter.create(serviceType, adapter.create(serviceType));
 
return adapter.create(serviceType)

【讨论】:

感谢您的回复。让我试试你的解决方案,我会告诉你的。

以上是关于使用改造从(本地)android资产文件夹获取Json数据的主要内容,如果未能解决你的问题,请参考以下文章

从资产文件夹的本地html(WebView)中的外部存储中打开文件(视频)? (安卓)

在 Android 中通过改造获取对象数组

为远程 html 页面从 Android 中的本地资产加载 jQuery

使用本地资产/HTML/资源时,jQuery getScript 在 Android WebView 中不起作用

Android SDK Webview加载不在资产文件夹中的本地文件

如何使用 json 本地资产文件创建动态列表视图