Android的DexClassLoader错误,“优化的数据目录..不是由当前用户拥有” [英] Android DexClassLoader error, 'optimized data directory .. not owned by current user'

查看:394
本文介绍了Android的DexClassLoader错误,“优化的数据目录..不是由当前用户拥有”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个简单的Andr​​oid应用程序,可以从SD卡在运行时加载一个DEX文件。

I am trying to produce a simple android application that can load a DEX file from the SD card at run-time.

该应用程序有两个activites。第一个活动是,有一个按钮,一个简单的屏幕。当按钮pssed $ P $,第二活动启动引起待调用的loadDex()方法。该loadDex()方法试图找到一个jar文件在SD卡上,并将其加载到当前应用程序。

The application has two activites. The first activity is a simple screen that has a button. When the button is pressed, the second activity is launched which causes the loadDex() method to be invoked. The loadDex() method attempts to locate a jar file on the SD card and load it into the current application.

下面是我的$ C $下的第一个活动:

Here is my code for the first activity:

package poc.example.del.customclass;

import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;


public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void launchLoadClass(View view) {
        Intent intent = new Intent(MainActivity.this, LoadClass.class);
        startActivity(intent);
    }
}

下面是code我的第二个活动(一个加载的DEX文件):

Here is the code for my second activity (the one that loads the DEX file):

package poc.example.del.customclass;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;


public class LoadClass extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_load_class);
        loadDex();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_load_class, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void loadDex() {
        String dexFile = "/sdcard/output.jar";
        File jarFile = new File(dexFile);
        if (jarFile.exists()) {
            // Toast.makeText(getApplicationContext(), "It Worked!", Toast.LENGTH_LONG).show();
            DexClassLoader cl = new DexClassLoader (jarFile.toString (), "/data/test", null, ClassLoader.getSystemClassLoader());

        }
    }
}

在DexClassLoader构造函数被调用的问题出现。下面的错误可以在日志中找到:

The issue arise when the DexClassLoader constructor is called. The following error can be found in the log:

03-25 10:15:48.441    1934-1934/poc.example.del.customclass E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{poc.example.del.customclass/poc.example.del.customclass.LoadClass}: java.lang.IllegalArgumentException: Optimized data directory /data/test is not owned by the current user. Shared storage cannot protect your application from code injection attacks.
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.IllegalArgumentException: Optimized data directory /data/test is not owned by the current user. Shared storage cannot protect your application from code injection attacks.
            at dalvik.system.DexFile.<init>(DexFile.java:100)
            at dalvik.system.DexFile.loadDex(DexFile.java:149)
            at dalvik.system.DexPathList.loadDexFile(DexPathList.java:261)
            at dalvik.system.DexPathList.makeDexElements(DexPathList.java:229)
            at dalvik.system.DexPathList.<init>(DexPathList.java:96)
            at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:56)
            at dalvik.system.DexClassLoader.<init>(DexClassLoader.java:57)
            at poc.example.del.customclass.LoadClass.loadDex(LoadClass.java:54)
            at poc.example.del.customclass.LoadClass.onCreate(LoadClass.java:23)
            at android.app.Activity.performCreate(Activity.java:5104)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)

下面是我相信再$ P $日志中的行psents问题:

Here is the line in the log that I believe represents the issue:

java.lang.IllegalArgumentException: Optimized data directory /data/test is not owned by the current user. Shared storage cannot protect your application from code injection attacks.

任何帮助将是AP preciate因为我发现关于这个问题的资料很少在网络上。我正在开发针对Android 4.2的应用程序,空气污染指数17。

Any help would be appreciate as I have found very little information on the web regarding the issue. I am developing the application for Android 4.2, Api 17.

在此先感谢。

推荐答案

我找到了答案后,下面的各种教程几天。我认为Id在这里发表的解决方案,如果任何人有类似的问题。

I found an answer after a few days of following various tutorials. I thought id post the solution here in case anyone else has a similar problem.

有关安全方面的原因,Android的不允许应用程序加载文件到任何随机文件夹。相反,它应被装载到应用环境。下面是修改code,它使我继续这个项目。显示的code是为'loadDex()方法:

For security reasons, Android does not allow the application to load files to any random folder. Instead it should be loaded to the applications environment. Here is the modified code that has allowed me to continue with the project. The code shown is for the 'loadDex()' method:

public void loadDex() {
    // Toast the show the method has been invoked correctly
    // Toast.makeText(getApplicationContext(), "loadDex() Method invoked", Toast.LENGTH_LONG).show();

    // name of the DEX file
    String dexFile = "/output.jar";

    // Get the path to the SD card
    File f = new File(Environment.getExternalStorageDirectory().toString() + dexFile);

    // optimized directory, the applciation and package directory
    final File optimizedDexOutputPath = getDir("outdex", 0);

    // DexClassLoader to get the file and write it to the optimised directory
    DexClassLoader classLoader = new DexClassLoader(f.getAbsolutePath(),
    optimizedDexOutputPath.getAbsolutePath(),null, getClassLoader());

    // The classpath is created for the new class
    String completeClassName = "poc.example.del.mylibrary.name";
    String methodToInvoke = "display";

    try {
        Class<?> myClass = classLoader.loadClass(completeClassName);
        Object obj = (Object)myClass.newInstance();
        Method m = myClass.getMethod(methodToInvoke);
        String s = ""+m.invoke(obj);
        makeToast(s);
    }
    catch (Exception e) {
        e.printStackTrace();
        makeToast("Something went wrong!");
    }


}

的code中的特定行(s)表示,解决这个问题是:

The specific line(s) of code that resolved the problem is:

// DexClassLoader to get the file and write it to the optimized directory
DexClassLoader classLoader = new DexClassLoader(f.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(),null, getClassLoader());

正如你所看到的,optimizedDexOutputPath,getAbsolutePath()方法返回可以使用的应用程序写入文件的目录。

As you can see, the optimizedDexOutputPath,getAbsolutePath() method returns the directory that can be used to write files to by the application.

希望这有助于任何人有类似的问题!

Hope this helps anyone else with a similar issue!

这篇关于Android的DexClassLoader错误,“优化的数据目录..不是由当前用户拥有”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