【问题标题】:NullPointerException at openFileOutput in ActivityActivity 中 openFileOutput 的 NullPointerException
【发布时间】:2012-04-21 13:40:26
【问题描述】:

我有一个带有 ImageView 的 Activity,如果它是空的并被单击,则应该从 Internet 加载图像并将其保存到内部存储中。所以活动看起来像这样:

public class PlaceCreate extends Activity {
Context context;

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.create);
  context = this;

  ImageView img = (ImageView) findViewById(R.id.imageView);
  img.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
        EditText edit = (EditText)findViewById(R.id.editTextName);
        Download(edit.getText().toString());
    }
  });
}

private boolean Download(String Name)
{
  try
  {
    URL u = new URL("http://example.com/img.png");
    HttpURLConnection c = (HttpURLConnection)u.openConnection();
    c.setRequestMethod("GET");
    c.setDoOutput(true);
    c.connect();
    FileOutputStream f = context.openFileOutput(Name, Context.MODE_PRIVATE);
    InputStream in = c.getInputStream();
    byte[] buffer = new byte[1024];
    int len1 = 0;
    while((len1 = in.read(buffer)) > 0 )
    {
      f.write(buffer, 0, len1);
    }
    f.close();

    FileInputStream is = openFileInput(Name);
    Bitmap bitmap = BitmapFactory.decodeStream(is);
    is.close();
    ImageView img = (ImageView) findViewById(R.id.imageViewPlan);
    img.setImageBitmap(bitmap);
  }
  catch(IOException e)
  {
    return false;
  }
  return true;
}}

问题是我得到 NullPointerException 与openFileOutput 一致。我发现了几个类似的问题,但所有答案都暗示null 是一个缺失的上下文。由于在这种情况下它是一个活动,它显然有一个上下文(this),并且它不为空。我试图通过context 成员调用openFileOutput(隐含this)。任何一种方法都失败了。此外,我尝试将 v.getContext()onClick 传递到 Download 作为附加参数,并且该值不为空,但也产生了相同的异常。 (如果很重要,请求的文件名是有效的文件名,例如“abc”。)

有人能解释一下吗?

这是堆栈的示例:

04-22 00:45:10.659: W/dalvikvm(330): threadid=1: thread exiting with uncaught exception (group=0x40015560)
04-22 00:45:10.909: E/AndroidRuntime(330): FATAL EXCEPTION: main
04-22 00:45:10.909: E/AndroidRuntime(330): java.lang.NullPointerException
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.app.ContextImpl.openFileOutput(ContextImpl.java:420)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.content.ContextWrapper.openFileOutput(ContextWrapper.java:158)
04-22 00:45:10.909: E/AndroidRuntime(330):  at com.example.scanner.PlaceCreate.Download(PlaceCreate.java:93)
04-22 00:45:10.909: E/AndroidRuntime(330):  at com.example.scanner.PlaceCreate.access$0(PlaceCreate.java:84)
04-22 00:45:10.909: E/AndroidRuntime(330):  at com.example.scanner.PlaceCreate$3.onClick(PlaceCreate.java:67)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.view.View.performClick(View.java:2485)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.view.View$PerformClick.run(View.java:9080)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.os.Handler.handleCallback(Handler.java:587)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.os.Handler.dispatchMessage(Handler.java:92)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.os.Looper.loop(Looper.java:123)
04-22 00:45:10.909: E/AndroidRuntime(330):  at android.app.ActivityThread.main(ActivityThread.java:3683)
04-22 00:45:10.909: E/AndroidRuntime(330):  at java.lang.reflect.Method.invokeNative(Native Method)
04-22 00:45:10.909: E/AndroidRuntime(330):  at java.lang.reflect.Method.invoke(Method.java:507)
04-22 00:45:10.909: E/AndroidRuntime(330):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
04-22 00:45:10.909: E/AndroidRuntime(330):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
04-22 00:45:10.909: E/AndroidRuntime(330):  at dalvik.system.NativeStart.main(Native Method)

还有一些发现。根据堆栈,错误发生在ContextImpl 文件中,我看到parent 局部变量在此方法中为空。代码如下:

public FileOutputStream openFileOutput(String name, int mode)
  throws FileNotFoundException {
  final boolean append = (mode&MODE_APPEND) != 0;
  File f = makeFilename(getFilesDir(), name);
  try {
     FileOutputStream fos = new FileOutputStream(f, append);
     setFilePermissionsFromMode(f.getPath(), mode, 0);
     return fos;
  } catch (FileNotFoundException e) {
 }

 File parent = f.getParentFile();
 parent.mkdir();
 FileUtils.setPermissions(
     parent.getPath(),
     FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
     -1, -1);
 FileOutputStream fos = new FileOutputStream(f, append);
 setFilePermissionsFromMode(f.getPath(), mode, 0);
 return fos;
}

