video/audio playback:setDataSource

本文详细解析了Android平台上实现音视频播放的过程,包括MediaPlayer组件的使用、不同类型的音视频文件处理方式、以及如何通过Stagefright播放器进行HTTP流媒体播放。

实现video/audio playerback,需要经过如下步骤:

MediaPlayer mp = new MediaPlayer();   

mp.setDataSource(String URL/FILE_PATH);   

mp.prepare();   

mp.start();

 

首先是setDataSource 创建player, 如果url是以content://形式的转换为FD,并提取出mAudioTrack/mVideoTrack保存起来,如果url是以http://之类的在线播放多媒体信息,需去下载SDP文件,找到url存储起来

1.framework/base/media/libmedia/ MediaPlayer.cpp

status_t MediaPlayer::setDataSource(

        const char *url, const KeyedVector<String8, String8> *headers) {

     (1)   const sp<IMediaPlayerService>& service(getMediaPlayerService()); ……首先获得mediaplayerService的服务

    if (service != 0) {

    2    sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));

    3  err = setDataSource(player);

    }

    return err;

}

2. framework/base/media/libmediaplayerservice/ MediaPlayerService.cpp

sp<IMediaPlayer> MediaPlayerService::create(

        pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,

        const KeyedVector<String8, String8> *headers, int audioSessionId)

{

….

    sp<Client> c = new Client(this, pid, connId, client, audioSessionId); …. 新建个mediaplayerservice client 的实例,即整个播放过程由这个实例控制

………

if (NO_ERROR != c->setDataSource(url, headers))…..create player setDataSource

    {

        c.clear();

        return c;

    }

   

}

 

status_t MediaPlayerService::Client::setDataSource(

        const char *url, const KeyedVector<String8, String8> *headers)

{….

如果是url content://开头要转换为file descriptor

    if (strncmp(url, "content://", 10) == 0) {…

        int fd = android::openContentProviderFile(url16);

……….

        setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus

        close(fd);

        return mStatus;

    } else {

        player_type playerType = getPlayerType(url);…. createplayer前要判断是哪种类型

        LOGV("player type = %d", playerType);

 

        // create the right type of player

        sp<MediaPlayerBase> p = createPlayer(playerType);

        mStatus = p->setDataSource(url, headers);

…       

return mStatus;

    }

}

 

player_type getPlayerType(const char* url) ……………. 根据url的后缀名判断属于哪种playerType,默认是stagefright

{

    if (TestPlayerStub::canBeUsed(url)) {

        return TEST_PLAYER;

    }

 

    // use MidiFile for MIDI extensions

    int lenURL = strlen(url);

    for (int i = 0; i < NELEM(FILE_EXTS); ++i) {

        int len = strlen(FILE_EXTS[i].extension);

        int start = lenURL - len;

        if (start > 0) {

            if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {

                return FILE_EXTS[i].playertype;

            }

        }

    }

……………….

    return getDefaultPlayerType();

}

 

有如下类型的playerType

 

typedef struct {

    const char *extension;

    const player_type playertype;

} extmap;

extmap FILE_EXTS [] =  {

        {".mid", SONIVOX_PLAYER},

        {".midi", SONIVOX_PLAYER},

        {".smf", SONIVOX_PLAYER},

        {".xmf", SONIVOX_PLAYER},

        {".mxmf", SONIVOX_PLAYER},

        {".imy", SONIVOX_PLAYER},

        {".rtttl", SONIVOX_PLAYER},

        {".rtx", SONIVOX_PLAYER},

        {".ota", SONIVOX_PLAYER},

        {".mnv", SOLS_PLAYER},

        {".mnvtmp", SOLS_PLAYER},

#ifndef NO_OPENCORE

        {".wma", PV_PLAYER},

        {".wmv", PV_PLAYER},

        {".asf", PV_PLAYER},

#endif

};

 

 sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)

{…….  if (p == NULL) {

        p = android::createPlayer(playerType, this, notify);

    }

    return p;

}

 

static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,

        notify_callback_f notifyFunc)

{

    sp<MediaPlayerBase> p;

    switch (playerType) {

#ifndef NO_OPENCORE

        case PV_PLAYER:

            LOGV(" create PVPlayer");

            p = new PVPlayer();

            break;

#endif

        case SONIVOX_PLAYER:

            LOGV(" create MidiFile");

            p = new MidiFile();

            break;

        case STAGEFRIGHT_PLAYER:

            LOGV(" create StagefrightPlayer");

            p = new StagefrightPlayer;   

            break;

        case TEST_PLAYER:

            LOGV("Create Test Player stub");

            p = new TestPlayerStub();

            break;

        case SOLS_PLAYER:

            LOGV(" create SolsStagefrightPlayer");

            p = new SolsStagefrightPlayer;

            break;

    }….

    return p;

}

 

