java - 由于 Intent 中的 NullPointerException,Android 画廊应用程序在安装后无法启动
问题描述
我是 Java 新手并使用 Android Studio。我的应用程序在安装后不会启动。检查源代码和 XML,我似乎找不到任何错误。请帮我检查下面的代码
MainActivity.java
public class MainActivity extends AppCompatActivity {
ArrayList<File> list;
GridView gridView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = (GridView)findViewById(R.id.image_grid);
list = imageReader(Environment.getExternalStorageDirectory());
gridView.setAdapter(new gridAdapter());
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, FullImageActivity.class);
intent.putExtra("img", list.get(i).toString());
startActivity(intent);
}
});
}
public class gridAdapter extends BaseAdapter{
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
View convertView = null;
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.row_layout, viewGroup, false);
ImageView myImage = (ImageView) convertView.findViewById(R.id.my_image);
myImage.setImageURI(Uri.parse(list.get(i).toString()));
}
return convertView;
}
}
private ArrayList<File> imageReader(File externalStorageDirectory) {
ArrayList<File> b = new ArrayList<>();
File[] files = externalStorageDirectory.listFiles();
for (int i =0; i<files.length; i++){
if (files[i].isDirectory()){
b.addAll(imageReader(files[i]));
}else {
if (files[i].getName().endsWith(".jpg")) {
b.add(files[i]);
}
}
}
return b;
}
}
这是activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
android:id="@+id/image_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="auto_fit"
android:columnWidth="100dp"
android:verticalSpacing="100dp"
android:horizontalSpacing="10dp"
android:stretchMode="spacingWidthUniform" />
</RelativeLayout>
这是 FullImageActivity.java
public class FullImageActivity extends AppCompatActivity {
ImageView fullImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full_image);
fullImage = (ImageView)findViewById(R.id.full_image);
String data = getIntent().getExtras().getString("img");
fullImage.setImageURI(Uri.parse(data));
}
}
activity_full_image.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FullImageActivity">
<ImageView
android:id="@+id/full_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/wp"
/>
</RelativeLayout>
row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/my_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/wp"
/>
</RelativeLayout>
如果我的问题得到关注,我会很高兴,因为它深深地侵蚀了我。
这是 LOGCAT
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at com.jkjworks.galleryextra.FullImageActivity.onCreate(FullImageActivity.java:19)
at android.app.Activity.performCreate(Activity.java:7030
#2 更新清单和BUILD.GRADLE
这是清单
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"/>
<activity android:name=".FullImageActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这是APP级别的Build.gradle
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.domain.galleryextra"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
compile 'com.android.support:multidex:1.0.3'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation 'com.google.android.gms:play-services-ads:12.0.1'
implementation 'com.android.support:support-vector-drawable:27.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
解决方案
你确定list.get(i)
不是null
吗?我会设置一个断点并分析 的返回值,list.get(i)
以确保您传递的是有效数据。
另外,使用intent.getStringExtra("img")
而不是getIntent().getExtras().getString("img")
您的问题是getIntent()
正在接收NULL
并且您正在尝试访问它,从而导致NullPointerException
发生。
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at com.merizekworks.galleryextra.FullImageActivity.onCreate(FullImageActivity.java:19)
编辑(关于如何调试的快速细分) 您可以做的最好的事情是通过调试器逐步执行您的代码。如果您从未这样做过,它实际上很容易做到,并且会帮助您了解问题所在。
在MainActivity
改变这个:
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, FullImageActivity.class);
intent.putExtra("img", list.get(i).toString());
startActivity(intent);
}
对此,帮助我们调试更容易一点:
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, FullImageActivity.class);
File selectedFile = list.get(i); //PUT BREAKPOINT ON THIS LINE
String filePath = selectedFile.toString();
intent.putExtra("img", filePath );
startActivity(intent);
}
注意:如果您不熟悉调试代码,那么我强烈建议您花几分钟时间阅读这篇文章。在我看来,它是程序员拥有的最有价值的工具。单击此处了解如何在 Android Studio 中进行调试
左边的红圈是断点,代码会在这里停止执行,你可以分析每个变量,如上图所示。您甚至可以在您的应用程序正在运行并且执行被断点暂停时“评估表达式”。这样做可以让您抓取内存中当前的任何对象并对其进行测试。
例如,使用上面设置的断点,我们可以使用“调试”选项卡中的“评估表达式”按钮:
这是一篇关于如何使用 AndroidStudio 调试器的文章中如何评估表达式的快速屏幕截图(此处为完整指南):
更新#2
请注意,如果您使用 API 23 或更高版本,则必须确保您有权从 Android 设备读取/写入。
在您的AndroidManifest.xml
内部Manifest
标签中包括以下内容:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
然后这是我在项目中使用的解决方案,对我来说效果很好,特别是如果您计划请求多个权限。
public class MainActivity extends AppCompatActivity {
private final String TAG = "DEBUG";
private Activity activity;
private ArrayList<File> list;
private GridView gridView;
private final int REQUEST_PERMISSIONS_CODE = 1;
private String[] PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int totalGrantedCount = 0;
for(int x=0; x < grantResults.length; x++){
if (grantResults[x] == PackageManager.PERMISSION_GRANTED){
totalGrantedCount++;
}
}
if(totalGrantedCount == grantResults.length){
startApp();
}else{
boolean somePermissionsForeverDenied = false;
for(String permission: permissions){
if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
//denied
Log.d(TAG, "PERMISSIONS: DENIED " + permission);
}else{
if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
//allowed
Log.d(TAG, "PERMISSIONS: ALLOWED " + permission);
} else{
//set to never ask again
somePermissionsForeverDenied = true;
}
}
}
if(somePermissionsForeverDenied){
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Permissions Required")
.setMessage("You have forcefully denied some of the required permissions " +
"for this action. Please open settings, go to permissions and allow them manually.")
.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setCancelable(false)
.create()
.show();
}else{
new AlertDialog.Builder(this)
.setTitle("PERMISSIONS DENIED")
.setMessage("Unable to proceed, this application requires that permissions be accepted to operate correctly. \r\n\r\n YOU MUST APPROVE ALL PERMISSIONS BEFORE CONTINUING.")
.setPositiveButton("TAP HERE TO CLOSE AND TRY AGAIN.", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
activity.finish();
System.exit(0);
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.setCancelable(false)
.show();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.activity = this;
//REQUIRED FOR API 23+ - REQUEST FOR PERMISSIONS - ONLY REQUIRED TO BE DONE ONCE PER APP INSTALL.
int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
this,
PERMISSIONS,
REQUEST_PERMISSIONS_CODE);
}else{
startApp();
}
}
public void startApp(){
gridView = (GridView)findViewById(R.id.image_grid);
list = imageReader(Environment.getExternalStorageDirectory());
gridView.setAdapter(new gridAdapter());
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, FullImageActivity.class);
intent.putExtra("img", list.get(i).toString());
startActivity(intent);
}
});
}
public class gridAdapter extends BaseAdapter {
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
View convertView = null;
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.row_layout, viewGroup, false);
ImageView myImage = (ImageView) convertView.findViewById(R.id.my_image);
myImage.setImageURI(Uri.parse(list.get(i).toString()));
}
return convertView;
}
}
private ArrayList<File> imageReader(File externalStorageDirectory) {
ArrayList<File> b = new ArrayList<>();
File[] files = externalStorageDirectory.listFiles();
for (int i =0; i<files.length; i++){
if (files[i].isDirectory()){
b.addAll(imageReader(files[i]));
}else {
if (files[i].getName().endsWith(".jpg")) {
b.add(files[i]);
}
}
}
return b;
}
}
推荐阅读
- git - 如何在不丢失原始哈希码和我应该提交的代码的情况下恢复 git commit --amend -m?
- python - 我在以下程序中遇到错误,因为 KeyError Traceback(最近一次调用最后一次)
- javascript - Next.js 刷新页面中断 css classNames
- python-3.x - Microsoft MSAL Resource Owner Password Credentials(ROPC) Grant 授权是否支持 ClientConfidentialApplicaton 类获取 Token?
- javascript - 为什么 setState 会导致我的 React 应用程序进入无限循环?
- peoplesoft - 是否有一个列表或方法来查找所有具有不同名称但包含相同数据的字段?
- python - 当我使用 selenium 时,我得到“StaleElementReferenceException: stale element reference: element is not attach to the page document”
- windows - 如何在 Visual Studio 等 VS Code 中进行块粘贴
- python - Geopandas - read_file() 函数通过共享网络非常慢。如何在不通过共享网络读取文件的情况下运行应用程序
- html - 当显示大小发生变化时,如何正确调整社交媒体图标的大小?