所以现在的问题是如何确保对 f.getParentFile() 的调用不会返回 null,为什么它有时会起作用?

【问题讨论】:

  • 当您说...名称是一个有效的文件名,例如“abc”时,这是您尝试过的实际文件名吗?
  • 请提供完整的堆栈跟踪。
  • @MisterSquonk:是的,我也试过'abc'。这个名字有什么问题?
  • @CommonsWare:奇怪,但重启后我无法得到异常,代码可以工作。很抱歉提出一个问题,这在代码中似乎没有根据。
  • @CommonsWare:嗯,又回来了,这是堆栈:

标签: android nullpointerexception


【解决方案1】:

问题是我在使用 openFileOutput 时得到 NullPointerException。

您将在openFileOutput()实现 中获得NullPointerException。这就是为什么您需要为 SO 提供堆栈跟踪,而不仅仅是提供异常名称。一行的异常不同于一行触发的异常,尤其是NullPointerException

根据我在ContextImpl 上对openFileOutput() 的阅读,要么:

  • Namenull,或者
  • 你有一个非常奇怪的context,或者
  • 在当前的openFileOutput() 实现中,您运行的Android 版本可能存在其他一些问题

我将首先完全删除context,因为您在Activity 中并且不需要它。然后,放入一些Log 语句或设置断点,看看Name 是什么。

【讨论】:

  • 您是否看到带有堆栈和新发现的新版本问题? ContextImpl 中带有f.getParentFile() 的行产生null
  • @Stan:当f.getParentFile()返回null时,f包含什么?
  • f File (id=830007877600) absolutePath "/a" (id=830007877752) path "a" (id=830007877784) parent null,意思是我这次选择了名字a
  • @Stan:你在EditText 中输入了什么来生成这个结果?如果答案是/a,那你的问题就出来了——openFileInput()openFileOutput() 只适用于裸文件名,没有任何路径。
  • 不,我当然输入了a。如果我输入/a(我尝试过,因为我已经不知道该怎么做)我会得到另一个异常。
【解决方案2】:

这被证明是作为 SDK 的一部分安装在这里的 Android 2.3.3 模拟器的一个功能。如果我使用带有 Android 2.3.3 的真实设备,则不会出现此问题。如果我使用 Android 4.0.3 模拟器,代码也可以正常工作。因此,如果发生一些奇怪的事情,在另一个环境中进行测试可以提供一些启示。我希望这可以帮助其他人解决类似的问题。

【讨论】:

  • @d34th4ck3r,不,不清楚哪个产品受到影响和/或哪个环境设置导致问题。另外,我想先从其他人那里得到一些确认。
  • 你可以算我在确认中。
  • @d34th4ck3r,问题是SDK老版本的问题,好像对新版本没有影响,所以应该视为已修复,恕我直言。
【解决方案3】:

我在运行 ICS 的 Asus TF101 上遇到了同样的问题 - 即一个真实的设备而不是一个模拟器。这很令人烦恼,因为事实证明这个问题与底层文件夹的 Linux 写权限有关。

我一直在尝试在清单文件中使用带有 android:sharedUserId 标记的共享资源。由于 UID 已更改,该活动不再具有数据文件目录中的写入权限。

所以任何可能改变 uid 的东西都可能导致这个问题。

解决问题我:

  1. 从清单中删除了sharedUserID 标签(可能是可选的);
  2. 从我的设备上手动卸载了该应用。
  3. 重新安装应用程序。

然后完美运行。

【讨论】:

    【解决方案4】:

    通过阅读 openFileOutput() 的代码,我可以看到 f.getParentFile() 可能返回 null 的情况,这在此处的任何其他答案或评论中均未提及。

    在一行

    File f = makeFilename(getFilesDir(), name);
    

    如果dataDir 不存在并且getFilesDir() 未能创建dataDir,getFilesDir() 可以返回null。如果发生这种情况,文件f 将只有在name 是路径(例如“目录/文件”)而不只是文件(例如“文件”)时才会有父文件。

    我不知道在什么情况下会丢失 dataDir 以及何时无法创建它,但听起来由于某种原因无法在 Android 2.3.3 模拟器中创建它的可能性不大。

    【讨论】:

      【解决方案5】:

      查看this完整示例

      URL url = new URL (strURL);
      input = url.openStream();
      byte[] buffer = new byte[1500];
      OutputStream output = new FileOutputStream ("/sdcard/abc.png");
      int bytesRead = 0;
      while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) .
      {
       output.write(buffer, 0, bytesRead);
       }
      

      【讨论】:

      • 不幸的是,我不需要外部存储(例如sd卡),我需要内部存储。在我看到的这种情况的示例中,单个文件名(没有路径)是可以的。
      猜你喜欢
      • 2015-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-22
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      相关资源
      最近更新 更多