3, framework/base/media/libmediaplayerservice/ StagefrightPlayer.cpp

创建stagefrightplayer实例也new了个AwesomePlayer(mPlayer)

StagefrightPlayer::StagefrightPlayer()

    : mPlayer(new AwesomePlayer) {

    LOGV("StagefrightPlayer");

 

    mPlayer->setListener(this);

}

4, framework/base/media/libStagefright/ AwesomePlayer.cpp

AwesomePlayer  setDataSource 根据传过来的是 url(http://..),还是fd进行不同的处理

url:记录下url  http request header , mediaextract ::finishSetDataSource_l 中进行。

status_t AwesomePlayer::setDataSource_l(

        const char *uri, const KeyedVector<String8, String8> *headers) {

    LOGV("setDataSource '%s'", uri);

    // Check for sdp

    status_t err;

    if (headers) {

        mUriHeaders = *headers;

    }…….

    if (extension.length() == 4 && !strncasecmp(extension.string(), ".sdp", 4)) {

        //found sdp

        if (!strncasecmp("http://", tmpString8Uri.string(), 7)) {

            LOGV("found SDP file over http");

            String8 newUri;

            err = getUriFromSDP(uri, &newUri);…………..Download SDP, parse and return found URI                    SDP:Service Data Point业务数据点

            if (err == OK) {

                return setDataSource_l(newUri.string(), headers);

            } else {

..

            }

        }

    }

    reset_l();

    mUri = uri;

    return OK;

}

FD 形式:根据FD 生成filesource ,后找到匹配的mediaextractor--->mVideoTrack/mAudioTrack

status_t AwesomePlayer::setDataSource(

        int fd, int64_t offset, int64_t length) {

    Mutex::Autolock autoLock(mLock);

    reset_l();

    sp<DataSource> dataSource = new FileSource(fd, offset, length);

…..

    return setDataSource_l(dataSource);

}

status_t AwesomePlayer::setDataSource_l(

        const sp<DataSource> &dataSource) {

    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);…….创建对应的extractor

…..

    return setDataSource_l(extractor);

}

