英文:
NullPointerException: Getting data from Database ((java.lang.String)' on a null object reference)
问题
我已经为您翻译了您提供的内容,请查阅:
我已经创建了一个数据库来存储ExoPlayer的播放进度,所以当用户尝试播放相同的内容时,如果在数据库中存在该内容,它会要求用户恢复播放或重新开始,但是会出现NullPointerException错误。
这是数据库部分:
public class DatabaseHelper extends SQLiteOpenHelper {
// ... (其余代码)
public String getEpisodeData(String string2) {
SQLiteDatabase sQLiteDatabase = this.getReadableDatabase();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("SELECT * FROM episode_data WHERE id= ");
stringBuilder.append(string2);
Cursor cursor = sQLiteDatabase.rawQuery(stringBuilder.toString(), null);
String string3 = null;
if (cursor != null) {
boolean bl = cursor.moveToLast();
string3 = null;
if (bl) {
string3 = cursor.getString(cursor.getColumnIndex("timestamp"));
}
cursor.close();
}
return string3;
}
// ... (其余代码)
}
在存储数据并且可能崩溃的活动:
public class ShowsDetailsActivity extends AppCompatActivity {
// ... (其余代码)
private void showResumeAlert() {
new AlertDialog.Builder(this)
.setTitle("您想要从上次离开的地方继续播放吗?")
.setPositiveButton("继续", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String getPlayed = databaseHelper.getEpisodeData(episodeid);
if (getPlayed != null) {
player.seekTo(Long.parseLong(getPlayed));
player.setPlayWhenReady(true);
}
}
})
.setNegativeButton("重新开始", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
player.setPlayWhenReady(true);
}
})
.setCancelable(false)
.show();
}
// ... (其余代码)
}
适配器部分:
public class DirectorApater extends RecyclerView.Adapter<DirectorApater.OriginalViewHolder> {
// ... (其余代码)
@Override
public void onBindViewHolder(final DirectorApater.OriginalViewHolder holder, final int position) {
final EpiModel obj = items.get(position);
holder.llEpi.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectedPosition=position;
notifyDataSetChanged();
((ShowsDetailsActivity)ctx).setMediaUrlForTvSeries(obj.getStreamURL(), obj.getSeson(), obj.getEpi(), obj.getEpisode_id());
String getPlayed = databaseHelper.getEpisodeData(episodeid);
if (getPlayed != null) {
((ShowsDetailsActivity)ctx).showResumeAlert();
return;
}
if (!castSession) {
new ShowsDetailsActivity().iniMoviePlayerForEpisode(obj,ctx);
} else {
((ShowsDetailsActivity)ctx).showQueuePopup(ctx, holder.llEpi, ((ShowsDetailsActivity)ctx).getMediaInfo());
}
}
});
// ... (其余代码)
}
// ... (其余代码)
}
希望这些翻译对您有所帮助。如果您有任何疑问,请随时问我。
英文:
I've created a database to store ExoPlayer's seek time so when the user tries to play the same content, if it is in the database, then it will ask the user to resume or start again but getting NullPointerException.
Here's the Database:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "mydata.db";
private static final String EPISODE_TABLE_NAME = "episode_data";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_EPISODE_DATA_TABLE());
}
private String CREATE_EPISODE_DATA_TABLE() {
return "CREATE TABLE IF NOT EXISTS episode_data (id TEXT,timestamp TEXT)";
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS episode_data");
onCreate(db);
}
public String getEpisodeData(String string2) {
SQLiteDatabase sQLiteDatabase = this.getReadableDatabase();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("SELECT * FROM episode_data WHERE id= ");
stringBuilder.append(string2);
Cursor cursor = sQLiteDatabase.rawQuery(stringBuilder.toString(), null);
String string3 = null;
if (cursor != null) {
boolean bl = cursor.moveToLast();
string3 = null;
if (bl) {
string3 = cursor.getString(cursor.getColumnIndex("timestamp"));
}
cursor.close();
}
return string3;
}
public long insertEpisodeData(String string2, String string3) {
SQLiteDatabase sQLiteDatabase = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("id", string2);
contentValues.put("timestamp", string3);
long l = sQLiteDatabase.replace(EPISODE_TABLE_NAME, null, contentValues);
sQLiteDatabase.close();
return l;
}
}
The activity where it stores the data from and also crashes:
public class ShowsDetailsActivity extends AppCompatActivity {
public String episodeid;
DatabaseHelper databaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_series_details);
databaseHelper = new DatabaseHelper(this);
// My rest of the code
}
public void iniMoviePlayerForEpisode(EpiModel epiModel,Context context){
ShowsDetailsActivity.epiModel =epiModel;
String type=epiModel.getServerType();
if (type.equals("embed") || type.equals("vimeo") || type.equals("gdrive")){
isVideo=false;
initWeb(epiModel.getStreamURL());
}else {
isVideo=true;
initVideoPlayer(epiModel.getStreamURL(),context,type);
}
}
}
public void setMediaUrlForTvSeries(String url, String season, String episod, String episode_id) {
mediaUrl = url;
this.season = season;
this.episod = episod;
this.episodeid = episode_id;
}
public void initVideoPlayer(String url, Context context, String type) {
progressBar.setVisibility(VISIBLE);
if (player != null) {
player.release();
}
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new
AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new
DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
simpleExoPlayerView.setPlayer(player);
player.prepare(mediaSource, true, false);
player.addListener(new Player.DefaultEventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playWhenReady && playbackState == Player.STATE_READY) {
isPlaying = true;
progressBar.setVisibility(View.GONE);
} else if (playbackState == Player.STATE_READY) {
progressBar.setVisibility(View.GONE);
isPlaying = false;
if (player != null) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("episode id: ");
stringBuilder.append(episodeid);
stringBuilder.append(" TimeStamp: ");
stringBuilder.append(player.getCurrentPosition() / 1000L);
databaseHelper.insertEpisodeData(episodeid, String.valueOf((long)player.getCurrentPosition()));
}
} else if (playbackState == Player.STATE_BUFFERING) {
isPlaying = false;
progressBar.setVisibility(VISIBLE);
} else {
isPlaying = false;
if (player != null) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("episode id: ");
stringBuilder.append(episodeid);
stringBuilder.append(" TimeStamp: ");
stringBuilder.append(player.getCurrentPosition() / 1000L);
databaseHelper.insertEpisodeData(episodeid, String.valueOf((long)player.getCurrentPosition()));
}
}
}
});
String getPlayed = databaseHelper.getEpisodeData(episodeid);
if (getPlayed != null) {
showResumeAlert();
return;
}
player.setPlayWhenReady(true);
}
private void showResumeAlert () {
new AlertDialog.Builder(this)
.setTitle("Do you want to resume from where you left ?")
.setPositiveButton("Resume", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String getPlayed = databaseHelper.getEpisodeData(episodeid);
if (getPlayed != null) {
player.seekTo(Long.parseLong(getPlayed));
player.setPlayWhenReady(true);
}
}
})
.setNegativeButton("Start Again", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
player.setPlayWhenReady(true);
}
})
.setCancelable(false)
.show();
}
// My rest of the code
}
The adapter:
public class DirectorApater extends RecyclerView.Adapter<DirectorApater.OriginalViewHolder> {
private List<EpiModel> items;
private Context ctx;
int selectedPosition=-1;
private int seasonNo;
public DirectorApater(Context context, List<EpiModel> items,String name, int seasonNo) {
ArrayList<EpiModel> arrayList=new ArrayList<>();
for(int i=0;i<items.size();i++){
if(items.get(i).getSeson().equals(name)){
arrayList.add(items.get(i));
}
}
items.clear();
this.items = arrayList;
this.seasonNo = seasonNo;
ctx = context;
}
@Override
public DirectorApater.OriginalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
DirectorApater.OriginalViewHolder vh;
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_director_name, parent, false);
vh = new DirectorApater.OriginalViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(final DirectorApater.OriginalViewHolder holder, final int position) {
final EpiModel obj = items.get(position);
holder.llEpi.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectedPosition=position;
notifyDataSetChanged();
((ShowsDetailsActivity)ctx).setMediaUrlForTvSeries(obj.getStreamURL(), obj.getSeson(), obj.getEpi(), obj.getEpisode_id());
if (!castSession) {
new ShowsDetailsActivity().iniMoviePlayerForEpisode(obj,ctx);
} else {
((ShowsDetailsActivity)ctx).showQueuePopup(ctx, holder.llEpi, ((ShowsDetailsActivity)ctx).getMediaInfo());
}
}
});
}
@Override
public int getItemCount() {
return items.size();
}
public class OriginalViewHolder extends RecyclerView.ViewHolder {
// some code
public OriginalViewHolder(View v) {
super(v);
// some code
}
}
So basically when a user clicks on the recyclerview item, it passes the data to the activity class "(ShowsDetailsActivity)ctx).setMediaUrlForTvSeries(obj.getStreamURL(), obj.getSeson(), obj.getEpi(), obj.getEpisode_id());"
App works fine without
String getPlayed = databaseHelper.getEpisodeData(episodeid);
if (getPlayed != null) {
showResumeAlert();
return;
}
in ShowsDetailsActivity class but crashes with this error log when I add it:
> java.lang.NullPointerException: Attempt to invoke virtual method
> 'java.lang.String
> com.myapp.db.DatabaseHelper.getEpisodeData(java.lang.String)' on a null object reference
答案1
得分: 4
你在这里调用了 iniMoviePlayerForEpisode
方法:
new ShowsDetailsActivity().iniMoviePlayerForEpisode(obj,ctx);
但是在那个时候,onCreate
方法还没有被调用,因此你的 databaseHelper
仍然为 null。请查阅我提供的链接,其中说明了 onCreate
方法是在 Activity 启动时调用的,而不是在对象创建时调用。
英文:
You are calling the iniMoviePlayerForEpisode
method here:
new ShowsDetailsActivity().iniMoviePlayerForEpisode(obj,ctx);
but at that point onCreate was not yet called and thus your databaseHelper
is still null. Check the reference i linked: onCreate
is called when your Activity starts, not when the object is created.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论