activity не запускается в Android 9, но хорошо работает в более низкой версии Android

#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. Спасибо за ваш ответ, он работает после удаления этой библиотеки. Еще раз спасибо