status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {

        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {

            setVideoSource(extractor->getTrack(i)); ………>mVideoTrack

            haveVideo = true;

        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {

            setAudioSource(extractor->getTrack(i));……….>mAudioTrack

            haveAudio = true;

    return OK;

}

来自:video-audio playback:setDataSource - 太妃糖的专栏 - 博客频道 - youkuaiyun.com.mht
package com.weishitech.qmmfchangkge.fragment.home; import android.Manifest; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.AssetFileDescriptor; import android.media.MediaPlayer; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.provider.Settings; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.anythink.core.api.ATAdConst; import com.anythink.core.api.ATAdInfo; import com.anythink.core.api.ATNetworkConfirmInfo; import com.anythink.core.api.ATShowConfig; import com.anythink.core.api.AdError; import com.anythink.rewardvideo.api.ATRewardVideoAd; import com.anythink.rewardvideo.api.ATRewardVideoAutoAd; import com.anythink.rewardvideo.api.ATRewardVideoAutoEventListener; import com.anythink.rewardvideo.api.ATRewardVideoAutoLoadListener; import com.anythink.rewardvideo.api.ATRewardVideoExListener; import com.hfd.common.base.BaseFragment; import com.hfd.common.net.JsonUtil; import com.hfd.common.net.Url; import com.hfd.common.util.SPUtils; import com.hfd.common.util.ToastUtil; import com.weishitech.qmmfchangkge.LCAppcation; import com.weishitech.qmmfchangkge.MainActivity; import com.weishitech.qmmfchangkge.R; import com.weishitech.qmmfchangkge.ad.AdConst; import com.weishitech.qmmfchangkge.ad.util.SDKUtil; import com.weishitech.qmmfchangkge.bean.CloseSong; import com.weishitech.qmmfchangkge.bean.SongBean; import com.weishitech.qmmfchangkge.dialog.CustomBottomDialog; import com.weishitech.qmmfchangkge.dialog.PermissionDialog; import com.weishitech.qmmfchangkge.fragment.Adapter.SongAdapter; import com.weishitech.qmmfchangkge.utils.LocalData; import com.weishitech.qmmfchangkge.utils.PermissionUtils; import com.weishitech.qmmfchangkge.utils.RingtoneHelper; import com.weishitech.qmmfchangkge.utils.TimeUtil; import com.zhihu.matisse.Matisse; import com.zhihu.matisse.MimeType; import com.zhihu.matisse.engine.impl.GlideEngine; import com.zhihu.matisse.internal.entity.CaptureStrategy; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import pub.devrel.easypermissions.EasyPermissions; public class DataFragment extends BaseFragment implements SongAdapter.OnButtonClickListener,SongAdapter.OnIvClickListener,EasyPermissions.PermissionCallbacks { private static final String TAG = DataFragment.class.getSimpleName(); private static final String ARG_DATA = "data"; private static final String ARG_POSITION = "position"; private static final String ARG_TYPE = "type"; private ArrayList<SongBean> songBeanList; private int homePosition;//tab下标 private int savePosition;//下载下标 private int type;//区分弹框显示 RecyclerView rv; boolean topStart = false; // 条目播放器状态 private MediaPlayer mediaTopPlayer; // 条目播音 private int page = 0; private int pos;//音乐列表下标 private List<SongBean> songBeans; private List<SongBean> songBeans1; private List<SongBean> songBeans2; private List<SongBean> songBeans3; private List<SongBean> currentSongBeans; private AlertDialog progressDialog; private static final String[] PERMS_CAMERA = new String[] {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}; // 需要请求的权限数组 private static final int RC_CAMERA_PERM = 123; // 请求码,唯一标识 private static final int REQUEST_CODE_WRITE_SETTINGS = 101; //激励广告 private boolean onRewardedVideoAdPlayEnd = false;//激励视频是否播放完 private final Map<String, Boolean> mAutoLoadPlacementIdMap = new HashMap<>(); private ATRewardVideoAd mRewardVideoAd; private int ringtones; private ImageView ivBf; private SongAdapter songAdapter; public static DataFragment newInstance(ArrayList<SongBean> data, int position,int type) { DataFragment fragment = new DataFragment(); Bundle args = new Bundle(); args.putParcelableArrayList(ARG_DATA, data); args.putInt(ARG_POSITION, position); args.putInt(ARG_TYPE, type); fragment.setArguments(args); return fragment; } @Override protected int setLayout() { return R.layout.data_fragment; } @Override protected void initView() { rv = fvbi(R.id.rv); if (getArguments() != null) { songBeanList = getArguments().getParcelableArrayList(ARG_DATA); homePosition = getArguments().getInt(ARG_POSITION); type = getArguments().getInt(ARG_TYPE); songBeans = new ArrayList<>(); for (int i = 0; i < MainActivity.songBeans.size(); i++) { if (i > 6) { songBeans.add(MainActivity.songBeans.get(i)); } } songBeans1 = new ArrayList<>(); for (int i = 0; i < MainActivity.songBeans.size(); i++) { if (i > 4) { songBeans1.add(MainActivity.songBeans.get(i)); } } songBeans2 = new ArrayList<>(); for (int i = 0; i < MainActivity.songBeans.size(); i++) { if (i > 9) { songBeans2.add(MainActivity.songBeans.get(i)); } } songBeans3 = new ArrayList<>(); for (int i = 0; i < MainActivity.songBeans.size(); i++) { if (i > 5) { songBeans3.add(MainActivity.songBeans.get(i)); } } currentSongBeans = new ArrayList<>(); if (homePosition == 0) { currentSongBeans = songBeans; } else if (homePosition == 1) { currentSongBeans = songBeans1; } else if (homePosition == 2) { currentSongBeans = songBeans2; } else if (homePosition == 3) { currentSongBeans = songBeans3; } else { currentSongBeans = songBeanList; } songAdapter = new SongAdapter(getActivity(), currentSongBeans); rv.setLayoutManager(new LinearLayoutManager(getActivity())); rv.setAdapter(songAdapter); songAdapter.setOnButtonClickListener(this); // 设置监听器 songAdapter.setOnIvClickListener(this); rv.setNestedScrollingEnabled(false); // EventBus.getDefault().register(this); } } @Override protected void initClick() { } @Override protected void initData() { } private void prepareMediaPlayer(int pos) { if (mediaTopPlayer != null) { if (mediaTopPlayer.isPlaying()) { mediaTopPlayer.stop(); } mediaTopPlayer.reset(); mediaTopPlayer.release(); } mediaTopPlayer = new MediaPlayer(); try { // 设置数据源 AssetFileDescriptor afd = getActivity().getAssets().openFd(songBeans.get(pos).getSongFilePath()); mediaTopPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); mediaTopPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { Log.d("MusicPlayer", "MediaPlayer prepared, starting playback"); mp.start(); } }); mediaTopPlayer.prepareAsync(); } catch (IOException e) { Log.e("MusicPlayer", "Failed to prepare MediaPlayer: " + e.getMessage()); } } @Override public void onButtonClick(int position, ImageView iv_bf) { ivBf = iv_bf; pos = position; // if (topStart) { // iv_bf.setImageResource(R.mipmap.img_home_stop); // currentSongBeans.get(position).setIsStart(0); // topStart = false; // if (mediaTopPlayer != null && mediaTopPlayer.isPlaying()) { // mediaTopPlayer.pause(); // } // } else { // iv_bf.setImageResource(R.mipmap.img_home_start); // topStart = true; // currentSongBeans.get(position).setIsStart(1); // if (mediaTopPlayer == null ||!mediaTopPlayer.isPlaying()) { // prepareMediaPlayer(pos); // mediaTopPlayer.start(); // } // } for (int i = 0; i < songAdapter.getData().size(); i++) { if (i != position) { songAdapter.getData().get(i).setIsStart(0); } } if (songAdapter.getData().get(position).getIsStart() == 0) { songAdapter.getData().get(position).setIsStart(1); }else { songAdapter.getData().get(position).setIsStart(0); } if (mediaTopPlayer != null && mediaTopPlayer.isPlaying()) { mediaTopPlayer.stop(); mediaTopPlayer.reset(); mediaTopPlayer.release(); } prepareMediaPlayer(position); // if (topStart) { // topStart = false; // if (mediaTopPlayer != null && mediaTopPlayer.isPlaying()) { // mediaTopPlayer.pause(); // } // }else { // topStart = true; // if (mediaTopPlayer == null ||!mediaTopPlayer.isPlaying()) { // prepareMediaPlayer(position); // if (mediaTopPlayer.isPlaying()) { // Log.d("11111", "MediaPlayer is already playing"); // } else if (mediaTopPlayer.isLooping()) { // Log.d("11111", "MediaPlayer is looping"); // } else if (mediaTopPlayer.isPlaying()) { // Log.d("11111", "MediaPlayer is playing"); // } else { // Log.d("11111", "MediaPlayer is not playing"); // } // mediaTopPlayer.start(); // } // } songAdapter.notifyDataSetChanged(); } // @Subscribe(threadMode = ThreadMode.MAIN,sticky = true) @Override public void onIvClick(int position, ImageView iv_gd) { iv_gd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { CustomBottomDialog dialog = new CustomBottomDialog(getActivity()); dialog.setTitle(currentSongBeans.get(position).getSingName(),currentSongBeans.get(position).getSongName(),currentSongBeans.get(position).getIcon(),type,currentSongBeans.get(position).isCollected()); //下载点击 dialog.setOnDownloadClickListener(new CustomBottomDialog.OnDownloadClickListener() { @Override public void onDownloadClick() { savePosition = position; getSavePermissions(); } }); //收藏点击 dialog.setOnLikeClickListener(new CustomBottomDialog.OnLikeClickListener() { @Override public void onLikeClick() { SongBean songBean = currentSongBeans.get(position); boolean isCollected = songBean.isCollected(); List<SongBean> songBeanList = LocalData.getInstance().getOratoriList(); if (type == 0) { songBean.setType(0); if (homePosition == 0) { songBean.setPosition(position+7); }else if (homePosition == 1){ songBean.setPosition(position+5); }else if (homePosition == 2){ songBean.setPosition(position+10); }else if (homePosition == 3){ songBean.setPosition(position+6); }else { songBean.setPosition(position); } }else { songBean.setType(1); if (homePosition == 0) { songBean.setPosition(position+7); }else if (homePosition == 1){ songBean.setPosition(position+5); } } if (isCollected) { // 取消收藏 if (songBeanList != null) { songBeanList.removeIf(song -> song.getSongName().equals(songBean.getSongName())); SPUtils.setParam(Url.oratoriInfo, JsonUtil.toJson(songBeanList)); } songBean.setCollected(false); Toast.makeText(getActivity(), "取消收藏", Toast.LENGTH_SHORT).show(); } else { // 收藏 songBean.setCollected(true); if (songBeanList == null) { songBeanList = new ArrayList<>(); } songBeanList.add(songBean); SPUtils.setParam(Url.oratoriInfo, JsonUtil.toJson(songBeanList)); Toast.makeText(getActivity(), "收藏成功", Toast.LENGTH_SHORT).show(); } saveCollectedStatus(songBean); dialog.updateLikeStatus(songBean.isCollected()); initSongBeans(); // 确保调用该方法更新界面 } }); //设置铃声点击 dialog.setOnPhoneClickListener(new CustomBottomDialog.OnPhoneClickListener() { @Override public void onPhoneClick() { Toast.makeText(getActivity(), "设置铃声点击", Toast.LENGTH_SHORT).show(); ringtones = position; getPermissions(); } }); //K歌点击 dialog.setOnKgClickListener(new CustomBottomDialog.OnKgClickListener() { @Override public void onKgClick() { Toast.makeText(getActivity(), "K歌点击", Toast.LENGTH_SHORT).show(); if (homePosition == 0) { Bundle bundle = new Bundle(); bundle.putInt("index",position+7); toClass(SingActivity.class,bundle); }else if (homePosition == 1){ Bundle bundle = new Bundle(); bundle.putInt("index",position+5); toClass(SingActivity.class,bundle); }else if (homePosition == 2){ Bundle bundle = new Bundle(); bundle.putInt("index",position+10); toClass(SingActivity.class,bundle); }else if (homePosition == 3){ Bundle bundle = new Bundle(); bundle.putInt("index",position+6); toClass(SingActivity.class,bundle); }else { Bundle bundle = new Bundle(); bundle.putInt("index",position); toClass(SingActivity.class,bundle); } } }); //清唱点击 dialog.setOnQcClickListener(new CustomBottomDialog.OnQcClickListener() { @Override public void onQcClick() { Toast.makeText(getActivity(), "清唱点击", Toast.LENGTH_SHORT).show(); if (homePosition == 0) { Bundle bundle = new Bundle(); bundle.putInt("index",position+7); toClass(SingActivitys.class,bundle); }else if (homePosition == 1){ Bundle bundle = new Bundle(); bundle.putInt("index",position+5); toClass(SingActivitys.class,bundle); }else if (homePosition == 2){ Bundle bundle = new Bundle(); bundle.putInt("index",position+10); toClass(SingActivitys.class,bundle); }else if (homePosition == 3){ Bundle bundle = new Bundle(); bundle.putInt("index",position+6); toClass(SingActivitys.class,bundle); }else { Bundle bundle = new Bundle(); bundle.putInt("index",position); toClass(SingActivitys.class,bundle); } } }); dialog.show(); } }); } private void saveCollectedStatus(SongBean songBean) { SharedPreferences sharedPreferences = getActivity().getSharedPreferences("SongCollection", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean(songBean.getSongName(), songBean.isCollected()); editor.apply(); } private void initSongBeans() { SharedPreferences sharedPreferences = getActivity().getSharedPreferences("SongCollection", Context.MODE_PRIVATE); for (SongBean songBean : currentSongBeans) { boolean isCollected = sharedPreferences.getBoolean(songBean.getSongName(), false); songBean.setCollected(isCollected); } // 刷新适配器 SongAdapter songAdapter = (SongAdapter) rv.getAdapter(); if (songAdapter != null) { songAdapter.notifyDataSetChanged(); } } //保存歌曲到本地 private void save(int position) { // 显示正在保存的弹框 showProgressDialog(getActivity()); new SaveTask(position).execute(); } private void showProgressDialog(Context context) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage("正在保存..."); builder.setCancelable(false); progressDialog = builder.create(); progressDialog.show(); } private class SaveTask extends AsyncTask<Void, Void, Boolean> { private int position; private String targetPath; SaveTask(int position) { this.position = position; } @Override protected Boolean doInBackground(Void... voids) { targetPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath() + "/" + currentSongBeans.get(position).getSongName() + ".mp3"; try { InputStream inputStream = getActivity().getAssets().open(currentSongBeans.get(position).getSongFilePath()); FileOutputStream outStream = new FileOutputStream(new File(targetPath)); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outStream.write(buffer, 0, length); } outStream.flush(); outStream.close(); inputStream.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } @Override protected void onPostExecute(Boolean success) { // 关闭弹框 if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } if (success) { Toast.makeText(getActivity(), "音乐保存到本地成功" + targetPath, Toast.LENGTH_LONG).show(); } else { Toast.makeText(getActivity(), "音乐保存到本地失败", Toast.LENGTH_SHORT).show(); } } } @Override public void onStop() { super.onStop(); if (mediaTopPlayer != null) { mediaTopPlayer.stop(); mediaTopPlayer.release(); mediaTopPlayer = null; ivBf.setImageResource(R.mipmap.img_home_stop); } } @Override public void onDestroy() { super.onDestroy(); if (mediaTopPlayer != null) { if (mediaTopPlayer.isPlaying()) { mediaTopPlayer.stop(); } mediaTopPlayer.release(); mediaTopPlayer = null; } //激励广告 for (Map.Entry<String, Boolean> entry : mAutoLoadPlacementIdMap.entrySet()) { ATRewardVideoAutoAd.removePlacementId(entry.getKey()); } if (mRewardVideoAd != null) { mRewardVideoAd.setAdSourceStatusListener(null); mRewardVideoAd.setAdDownloadListener(null); mRewardVideoAd.setAdListener(null); mRewardVideoAd.setAdMultipleLoadedListener(null); } // EventBus.getDefault().unregister(this); } /** * 检查并请求权限 */ private void getPermissions(){ // 检查并请求权限 if (!EasyPermissions.hasPermissions(getContext(), PERMS_CAMERA)) { new PermissionDialog(getActivity(),"权限说明:由于设置铃声,需要相应的存储权限以及系统设置权限。拒绝将无法使用此功能").show(); EasyPermissions.requestPermissions(DataFragment.this, "需要相应的存储权限以及系统设置权限", RC_CAMERA_PERM, PERMS_CAMERA); } else { setRing(); } } private void getSavePermissions(){ // 检查并请求权限 if (!PermissionUtils.hasStoragePermissions(getActivity())) { new PermissionDialog(getActivity(),"权限说明:由于设置铃声,需要相应的存储权限以及系统设置权限。拒绝将无法使用此功能").show(); // EasyPermissions.requestPermissions(this, "需要相应的存储权限以及系统设置权限", RC_CAMERA_PERM, PERMS_CAMERA); PermissionUtils.requestStoragePermissions(getActivity(),RC_CAMERA_PERM); } else { save(savePosition); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); } @Override public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) { if(requestCode == RC_CAMERA_PERM){ setRing(); } } @Override public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) { } private boolean checkWriteSettingsPermission() { if (!Settings.System.canWrite(getActivity())) { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getActivity().getPackageName())); startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS); return false; } return true; } private void setRing(){ if (checkWriteSettingsPermission()) { onRewardedVideoAdPlayEnd = false; if(LCAppcation.getInstance().isShowAd(53)){ initJlAutoLoad(); initJlRewardVideoAd(LCAppcation.rewardVideoAdId); isJlAdReady(); new Handler().postDelayed(() -> { ATRewardVideoAd.entryAdScenario(LCAppcation.rewardVideoAdId, AdConst.SCENARIO_ID.REWARD_VIDEO_AD_SCENARIO); if (mRewardVideoAd != null && mRewardVideoAd.isAdReady()) { showJlAd(); } else { //printLogOnUI(getString(R.string.anythink_ad_status_not_load)); } }, 1000); // 延时2000毫秒(2秒)后跳转 }else{ RingtoneHelper.setRingtone(getActivity(),ringtones); } } } //激励广告 private ATShowConfig getJlATShowConfig() { ATShowConfig.Builder builder = new ATShowConfig.Builder(); builder.scenarioId(AdConst.SCENARIO_ID.REWARD_VIDEO_AD_SCENARIO); builder.showCustomExt(AdConst.SHOW_CUSTOM_EXT.REWARD_VIDEO_AD_SHOW_CUSTOM_EXT); return builder.build(); } private void initJlRewardVideoAd(String placementId) { mRewardVideoAd = new ATRewardVideoAd(getActivity(), placementId); mRewardVideoAd.setAdRevenueListener(new com.weishitech.qmmfchangkge.ad.base.BaseActivity.AdRevenueListenerImpl()); mRewardVideoAd.setAdListener(new ATRewardVideoExListener() { @Override public void onDeeplinkCallback(ATAdInfo adInfo, boolean isSuccess) { Log.i(TAG, "onDeeplinkCallback:" + adInfo.toString() + "--status:" + isSuccess); } @Override public void onDownloadConfirm(Context context, ATAdInfo adInfo, ATNetworkConfirmInfo networkConfirmInfo) { Log.i(TAG, "onDownloadConfirm: " + adInfo.toString()); } //-------------------------- Only for CSJ -------------------------- @Override public void onRewardedVideoAdAgainPlayStart(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdAgainPlayStart:\n" + entity.toString()); } @Override public void onRewardedVideoAdAgainPlayEnd(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdAgainPlayEnd:\n" + entity.toString()); } @Override public void onRewardedVideoAdAgainPlayFailed(AdError errorCode, ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdAgainPlayFailed error: " + errorCode.getFullErrorInfo()); } @Override public void onRewardedVideoAdAgainPlayClicked(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdAgainPlayClicked: " + entity.toString()); } @Override public void onAgainReward(ATAdInfo entity) { Log.i(TAG, "onAgainReward:\n" + entity.toString()); printRewardInfo("onAgainReward rewardInfo", entity); } @Override public void onAgainRewardFailed(ATAdInfo entity) { Log.i(TAG, "onAgainRewardFailed:\n" + entity.toString()); printRewardInfo("onAgainRewardFailed rewardInfo", entity); } //-------------------------- Only for CSJ -------------------------- @Override public void onRewardedVideoAdLoaded() { Log.i(TAG, "onRewardedVideoAdLoaded"); } @Override public void onRewardedVideoAdFailed(AdError errorCode) { Log.i(TAG, "onRewardedVideoAdFailed error:" + errorCode.getFullErrorInfo()); } @Override public void onRewardedVideoAdPlayStart(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdPlayStart:\n" + entity.toString()); } @Override public void onRewardedVideoAdPlayEnd(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdPlayEnd:\n" + entity.toString()); } @Override public void onRewardedVideoAdPlayFailed(AdError errorCode, ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdPlayFailed:\n" + entity.toString()); } @Override public void onRewardedVideoAdClosed(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdClosed:\n" + entity.toString()); } @Override public void onRewardedVideoAdPlayClicked(ATAdInfo entity) { Log.i(TAG, "onRewardedVideoAdPlayClicked:\n" + entity.toString()); } @Override public void onReward(ATAdInfo entity) { Log.e(TAG, "onReward:\n" + entity.toString()); printRewardInfo("onReward rewardInfo", entity); } @Override public void onRewardFailed(ATAdInfo entity) { Log.i(TAG, "onRewardFailed:\n" + entity.toString()); printRewardInfo("onRewardFailed rewardInfo", entity); } }); mRewardVideoAd.setAdSourceStatusListener(new com.weishitech.qmmfchangkge.ad.base.BaseActivity.ATAdSourceStatusListenerImpl()); } final ATRewardVideoAutoEventListener autoEventListener = new ATRewardVideoAutoEventListener() { @Override public void onRewardedVideoAdPlayStart(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdPlayStart:\n" + adInfo.toString()); MainActivity.reportInfo(adInfo); } @Override public void onRewardedVideoAdPlayEnd(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdPlayEnd1:\n" + adInfo.toString()); onRewardedVideoAdPlayEnd = true; } @Override public void onRewardedVideoAdPlayFailed(AdError errorCode, ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdPlayFailed:\n" + adInfo.toString()); } @Override public void onRewardedVideoAdClosed(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdClosed:\n" + adInfo.toString()); if(onRewardedVideoAdPlayEnd){ RingtoneHelper.setRingtone(getActivity(),ringtones); } } @Override public void onRewardedVideoAdPlayClicked(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdPlayClicked:\n" + adInfo.toString()); } @Override public void onReward(ATAdInfo adInfo) { Log.e(TAG, "onReward:\n" + adInfo.toString()); printRewardInfo("onReward rewardInfo", adInfo); } @Override public void onRewardFailed(ATAdInfo adInfo) { Log.e(TAG, "onRewardFailed:\n" + adInfo.toString()); printRewardInfo("onRewardFailed rewardInfo", adInfo); } public void onDeeplinkCallback(ATAdInfo adInfo, boolean isSuccess) { Log.i(TAG, "onDeeplinkCallback:\n" + adInfo.toString() + "| isSuccess:" + isSuccess); } public void onDownloadConfirm(Context context, ATAdInfo adInfo, ATNetworkConfirmInfo networkConfirmInfo) { Log.i(TAG, "onDownloadConfirm:\n" + adInfo.toString()); } //again listener public void onRewardedVideoAdAgainPlayStart(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdAgainPlayStart:\n" + adInfo.toString()); } public void onRewardedVideoAdAgainPlayEnd(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdAgainPlayEnd:\n" + adInfo.toString()); } public void onRewardedVideoAdAgainPlayFailed(AdError adError, ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdAgainPlayFailed:\n" + adInfo.toString() + "|error:" + adError.getFullErrorInfo()); } public void onRewardedVideoAdAgainPlayClicked(ATAdInfo adInfo) { Log.i(TAG, "onRewardedVideoAdAgainPlayClicked:\n" + adInfo.toString()); } public void onAgainReward(ATAdInfo adInfo) { Log.i(TAG, "onAgainReward:\n" + adInfo.toString()); printRewardInfo("onAgainReward rewardInfo", adInfo); } @Override public void onAgainRewardFailed(ATAdInfo adInfo) { Log.i(TAG, "onAgainRewardFailed:\n" + adInfo.toString()); printRewardInfo("onAgainRewardFailed rewardInfo", adInfo); } }; private void initJlAutoLoad() { ATRewardVideoAutoAd.init(getActivity(), null, autoLoadListener); mAutoLoadPlacementIdMap.put(LCAppcation.rewardVideoAdId, true); ATRewardVideoAutoAd.addPlacementId(LCAppcation.rewardVideoAdId); } private void loadAd() { SDKUtil.initSDK(getActivity()); if (mRewardVideoAd == null) { return; } String userid = "test_userid_001"; String userdata = "test_userdata_001"; Map<String, Object> localMap = new HashMap<>(); localMap.put(ATAdConst.KEY.USER_ID, userid); localMap.put(ATAdConst.KEY.USER_CUSTOM_DATA, userdata); mRewardVideoAd.setLocalExtra(localMap); mRewardVideoAd.load(); } private void isJlAdReady() { if (mRewardVideoAd == null) { return; } ATRewardVideoAutoAd.isAdReady(LCAppcation.rewardVideoAdId); } private void showJlAd() { //mRewardVideoAd.show(RewardVideoAdActivity.this); //mRewardVideoAd.show(OratoriEndActivity.this, getATShowConfig()); ATRewardVideoAutoAd.show(getActivity(), LCAppcation.rewardVideoAdId, getJlATShowConfig(), autoEventListener, new com.weishitech.qmmfchangkge.ad.base.BaseActivity.AdRevenueListenerImpl()); } public static void initPlacementIdLocalExtra(String placementId) { String userid = "test_userid_001"; String userdata = "test_userdata_001_" + placementId + "_" + System.currentTimeMillis(); Map<String, Object> localMap = new HashMap<>(); localMap.put(ATAdConst.KEY.USER_ID, userid); localMap.put(ATAdConst.KEY.USER_CUSTOM_DATA, userdata); Log.i(TAG, "Set PlacementId:" + placementId + ": UserId:" + userid + "| userdata:" + userdata); ATRewardVideoAutoAd.setLocalExtra(placementId, localMap); } public final ATRewardVideoAutoLoadListener autoLoadListener = new ATRewardVideoAutoLoadListener() { @Override public void onRewardVideoAutoLoaded(String placementId) { placementId = LCAppcation.rewardVideoAdId; initPlacementIdLocalExtra(placementId); Log.i(TAG, "PlacementId:" + placementId + ": onRewardVideoAutoLoaded"); } @Override public void onRewardVideoAutoLoadFail(String placementId, AdError adError) { Log.i(TAG, "PlacementId:" + placementId + ": onRewardVideoAutoLoadFail:\n" + adError.getFullErrorInfo()); } }; private static void printRewardInfo(String msg, ATAdInfo entity) { Map<String, Object> extInfoMap = entity.getExtInfoMap(); if (extInfoMap != null) { Object rewardInfoObj = extInfoMap.get(ATAdConst.REWARD_EXTRA.REWARD_INFO); if (rewardInfoObj instanceof Map) { Map<String, Object> rewardMap = (Map<String, Object>) rewardInfoObj; for (Map.Entry<String, Object> stringObjectEntry : rewardMap.entrySet()) { String key = stringObjectEntry.getKey(); Object value = stringObjectEntry.getValue(); Log.e(TAG, msg + ": key=" + key + ", value=" + value); } } } } } 这样写报错 java.lang.IllegalStateException
最新发布
11-08
在 Android 代码中使用 `MediaPlayer` 时出现 `java.lang.IllegalStateException` 错误,通常是由于调用方法的时机或者状态不对造成的。以下是针对不同情况的解决办法: #### 调用 `prepare()` 或 `prepareAsync()` 时出错 若在调用 `prepare()` 或 `prepareAsync()` 方法时出现 `IllegalStateException`,往往是因为 `MediaPlayer` 未正确设置数据源或者处于错误状态。要保证在调用这两个方法之前,已经成功调用 `setDataSource()` 方法。 ```java MediaPlayer mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource("your_audio_file_path"); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); mediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); } ``` #### 调用 `setDataSource()` 时出错 当第二次调用 `setDataSource()` 方法时出现 `IllegalStateException`,可能是因为 `MediaPlayer` 没有正确重置。在调用 `setDataSource()` 之前,要先调用 `reset()` 方法。 ```java MediaPlayer mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource("first_audio_file_path"); mediaPlayer.prepare(); mediaPlayer.start(); mediaPlayer.stop(); mediaPlayer.reset(); mediaPlayer.setDataSource("second_audio_file_path"); mediaPlayer.prepare(); mediaPlayer.start(); } catch (IOException e) { e.printStackTrace(); } ``` #### 调用其他方法时出错 在调用 `getCurrentPosition()`、`seekTo()` 等方法时出现 `IllegalStateException`,可能是因为 `MediaPlayer` 处于错误状态。要确保在调用这些方法之前,`MediaPlayer` 已经处于准备好或者正在播放的状态。 ```java if (mediaPlayer.isPlaying()) { int currentPosition = mediaPlayer.getCurrentPosition(); // 其他操作 } ``` #### 渲染控件问题 若使用自定义 `SurfaceView` 子类作为渲染控件,调用 `MediaPlayer.setDisplay()` 时可能会出现问题。可以尝试更换渲染控件,例如使用 `SurfaceView.getHolder()` 作为数据渲染控件[^4]。 ```java SurfaceView surfaceView = findViewById(R.id.surfaceView); SurfaceHolder surfaceHolder = surfaceView.getHolder(); mediaPlayer.setDisplay(surfaceHolder); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值