【发布时间】:2017-02-02 09:31:48
【问题描述】:
我是原生安卓开发的新手。我正在使用android studio 开发应用程序。我正在使用 tabbed-activity 并使用 3 个选项卡。所有 3 个选项卡都有单独的 classes 和 layouts,其名称如下图所示。
类和布局名称与图片中显示的相同。
我的标签有以下功能。
- 在第一个选项卡上,我实现了
google map v2,它显示了我当前的 gps 位置以及坐标和标记。 - 在第二个选项卡上,我实现了一个
camera,我在其中放置了一个按钮和一个image view。通过按下按钮,相机将显示,当我拍照时,它会在图像视图中显示我。这张图片也保存到我的SD CARD中。 - 在第三个也是最后一个选项卡中,我添加了一个
gird view,它将从SD CARD获取这些图像并将其显示在网格上。
对于third tab,我关注了tutorial,因此我分别制作了2 个helper 和1 个adapter 课程。 2 个辅助类是 AppConstant 和 Utils,适配器被命名为 GridViewImageAdapter,它扩展了 BaseAdapter。
以上所有 3 个(2 个帮助程序和 1 个适配器)类都导入到我的 pictures 类中。
现在,当我第一次运行该应用程序时,我可以看到我当前的位置。但是当我点击camera 选项卡时,它会转到Util 类,当它找不到任何文件时,应用程序就会崩溃。这不应该发生,因为我的 Util 类仅在 pictures 片段中导入,与 camera 片段无关。下面是代码部分
Camera.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.camera, container, false);
button = (Button)rootView.findViewById(R.id.getpicture);
imageView = (ImageView)rootView.findViewById(R.id.imageView);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Check permission for CAMERA
if (ActivityCompat.checkSelfPermission(getActivity(), CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
// Callback onRequestPermissionsResult interceptado na Activity MainActivity
ActivityCompat.requestPermissions(getActivity(),
new String[]{CAMERA},
Camera.REQUEST_CAMERA);
}
else {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE );
}
}
});
return rootView;
}
//For saving image(s)
private void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
Log.v(getTag(), root);
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir,fname);
if (file.exists())file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG,90,out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
//Toast.makeText(getContext(), "Image is saved", Toast.LENGTH_LONG).show();
}
下面是我的图片代码
Pictures.java
import com.example.accurat.faisal.adapter.GridViewImageAdapter;
import com.example.accurat.faisal.helper.Utils;
import com.example.accurat.faisal.helper.AppConstant;
//other imports
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.pictures, container, false);
gridView = (GridView)rootView.findViewById(R.id.grid_view);
utils = new Utils(getContext());
// Initilizing Grid View
InitilizeGridLayout();
// loading all image paths from SD card
imagePaths = utils.getFilePaths();
// Gridview adapter
adapter = new GridViewImageAdapter(getActivity(), imagePaths, columnWidth);
/*adapter = new GridViewImageAdapter(Pictures.this, imagePaths,
columnWidth);*/
// setting grid view adapter
gridView.setAdapter(adapter);
return rootView;
}
private void InitilizeGridLayout() {
Resources r = getResources();
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppConstant.GRID_PADDING, r.getDisplayMetrics());
columnWidth = (int) ((utils.getScreenWidth() - ((AppConstant.NUM_OF_COLUMNS + 1) * padding)) / AppConstant.NUM_OF_COLUMNS);
gridView.setNumColumns(AppConstant.NUM_OF_COLUMNS);
gridView.setColumnWidth(columnWidth);
gridView.setStretchMode(GridView.NO_STRETCH);
gridView.setPadding((int) padding, (int) padding, (int) padding,
(int) padding);
gridView.setHorizontalSpacing((int) padding);
gridView.setVerticalSpacing((int) padding);
}
上面的这个类将访问helper 和adapter 方法。帮助方法见下文
Utils.java
public class Utils {
// Reading file paths from SDCard
public ArrayList<String> getFilePaths() {
ArrayList<String> filePaths = new ArrayList<String>();
File directory = new File(
android.os.Environment.getExternalStorageDirectory(),AppConstant.PHOTO_ALBUM);
// check for directory
if (directory.isDirectory()) {
// getting list of file paths
File[] listFiles = directory.listFiles();
// Check for count
if (listFiles.length > 0) {
// loop through all files
for (int i = 0; i < listFiles.length; i++) {
// get file path
String filePath = listFiles[i].getAbsolutePath();
// check for supported file extension
if (IsSupportedFile(filePath)) {
// Add image path to array list
filePaths.add(filePath);
}
}
} else {
// image directory is empty
Toast.makeText(
_context,
AppConstant.PHOTO_ALBUM
+ " is empty. Please load some images in it !",
Toast.LENGTH_LONG).show();
}
} else {
AlertDialog.Builder alert = new AlertDialog.Builder(_context);
alert.setTitle("Error!");
alert.setMessage(AppConstant.PHOTO_ALBUM
+ " directory path is not valid! Please set the image directory name AppConstant.java class");
alert.setPositiveButton("OK", null);
alert.show();
}
return filePaths;
}
}
本课程中还有其他方法,但我只发布了上述方法,因为当我转到 pictures 选项卡时,首先调用此方法,它适用于图片选项卡,但当我转到 camera 时再次选项卡调用上述方法并且应该调用它,因为我的相机类中没有任何内容可以访问帮助程序类。我不知道为什么会这样,因为所有类都是分开的,所以它不应该像这样工作,我得到null exception
清单见下文
<uses-permission android:name="com.example.accurat.faisal.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
下面是错误
FATAL EXCEPTION: main
Process: com.example.accurat.faisal, PID: 25624
java.lang.NullPointerException: Attempt to get length of null array
at com.example.accurat.faisal.helper.Utils.getFilePaths(Utils.java:42)
at com.example.accurat.faisal.Pictures.onCreateView(Pictures.java:45)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1969)
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:620)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1268)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:668)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:630)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:611)
at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:2178)
at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1155)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1148)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1118)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1413)
at android.support.design.widget.TabLayout$TabView.performClick(TabLayout.java:1523)
at android.view.View$PerformClick.run(View.java:22596)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Utlis.java:42是
// check for directory
if (directory.isDirectory()) {
// getting list of file paths
File[] listFiles = directory.listFiles();
// Check for count
if (listFiles.length > 0) {// do the needful
而Pictures.java:42 是// loading all image paths from SD card
imagePaths = utils.getFilePaths();
更新 1
根据Mike M 和Ruben2112 的建议,我将READ_EXTERNAL_STORAGE 导入到我的每个助手和适配器类中,并在Utils 类中检查listFiles,如下所示
File directory = new File(
android.os.Environment.getExternalStorageDirectory(),AppConstant.PHOTO_ALBUM);
// check for directory
if (directory.isDirectory()) {
// getting list of file paths
File[] listFiles = directory.listFiles();
if (listFiles != null) {// Check for list files
// Check for count
if (listFiles.length > 0) {
// loop through all files
for (int i = 0; i < listFiles.length; i++) {
// get file path
String filePath = listFiles[i].getAbsolutePath();
// check for supported file extension
if (IsSupportedFile(filePath)) {
// Add image path to array list
filePaths.add(filePath);
}
}
} else {
// image directory is empty
Toast.makeText(
_context,
AppConstant.PHOTO_ALBUM
+ " is empty. Please load some images in it !",
Toast.LENGTH_LONG).show();
}
} else {
AlertDialog.Builder alert = new AlertDialog.Builder(_context);
alert.setTitle("Error!");
alert.setMessage(AppConstant.PHOTO_ALBUM
+ " directory path is not valid! Please set the image directory name AppConstant.java class");
alert.setPositiveButton("OK", null);
alert.show();
}
}
现在我的应用程序没有崩溃,但它仍然在警告框中显示错误,如下图所示
点击确定后,应用程序仍然运行
我坚持下去,不知道该怎么办。任何帮助将不胜感激。
【问题讨论】:
-
默认情况下,
ViewPager将加载下一个相邻页面,以便将它们拉到屏幕上。当您导航到第二个选项卡时,它正在准备第三页。查看您的Utils类,如果AppConstant.PHOTO_ALBUM确实是一个常量,它看起来无论如何都会崩溃。它崩溃了,因为directory.listFiles()返回 null。如果您在 Marshmallow 或更高版本上运行,您确定您已正确处理权限吗?READ_EXTERNAL_STORAGE是一个危险的权限。你需要请求它,就像你是CAMERA。 -
@MikeM。是的,我添加了权限检查。在棉花糖上,应用程序崩溃,但在 API utils 类并显示一个警告框。我想知道如何处理标签的切换
-
好的,我没有看到
READ_EXTERNAL_STORAGE权限的请求,所以我想我会指出来。无论如何,这就是您需要解决的问题,而不是标签切换。我很确定无论如何都会崩溃。我真的不认为这仅仅是因为您在第二页时加载了第三页。这是因为您无法读取PHOTO_ALBUM目录。 -
我的
Camera中有READ_EXTERNAL_STORAGE。此外,如果我创建一个文件夹并将其粘贴到我的设备上,那么该应用程序可以完美运行。 -
好的,我想我在关注你了。
AppConstant.PHOTO_ALBUM是"/saved_images"文件夹吗?如果是这样,那是因为第三页试图在第二页创建它之前访问该文件夹。你必须决定你想如何处理它。您可以预先请求所有权限,并尽快创建该文件夹。或者你可以推迟加载GridView;即,不要尝试将其加载到onCreateView()。
标签: java android android-fragments tabs camera