Я новичок в разработке для Android. Я использую android studio
для разработки приложения. Я использую tabbed-activity
и используя 3 вкладки. Все 3 вкладки имеют отдельные classes
и layouts
со следующими именами, как показано на рисунке ниже.Вкладки не работают должным образом при переключении в студию android
Классы и макеты имя такие же, как показано на рисунке.
Мои вкладки имеют следующие функции.
- На первой вкладке я внедрил
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();
Update 1
После предложений Mike M
и Ruben2112
я ввезенных READ_EXTERNAL_STORAGE
к каждому из моих помощников и адаптер класса, а также размещены чек на listFiles
в Utils
класса, как показано ниже
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 <20 приложение не будет разбиваться, но все же оно переходит в класс 'utils' и отображает окно предупреждения. Я хочу знать, как обрабатывать переключение вкладок – faisal1208
ОК, я не вижу запроса на разрешение READ_EXTERNAL_STORAGE, поэтому я решил указать на это. Во всяком случае, это то, что вам нужно исправить, а не переключение табуляции. Я почти уверен, что это произойдет, несмотря ни на что. Я действительно не думаю, что это просто потому, что третья страница загружается, пока вы на втором. Это потому, что вы не можете прочитать каталог 'PHOTO_ALBUM'. –