#java #android #android-studio #exception #nullpointerexception
#java #Android #android-studio #исключение #исключение nullpointerexception
Вопрос:
Я создал приложение, которое хорошо работает на более низких версиях Android, но показывает исключение для основной активности activity, которую я наследую от базовой активности в Android 9 после обновления. Это приложение отлично работает на Android 4.
Любое предложение приветствуется
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.owaisqadri, PID: 16322
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.owaisqadri/com.owaisqadri.playaudio.activities.MainActivityAudio}: android.view.InflateException: Binary XML file line #17 in com.owaisqadri:layout/abc_screen_simple: Binary XML file line #17 in com.owaisqadri:layout/abc_screen_simple: Error inflating class androidx.appcompat.widget.FitWindowsLinearLayout
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: android.view.InflateException: Binary XML file line #17 in com.owaisqadri:layout/abc_screen_simple: Binary XML file line #17 in com.owaisqadri:layout/abc_screen_simple: Error inflating class androidx.appcompat.widget.FitWindowsLinearLayout
Caused by: android.view.InflateException: Binary XML file line #17 in com.owaisqadri:layout/abc_screen_simple: Error inflating class androidx.appcompat.widget.FitWindowsLinearLayout
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Field.get(java.lang.Object)' on a null object reference
at uk.co.chrisjenx.calligraphy.ReflectionUtils.getValue(ReflectionUtils.java:29)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.createCustomViewInternal(CalligraphyLayoutInflater.java:203)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.access$000(CalligraphyLayoutInflater.java:20)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(CalligraphyLayoutInflater.java:302)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:239)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1069)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:997)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
at android.view.LayoutInflater.inflate(LayoutInflater.java:659)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(CalligraphyLayoutInflater.java:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:920)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:806)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:693)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:170)
at com.owaisqadri.playaudio.activities.BaseActivityAudio.onCreate(BaseActivityAudio.java:36)
at com.owaisqadri.playaudio.activities.MainActivityAudio.onCreate(MainActivityAudio.java:76)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
E/AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Моя активность
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageSwitcher;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.owaisqadri.playaudio.adapters.SlidePagerAdapter;
import com.owaisqadri.R;
import com.owaisqadri.playaudio.services.MediaService;
import com.owaisqadri.playaudio.models.Song;
import com.owaisqadri.playaudio.dataloaders.SongLoader;
import com.owaisqadri.playaudio.utils.Constants;
import com.owaisqadri.playaudio.utils.MediaControlUtils;
import com.owaisqadri.playaudio.utils.MediaDataUtils;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.PicassoTools;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
public class MainActivityAudio extends BaseActivityAudio {
private static final String TAG = MainActivityAudio.class.getName();
private final Activity activity = this;
private SeekBar progressBar;
private ImageSwitcher songPlayButton;
private ViewPager viewPager;
private Thread getSongs;
private List<Song> songList;
private Handler handler;
TextView title;
private boolean isChanging;
private boolean musicBound;
private long albumId;
public MainActivityAudio() {
super(R.layout.activity_main_audio);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// External storage permissions
getPermissions();
// Get data
getData();
// Setup player
initPlayer();
// Initial fragment
waitForData();
initMainView();
}
@Override
protected void onStart() {
super.onStart();
// Setup songbar
initSongbar();
}
private void getPermissions() {
if (Build.VERSION.SDK_INT < 23) {
Log.d(TAG, "Don't need permissions.");
} else {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
Log.d(TAG, "PERMISSIONS: App needs permissions to read external storage.");
}
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
}
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Log.d(TAG, "PERMISSIONS: App needs permissions to read external storage.");
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
}
}
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
private void getData() {
// Multi-thread for performance
getSongs = new Thread(new Runnable() {
@Override
public void run() {
songList = SongLoader.getSongList(activity);
}
});
getSongs.start();
}
private void initPlayer() {
MediaControlUtils.initController(this);
}
@SuppressLint("NewApi")
private void initSongbar() {
// Get the song bar
progressBar = findViewById(R.id.songbar_progress);
progressBar.getProgressDrawable().setColorFilter(getResources().getColor(R.color.red), PorterDuff.Mode.SRC_IN);
progressBar.getThumb().setColorFilter(getResources().getColor(R.color.red), PorterDuff.Mode.SRC_IN);
songPlayButton = findViewById(R.id.songbar_play);
songPlayButton.setBackgroundResource(R.drawable.ic_pause);
musicBound = true;
// Add play button listener
songPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (musicBound) {
MediaControlUtils.pause(activity);
songPlayButton.setBackgroundResource(R.drawable.ic_play);
} else {
MediaControlUtils.start(activity);
songPlayButton.setBackgroundResource(R.drawable.ic_pause);
}
}
});
// Receive changes in bar
progressBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar sb, int position, boolean userPressed) {
if (userPressed) {
MediaControlUtils.seek(activity, position);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
isChanging = true;
MediaControlUtils.pause(activity);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
MediaControlUtils.start(activity);
songPlayButton.setBackgroundResource(R.drawable.ic_pause);
isChanging = false;
}
});
// Get receiver
handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
// Get music status
boolean status = MediaService.getStatus();
if (musicBound != status amp;amp; !isChanging) {
if (status) {
songPlayButton.setBackgroundResource(R.drawable.ic_pause);
} else {
songPlayButton.setBackgroundResource(R.drawable.ic_play);
}
}
musicBound = status;
// Update if different song
long tempSong = MediaService.getCurrSong();
if (tempSong != currSong) {
currSong = tempSong;
}
// Set location based on position/duration
int songPosition = MediaService.getSongPos();
int songDuration = MediaService.getSongDur();
if (!isChanging amp;amp; songPosition != Constants.MEDIA_ERROR amp;amp; songDuration != Constants.MEDIA_ERROR) {
progressBar.setMax(songDuration);
progressBar.setProgress(songPosition);
// Set new text in time
String songPositionTime = String.format(
Locale.US, "d:d",
TimeUnit.MILLISECONDS.toMinutes(songPosition),
TimeUnit.MILLISECONDS.toSeconds(songPosition) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(songPosition))
);
String songDurationTime = String.format(
Locale.US, "d:d",
TimeUnit.MILLISECONDS.toMinutes(songDuration),
TimeUnit.MILLISECONDS.toSeconds(songDuration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(songDuration))
);
String totalSongTime = songPositionTime "/" songDurationTime;
TextView songTimeView = findViewById(R.id.songbar_time);
songTimeView.setText(totalSongTime);
}
} catch (Exception ignored) {}
handler.postDelayed(this, Constants.HANDLER_DELAY);
}
}, Constants.HANDLER_DELAY);
}
private void waitForData() {
// Join threads
try {
getSongs.join();
} catch (Exception e) {
e.printStackTrace();
}
}
private void initMainView() {
// Init views
viewPager = findViewById(R.id.headers);
PagerAdapter pagerAdapter = new SlidePagerAdapter(getSupportFragmentManager(), this);
viewPager.setAdapter(pagerAdapter);
// Give tab layout
//FontTabLayout tabLayout = (FontTabLayout) findViewById(R.id.slider);
//tabLayout.setupWithViewPager(viewPager);
// Set title
//MainActivityAudio.this.setTitle();
title = findViewById(R.id.title_top);
Typeface tf = ResourcesCompat.getFont(this,R.font.jameel);
title.setText("آڈیو کولیکشن");
title.setTypeface(tf);
}
public void updateContent() {
Log.d(TAG, "Updating content.");
runOnUiThread(new Runnable() {
@Override
public void run() {
Objects.requireNonNull(viewPager.getAdapter()).notifyDataSetChanged();
}
});
}
public void updateAll() {
Log.d(TAG, "Updating all.");
runOnUiThread(new Runnable() {
@Override
public void run() {
// Get data
getData();
waitForData();
// Update adapter
Objects.requireNonNull(viewPager.getAdapter()).notifyDataSetChanged();
}
});
}
public void updateNew(final String path, final String url) {
Log.d(TAG, "Updating new.");
runOnUiThread(new Runnable() {
@Override
public void run() {
// Get data
Log.e(TAG, "Updating on UI thread.");
getData();
waitForData();
// Update individual song
//for (Song song: songList) {
// if (song.getPath().equals(path)) {
// Log.e(TAG, "Updating new song metadata: " song.getName() " " Long.toString(song.getAlbumId()));
// MediaDataUtils.updateSongMetadata(song.getId(), song.getAlbumId(), url, path, activity);
// break;
// }
//}
// Update adapter
getData();
waitForData();
Objects.requireNonNull(viewPager.getAdapter()).notifyDataSetChanged();
}
});
}
public void choosePhoto(long id) {
albumId = id;
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), Constants.RESULT_CHOOSE_ALBUM_COVER);
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Update main activity request
if (requestCode == Constants.RESULT_UPDATE_ACTIVITY amp;amp; resultCode == RESULT_OK) {
if (data != null) {
boolean change = data.getBooleanExtra(Constants.RESULT_DEFAULT, false);
if (change) {
updateAll();
}
}
}
// Change photo request
if (requestCode == Constants.RESULT_CHOOSE_ALBUM_COVER amp;amp; resultCode == RESULT_OK) {
if (data != null) {
Uri uri = data.getData();
String[] file = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(Objects.requireNonNull(uri), file, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
String path = cursor.getString(cursor.getColumnIndex(file[0]));
cursor.close();
MediaDataUtils.changeAlbumArt(path, albumId, getApplicationContext());
updateAll();
}
} else {
Log.e(TAG, "Error, no data.");
}
}
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
public List<Song> getSongList() {
return songList;
}
public long getCurrSong() {
return currSong;
}
public void setMusicBound(boolean bound) {
this.musicBound = bound;
}
@Override
public void onDestroy() {
PicassoTools.clearCache(Picasso.get());
super.onDestroy();
}
@Override public View onCreateView(@NonNull View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
if (name.equals("androidx.appcompat.view.menu.ListMenuItemView") amp;amp;
parent.getParent() instanceof FrameLayout) {
((View) parent.getParent()).setBackgroundColor(Color.WHITE);
}
return super.onCreateView(parent, name, context, attrs);
}
}
базовая активность — это то, от чего унаследовано приложение
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.owaisqadri.R;
import com.owaisqadri.playaudio.utils.Constants;
import java.util.Objects;
import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
public abstract class BaseActivityAudio extends AppCompatActivity {
protected int id;
protected long currSong;
protected Toolbar toolbar;
public BaseActivityAudio(int id) {
this.id = id;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add fonts
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath(Constants.FONT_PATH)
.setFontAttrId(R.attr.fontPath)
.build());
setContentView(id);
// Setup the toolbar
initToolbar();
}
protected void initToolbar() {
// Init toolbar
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
}
и xml, который я использовал, это
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="ContentDescription"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- Container -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Toolbar -->
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
app:elevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null">
<androidx.appcompat.widget.Toolbar
android:id="@ id/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#251868" />
<View
android:id="@ id/view"
android:layout_width="match_parent"
android:layout_height="7dp"
android:layout_below="@ id/toolbar"
android:background="#FDDF58" />
<ImageView
android:id="@ id/icon"
android:layout_width="72dp"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentStart="false"
android:layout_centerVertical="true"
android:src="@drawable/launcher" />
<TextView
android:id="@ id/title_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginStart="120dp"
android:ellipsize="end"
android:fontFamily="@font/jameel"
android:gravity="center"
android:maxLines="1"
android:textColor="#fff"
android:textSize="20sp" />
</RelativeLayout>
</com.google.android.material.appbar.AppBarLayout>
<!-- Fragment holding frame -->
<androidx.viewpager.widget.ViewPager
android:id="@ id/headers"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@drawable/back1"
android:layout_weight="1"/>
<!-- Song bar -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
android:background="#636363">
<ImageSwitcher
android:id="@ id/songbar_play"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical"
android:background="@drawable/ic_play"/>
<SeekBar
android:id="@ id/songbar_progress"
android:gravity="center_vertical"
android:layout_height="48dp"
android:layout_width="0dp"
android:layout_weight="1"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
<TextView
android:id="@ id/songbar_time"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center_vertical|end"
android:textColor="@android:color/white"
android:text="@string/song_default_time"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
Я много пробовал, но безуспешно, я новичок в Android. Пожалуйста, предложите какое-нибудь решение, спасибо
Комментарии:
1. Вы используете библиотеку, которая была прекращена три года назад . Пожалуйста, подумайте о том, чтобы либо переключиться на его замену , либо сделать что-то еще для пользовательских шрифтов.
2. Спасибо за ваш ответ, он работает после удаления этой библиотеки. Еще раз спасибо