我有一个带有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;
}}
问题是我在openFileOutput
的行上得到了NullPointerException。我发现了几个类似的问题,但所有答案都暗示null
是一个缺失的背景。因为在这种情况下它是一个活动,它显然有一个上下文(this
),它不是null。我尝试通过openFileOutput
成员致电this
(隐含context
)。两种方法都失败了。此外,我尝试将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
局部变量为null。这是代码:
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,为什么它会不时地工作?
答案 0 :(得分:2)
问题是我在使用openFileOutput的行上获得了NullPointerException。
您在NullPointerException
的实施中获得了openFileOutput()
。这就是为什么您需要为SO提供堆栈跟踪,而不是仅提供异常名称。 on 行中的异常与行触发的异常不同,尤其是NullPointerException
。
根据我对ContextImpl
的openFileOutput()
的解读,或者:
Name
是null
或context
或openFileOutput()
我首先完全删除context
,因为你在Activity
内并且不需要它。然后,输入一些Log
语句或设置断点以查看Name
是什么。
答案 1 :(得分:1)
这被证明是Android 2.3.3模拟器的一个功能,作为SDK的一部分安装在这里。如果我使用Android 2.3.3的真实设备,则不会出现此问题。如果我使用Android 4.0.3模拟器,代码也能正常工作。因此,如果发生一些奇怪的事情,在另一个环境中进行测试可以解决一些问题。我希望这可以帮助其他人解决类似问题。
答案 2 :(得分:1)
我在运行ICS的华硕TF101上遇到了同样的问题 - 即真正的设备,而不是模拟器。由于事实证明该问题与底层文件夹上的Linux写权限有关,因此令人烦恼。
我一直在使用共享资源和清单文件中的android:sharedUserId
标记。由于UID已更改,因此活动不再具有数据文件目录中的写入权限。
所以任何可能改变uid的东西都可能导致这个问题。
解决问题我:
sharedUserID
标记(可能是可选的); 然后运行得很好。
答案 3 :(得分:1)
通过阅读openFileOutput()的代码,我可以看到一个案例,其中f.getParentFile()可能返回null,这里没有提到任何其他答案或评论。
在第
行File f = makeFilename(getFilesDir(), name);
如果getFilesDir()不存在且getFilesDir()
无法创建dataDir,则 dataDir可以返回null。如果发生这种情况,如果f
是路径(例如"目录/文件")而不仅仅是文件(例如&#34),则文件name
将只有父项。 ;文件"。)
我不知道dataDir会在哪些情况下丢失,什么时候不可能创建它,但由于某些原因它不可能在Android 2.3中创建不太可能.3模拟器。
答案 4 :(得分:0)
请参阅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);
}