I am trying to create an intent with bundle extras but I am getting null pointer exception error on the Array List.
Here is the error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.ArrayList android.os.Bundle.getParcelableArrayList(java.lang.String)' on a null object reference
Am I implementing intents wrong?
Here is my application below for MP3 Player:
PlaylistSelector:
public class PlaylistSelector extends AppCompatActivity {
ListView listview;
String[] items;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.playlist);
listview = findViewById(R.id.listViewSong);
runtimePermission();
}
public void runtimePermission()
{
Dexter.withContext(this).withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse permissionGrantedResponse) {
displaySongs();
}
#Override
public void onPermissionDenied(PermissionDeniedResponse permissionDeniedResponse) {
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permissionRequest, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).check();
}
public ArrayList<File> findSong (File file)
{
ArrayList<File> arrayList = new ArrayList<>();
File[] files = file.listFiles();
for (File singlefile: files)
{
if (singlefile.isDirectory() && !singlefile.isHidden())
{
arrayList.addAll(findSong(singlefile));
}
else
{
if (singlefile.getName().endsWith(".mp3") || singlefile.getName().endsWith(".wav"))
{
arrayList.add(singlefile);
}
}
}
return arrayList;
}
void displaySongs()
{
final ArrayList<File> mySongs = findSong(Environment.getExternalStorageDirectory());
items = new String[mySongs.size()];
for(int i = 0; i<mySongs.size(); i++)
{
items[i] = mySongs.get(i).getName().toString().replace(".mp3","").replace(".wav","");
}
/*ArrayAdapter<String> myAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,songs);
listview.setAdapter(myAdapter);*/
customAdapter customAdapter = new customAdapter();
listview.setAdapter(customAdapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String songName = (String) listview.getItemAtPosition(i);
startActivity(new Intent(getApplicationContext(), MainActivity.class)
.putExtra("songs", mySongs)
.putExtra("songname", songName)
.putExtra("pos", i));
}
});
}
class customAdapter extends BaseAdapter{
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
View myView = getLayoutInflater().inflate(R.layout.list_item, null);
TextView textsong = myView.findViewById(R.id.txtsongname);
textsong.setSelected(true);
textsong.setText(items[i]);
return myView;
}
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private InputSource inputSource;
Button playbtn, btnnext,btnprev,btnff,btnrw;
TextView txtsn, txtsstop,txtsstart;
SeekBar seekmusic;
BarVisualizer visualizer;
String sname;
public static final String EXTRA_NAME = "song_name";
static MediaPlayer mediaPlayer;
int position;
ArrayList<File> mySongs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View frameLayoutMP = findViewById(R.id.preview_mp3_layout);
btnprev = findViewById(R.id.btnprev);
playbtn = findViewById(R.id.playbtn);
btnnext = findViewById(R.id.btnnext);
btnrw = findViewById(R.id.btnrw);
btnff = findViewById(R.id.btnff);
txtsn = findViewById(R.id.txtsn);
txtsstop = findViewById(R.id.txtsstop);
txtsstart = findViewById(R.id.txtsstart);
seekmusic = findViewById(R.id.seekbar);
visualizer = findViewById(R.id.blast);
if (mediaPlayer != null)
{
mediaPlayer.stop();
mediaPlayer.release();
}
Intent i = getIntent();
Bundle bundle = i.getExtras();
mySongs = (ArrayList) bundle.getParcelableArrayList("songs");
String songName = i.getStringExtra("songname");
position = bundle.getInt("pos",0);
txtsn.setSelected(true);
Uri uri = Uri.parse(mySongs.get(position).toString());
sname = mySongs.get(position).getName();
txtsn.setText(sname);
mediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
mediaPlayer.start();
playbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mediaPlayer.isPlaying())
{
playbtn.setBackgroundResource(R.drawable.ic_play);
mediaPlayer.pause();
}
else
{
playbtn.setBackgroundResource(R.drawable.ic_pause);
mediaPlayer.start();
}
}
});
}
}
I am trying to get this intent to grab song lists from playlists and put it into the player
Related
The code I've done was followed closely by a few YouTube tutorials. I'm designing an Age of Empires app that takes in the data from a public API. When the user progresses through the pages then different parts of the API data are shown. What I wanted it to do was get the data from the main activity (where the API is retrieved) and put some of its many data into the UniqueUnit page. It's using something called serializable which I can't quite understand how it works yet.
For the record, it works in getting the data from page 'DetailedCivilization' but just completely breaks on 'UniqueUnit'page.
MainActivity.java
package com.example.ageofempires2;
import ...
public class MainActivity extends AppCompatActivity {
public static final String TAG = "tag";
RecyclerView itemList;
Adapter adapter;
List<Civilizations> all_civilizations;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("Civilizations menu");
all_civilizations = new ArrayList<>();
itemList = findViewById(R.id.itemList);
itemList.setLayoutManager(new LinearLayoutManager(this));
adapter = new Adapter(this, all_civilizations);
itemList.setAdapter(adapter);
getJsonData();
}
private void getJsonData() {
String URL = "https://age-of-empires-2-api.herokuapp.com/api/v1/civilizations";
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest objectRequest = new JsonObjectRequest(Request.Method.GET, URL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray civilizations = response.getJSONArray("civilizations");
JSONObject civilizationsData = civilizations.getJSONObject(0);
Log.d(TAG, "onResponse "+ civilizationsData);
for (int i=0; i< civilizationsData.length();i++){
JSONObject civilization = civilizations.getJSONObject(i);
Civilizations v = new Civilizations();
v.setName(civilization.getString("name"));
v.setArmy_type(civilization.getString("army_type"));
v.setExpansion(civilization.getString("expansion"));
v.setCivilization_bonus(civilization.getString("civilization_bonus"));
v.setUnique_unit(civilization.getString("unique_unit"));
all_civilizations.add(v);
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse" + error.getMessage());
}
});
requestQueue.add(objectRequest);
}
}
Adapter.java
package com.example.ageofempires2;
import ...
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private List<Civilizations> allCivilizations;
private Context context;
public Adapter(Context ctx, List<Civilizations> civilizationsData){
this.allCivilizations = civilizationsData;
this.context = ctx;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.civilization_view,parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
holder.titleName.setText(allCivilizations.get(position).getName());
holder.vv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle b = new Bundle();
b.putSerializable("civilizationsData", allCivilizations.get(position));
Intent i = new Intent(context, DetailedCivilization.class);
i.putExtras(b);
v.getContext().startActivity(i);
}
});
}
#Override
public int getItemCount() {
return allCivilizations.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView titleName;
TextView expansionName;
View vv;
public ViewHolder(#NonNull View itemView) {
super(itemView);
titleName = itemView.findViewById(R.id.civilizationUniqueUnits);
expansionName = itemView.findViewById(R.id.civilizationUnitDescription);
vv = itemView;
}
}
}
Civilizations.java
package com.example.ageofempires2;
import java.io.Serializable;
public class Civilizations implements Serializable {
private String name;
private String expansion;
private String army_type;
private String civilization_bonus;
private String unique_unit;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getExpansion() {
return expansion;
}
public void setExpansion(String expansion) {
this.expansion = expansion;
}
public String getArmy_type() {
return army_type;
}
public void setArmy_type(String army_type) {
this.army_type = army_type;
}
public String getCivilization_bonus() {
return civilization_bonus;
}
public void setCivilization_bonus(String civilization_bonus) {this.civilization_bonus = civilization_bonus; }
public String getUnique_unit() {
return unique_unit;
}
public void setUnique_unit(String unique_unit) {this.unique_unit = unique_unit; }
}
UniqueUnits.java
package com.example.ageofempires2;
import ...
public class UniqueUnit extends AppCompatActivity {
public static final String TAG = "TAG";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_unique_unit);
getSupportActionBar().setTitle("Unique Unit");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent incomingIntent = getIntent();
Bundle incomingName = incomingIntent.getExtras();
Civilizations v = (Civilizations) incomingName.getSerializable("civilizationsData");
Log.d(TAG, "onCreate: IDK MAN IT SHOULD WORK??" +incomingName);
TextView unit = findViewById(R.id.civilizationUnitDescription);
unit.setText(v.getUnique_unit());
}
}
DetailedCivilization.java
package com.example.ageofempires2;
import ...
public class DetailedCivilization extends AppCompatActivity {
public static final String TAG = "TAG";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed_civilization);
getSupportActionBar().setTitle("Detailed view");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent i = getIntent();
Bundle data = i.getExtras();
Civilizations v = (Civilizations) data.getSerializable("civilizationsData");
TextView type = findViewById(R.id.civilizationType);
type.setText(v.getArmy_type());
TextView title = findViewById(R.id.civilizationUniqueUnits);
title.setText(v.getName());
TextView expansions = findViewById(R.id.civilizationUnitDescription);
expansions.setText(v.getExpansion());
TextView bonus = findViewById(R.id.civilizationBonus);
bonus.setText(v.getCivilization_bonus());
Button changeActivityTech = findViewById(R.id.tech_button);
Button changeActivityUnit = findViewById(R.id.unit_button);
changeActivityTech.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
activityTech();
}
});
changeActivityUnit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
activityUnit();
}
});
}
private void activityTech(){
Intent intent = new Intent(this, UniqueTech.class);
startActivity(intent);
}
private void activityUnit(){
Intent intent = new Intent(this, UniqueUnit.class);
startActivity(intent);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if(item.getItemId() == android.R.id.home){
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
}
Solutions is
private void activityUnit(Civilizations civ){
Bundle b = new Bundle();
b.putSerializable("civilizationsData", civ)
Intent intent = new Intent(this, UniqueUnit.class);
intent.putExtras(b);
startActivity(intent);
}
In DetailedCivilization.java
Rename v from line Civilizations v = (Civilizations) incomingName.getSerializable("civilizationsData"); to civ or something more descriptive
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed_civilization);
getSupportActionBar().setTitle("Detailed view");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent i = getIntent();
Bundle data = i.getExtras();
Civilizations civ = (Civilizations) data.getSerializable("civilizationsData");
TextView type = findViewById(R.id.civilizationType);
type.setText(v.getArmy_type());
TextView title = findViewById(R.id.civilizationUniqueUnits);
title.setText(v.getName());
TextView expansions = findViewById(R.id.civilizationUnitDescription);
expansions.setText(v.getExpansion());
TextView bonus = findViewById(R.id.civilizationBonus);
bonus.setText(v.getCivilization_bonus());
Button changeActivityTech = findViewById(R.id.tech_button);
Button changeActivityUnit = findViewById(R.id.unit_button);
changeActivityTech.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
activityTech();
}
});
changeActivityUnit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
activityUnit(civ);
}
});
}
And pass Civilizations when you call activityUnit function
Basically you forgot to pass Civilizations when you go from DetailedCivilization.java to UniqueUnits.java
**Main Activity.java**
This is main activity where I instantiate all methods/objects. Here I use Dexter library to grab files from user's external storage, then I made one method called find songs which helps in finding the path of files and list them accordingly. Then I made another method called display songs which will help in getting the whole size of songs and then display the whole list with their names accordingly. Then with the help of custom adapter I passed my list of songs which is in array named item.
public class MainActivity extends AppCompatActivity {
ListView listView;
String [] items;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listViewSong);
runtimePermission();
}
public void runtimePermission(){
Dexter.withContext(this)
.withPermissions(Manifest.permission.READ_EXTERNAL_STORAGE,Manifest
.permissi
on.RECORD_AUDIO)
.withListener(new MultiplePermissionsListener() {
#RequiresApi(api = Build.VERSION_CODES.R)
#Override
public void
onPermissionsChecked(MultiplePermissionsReport
multiplePermissionsReport)
{
displaySongs();
}
#Override
public void
onPermissionRationaleShouldBeShown(List<PermissionRequest> list,
PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).check();
}
public ArrayList<File> findSong(File file){
ArrayList arrayList = new ArrayList();
Log.d(TAG, "findSong:"+ file.getPath());
File [] files = file.listFiles();
if (files!=null) {
Log.d(TAG, "findSong:"+ files.length);
for (File singleFile : files) {
if (singleFile.isDirectory() && !singleFile.isHidden()) {
arrayList.addAll(findSong(singleFile));
} else {
if (singleFile.getName().endsWith(".mp3") &&
!singleFile.getName().startsWith(".")) {
arrayList.add(singleFile);
}
}
}
}
return arrayList;
}
public void displaySongs(){
ArrayList<File> mySongs =
findSong(Environment.getExternalStorageDirectory());
String [] items = new String [mySongs.size()];
if(mySongs == null)return; // this is very important function
otherwise app will crash
for (int i=0; i<mySongs.size(); i++){
items[i] = mySongs.get(i).getName().replace(".mp3",
"");
}
Log.d(TAG, "displaySongs:"+ items.length);
(this,
android.R.layout.simple_list_item_1,items);
CustomAdapter customAdapter = new CustomAdapter(this,
Arrays.asList(items));
Log.d(TAG, "displaySongs:"+ customAdapter.getCount());
listView.setAdapter(customAdapter);
listView.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
String currentSong = (String)
listView.getItemAtPosition(position);
startActivity(new Intent(getApplicationContext(),
PlayerActivity.class)
.putExtra("currentSong", currentSong)
.putExtra("position",position)
.putExtra("songs",mySongs));
}
});
}
class CustomAdapter extends ArrayAdapter {
public android.util.Log Log;
List<String> names;
LayoutInflater inflater;
Context context;
public CustomAdapter(Context context, List<String> names) {
super(context,R.layout.list_item ,names);
this.names=names;
this.context=context;
}
#Override
public View getView(int position, View convertView, ViewGroup
parent) {
inflater=LayoutInflater.from(getContext()); //inflater is
responsible for taking your xml files that defines your layout
// and converting them into view objects.
View
customview=inflater.inflate(R.layout.list_item,parent,false);
String data=names.get(position);
//String data1=names.get(position+1);
TextView tv=
(TextView)customview.findViewById(R.id.textsongname);
tv.setText(data);
tv.setSelected(true);
//TextView tv1=(TextView)customview.findViewById(R.id.TeamB);
//tv1.setText(data1);
return customview;
}
}
}
**PlayerActivity.java**
I tried to make a Thread named update seek bar which will update my seek bar to current position after that I applied set on click bar change listener so that whenever user update position of sidebar it should get updated. But error here is that when I run my app using this code on emulator its working completely fine but when installed in my phone 2 errors are coming. One after completion of song its not jumping automatically to the next song and second when user update sidebar and press next, sidebar is not coming to position 0, and this whole error is showing on my phone not in emulator.
public class PlayerActivity extends AppCompatActivity {
Button play,next,fastforward, previous, fastrewind;
TextView txtsn, txtsstart, txtsstop;
SeekBar seekBar;
BarVisualizer visualizer;
Thread updateSeekBar;
String sName;
public static final String EXTRA_NAME = "song_name";
static MediaPlayer mediaPlayer;
int position;
ArrayList mySongs;
ImageView imageView;
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId()== android.R.id.home){
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
if (visualizer != null){
visualizer.release();
}
super.onDestroy();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
getSupportActionBar().setTitle("Now Playing");
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
play = findViewById(R.id.play);
next = findViewById(R.id.next);
previous = findViewById(R.id.previous);
fastforward = findViewById(R.id.fastforward);
fastrewind = findViewById(R.id.fastrewind);
txtsn = findViewById(R.id.txtsn);
txtsstart = findViewById(R.id.txtsstart);
txtsstop = findViewById(R.id.txtsstop);
seekBar = findViewById(R.id.seekbar);
visualizer = findViewById(R.id.blast);
imageView = findViewById(R.id.iamgeView);
if (mediaPlayer != null){
mediaPlayer.stop();
mediaPlayer.release();
}
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
mySongs = (ArrayList) bundle.getParcelableArrayList("songs");
sName = intent.getStringExtra("currentSong");
position = bundle.getInt("position",0);
txtsn.setText(sName);
txtsn.setSelected(true);
Uri uri = Uri.parse(mySongs.get(position).toString()); // uri is
usually use tell a content provider what we want to access by
reference
mediaPlayer = MediaPlayer.create(this,uri);
mediaPlayer.start();
seekBar.setMax(mediaPlayer.getDuration());
updateSeekBar = new Thread(){
#Override
public void run() {
int currentPosition = 0;
while (currentPosition<mediaPlayer.getDuration()){
try {
currentPosition = mediaPlayer.getCurrentPosition();
seekBar.setProgress(currentPosition);
sleep(500);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
};
updateSeekBar.start();
seekBar.setOnSeekBarChangeListener(new
SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mediaPlayer.seekTo(seekBar.getProgress());
}
});
String endTime = createTime(mediaPlayer.getDuration());
txtsstop.setText(endTime);
final Handler handler = new Handler();
final int delay = 1000;
handler.postDelayed(new Runnable() {
#Override
public void run() {
String currentTime =
createTime(mediaPlayer.getCurrentPosition());
txtsstart.setText(currentTime);
handler.postDelayed(this,delay);
}
},delay);
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying()){
play.setBackgroundResource(R.drawable.ic_play);
mediaPlayer.pause();
}
else {
play.setBackgroundResource(R.drawable.ic_pause);
mediaPlayer.start();
}
}
});
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer.stop();
mediaPlayer.release();
if(position!=mySongs.size()-1){
position = position + 1;
}
else{
position = 0;
}
Uri uri = Uri.parse(mySongs.get(position).toString());
mediaPlayer = MediaPlayer.create(getApplicationContext(),
uri);
sName = mySongs.get(position).toString();
txtsn.setText(sName);
mediaPlayer.start();
play.setBackgroundResource(R.drawable.ic_pause);
seekBar.setMax(mediaPlayer.getDuration());
startAnimation(imageView);
int audiosessionId = mediaPlayer.getAudioSessionId();
if(audiosessionId!= -1){
visualizer.setAudioSessionId(audiosessionId);
}
}
});
mediaPlayer.setOnCompletionListener(new
MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
next.performClick();
}
});
int audiosessionId = mediaPlayer.getAudioSessionId();
if(audiosessionId!= -1){
visualizer.setAudioSessionId(audiosessionId);
}
previous.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer.stop();
mediaPlayer.release();
if(position!=0){
position = position - 1;
}
else{
position = mySongs.size() - 1;
}
Uri uri = Uri.parse(mySongs.get(position).toString());
mediaPlayer = MediaPlayer.create(getApplicationContext(),
uri);
sName = mySongs.get(position).toString();
txtsn.setText(sName);
mediaPlayer.start();
play.setBackgroundResource(R.drawable.ic_pause);
seekBar.setMax(mediaPlayer.getDuration());
startAnimation(imageView);
int audiosessionId = mediaPlayer.getAudioSessionId();
if(audiosessionId!= -1){
visualizer.setAudioSessionId(audiosessionId);
}
}
});
fastforward.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying()){
mediaPlayer.seekTo(mediaPlayer.getCurrentPosition()+1000);
}
}
});
fastrewind.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying()){
mediaPlayer.seekTo(mediaPlayer.getCurrentPosition()-1000);
}
}
});
}
private boolean isPermissionGranted(){
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R){
return Environment.isExternalStorageManager();
}
else {
int readExternalStoragePermission =
ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE);
return readExternalStoragePermission ==
PackageManager.PERMISSION_GRANTED;
}
}
public void startAnimation(View view){
ObjectAnimator animator =
ObjectAnimator.ofFloat(imageView,"rotation",0f,360f);
animator.setDuration(1000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(animator);
animatorSet.start();
}
public String createTime(int duration) {
String time = "";
int min = duration/1000/60;
int sec = duration/1000%60;
time+=min+":";
if (sec<10) {
time+="0";
}
time+=sec;
return time;
}
}
Here is my full java class code.
It is showing null pointer exception. I have also add logcat screen shot. I am trying to solve this problem, but no way.Please help me if possible.
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.AppViewHolder> implements Filterable {
// Load Settings
private AppPreferences appPreferences;
// AppAdapter variables
private List<AppInfo> appList;
private List<AppInfo> appListSearch;
private Context context;
public AppAdapter(List<AppInfo> appList, Context context) {
this.appList = appList;
this.context = context;
this.appPreferences = SystemInfoManager.getAppPreferences();
}
#Override
public int getItemCount() {
return appList.size();
}
public void clear() {
appList.clear();
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(AppViewHolder appViewHolder, int i) {
AppInfo appInfo = appList.get(i);
appViewHolder.vName.setText(appInfo.getName());
appViewHolder.vApk.setText(appInfo.getAPK());
appViewHolder.vIcon.setImageDrawable(appInfo.getIcon());
setButtonEvents(appViewHolder, appInfo);
}
private void setButtonEvents(AppViewHolder appViewHolder, final AppInfo appInfo) {
ButtonFlat appAbout = appViewHolder.vAbout;
ButtonFlat appShare = appViewHolder.vShare;
final ImageView appIcon = appViewHolder.vIcon;
final CardView cardView = appViewHolder.vCard;
appAbout.setBackgroundColor(Color.BLUE);
appShare.setBackgroundColor(Color.BLUE);
appAbout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Activity activity = (Activity) context;
Intent intent = new Intent(context, AppActivity.class);
intent.putExtra("app_name", appInfo.getName());
intent.putExtra("app_apk", appInfo.getAPK());
intent.putExtra("app_version", appInfo.getVersion());
intent.putExtra("app_source", appInfo.getSource());
intent.putExtra("app_data", appInfo.getData());
Bitmap bitmap = ((BitmapDrawable) appInfo.getIcon()).getBitmap();
intent.putExtra("app_icon", bitmap);
intent.putExtra("app_isSystem", appInfo.isSystem());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String transitionName = context.getResources().getString(R.string.transition_app_icon);
ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(activity, appIcon, transitionName);
context.startActivity(intent, transitionActivityOptions.toBundle());
} else {
context.startActivity(intent);
activity.overridePendingTransition(R.anim.slide_in_right, R.anim.fade_back);
}
}
});
appShare.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
UtilsApp.copyFile(appInfo);
Intent shareIntent = UtilsApp.getShareIntent(UtilsApp.getOutputFilename(appInfo));
context.startActivity(Intent.createChooser(shareIntent,
String.format(context.getResources().getString(R.string.send_to), appInfo.getName())));
}
});
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Activity activity = (Activity) context;
Intent intent = new Intent(context, AppActivity.class);
intent.putExtra("app_name", appInfo.getName());
intent.putExtra("app_apk", appInfo.getAPK());
intent.putExtra("app_version", appInfo.getVersion());
intent.putExtra("app_source", appInfo.getSource());
intent.putExtra("app_data", appInfo.getData());
Bitmap bitmap = ((BitmapDrawable) appInfo.getIcon()).getBitmap();
intent.putExtra("app_icon", bitmap);
intent.putExtra("app_isSystem", appInfo.isSystem());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String transitionName = context.getResources().getString(R.string.transition_app_icon);
ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(activity, appIcon, transitionName);
context.startActivity(intent, transitionActivityOptions.toBundle());
} else {
context.startActivity(intent);
activity.overridePendingTransition(R.anim.slide_in_right, R.anim.fade_back);
}
}
});
}
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
final FilterResults oReturn = new FilterResults();
final List<AppInfo> results = new ArrayList<>();
if (appListSearch == null) {
appListSearch = appList;
}
if (charSequence != null) {
if (appListSearch != null && appListSearch.size() > 0) {
for (final AppInfo appInfo : appListSearch) {
if (appInfo.getName().toLowerCase().contains(charSequence.toString())) {
results.add(appInfo);
}
}
}
oReturn.values = results;
oReturn.count = results.size();
}
return oReturn;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
if (filterResults.count > 0) {
InstalledAppsFragment.setResultsMessage(false);
} else {
InstalledAppsFragment.setResultsMessage(true);
}
appList = (ArrayList<AppInfo>) filterResults.values;
notifyDataSetChanged();
}
};
}
#Override
public AppViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View appAdapterView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.app_layout, viewGroup, false);
return new AppViewHolder(appAdapterView);
}
public static class AppViewHolder extends RecyclerView.ViewHolder {
protected TextView vName;
protected TextView vApk;
protected ImageView vIcon;
protected ButtonFlat vAbout;
protected ButtonFlat vShare;
protected CardView vCard;
public AppViewHolder(View v) {
super(v);
vName = (TextView) v.findViewById(R.id.txtName);
vApk = (TextView) v.findViewById(R.id.txtApk);
vIcon = (ImageView) v.findViewById(R.id.imgIcon);
vAbout = (ButtonFlat) v.findViewById(R.id.btnExtract);
vShare = (ButtonFlat) v.findViewById(R.id.btnShare);
vCard = (CardView) v.findViewById(R.id.app_card);
}
}
}
Here is the logcat message:
https://i.stack.imgur.com/vVOr7.jpg
Please give me some solution if possible.
I have used context.getBaseContext() but it also gave error.
Instead of parsing context to activity use getActiviy()
Intent intent = new Intent(getActivity(), AppActivity.class);
Try change this line
Instead
Intent intent = new Intent(context, AppActivity.class);
to
Intent intent = new Intent(YourActivityName.this, AppActivity.class);
I am making dictionary app having sound sample, when an item in the list is click, a new activity will open containing details view and a button. Can someone help me how can I assign the specific sound to the button. The sound files are placed in raw folder. for example, I click the item 'araw',the details will show and the button must play the sound araw...Pls help me...
heres the codes:
ListView lv;
SearchView sv;
String[] tagalog= new String[] {"alaala (png.)","araw (png.)","baliw (png.)","basura (png.)",
"kaibigan (png.)","kakatuwa (pu.)", "kasunduan (png.)","dambuhala (png.)",
"dulo (png.)","gawin (pd.)","guni-guni (png.)","hagdan (png.)","hintay (pd.)",
"idlip (png.)","maganda (pu.)","masarap (pu.)", "matalino (pu.)"};
ArrayAdapter<String> adapter;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView1);
sv = (SearchView) findViewById(R.id.searchView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,tagalog);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String tagword =tagalog[position];
String[] definition = getResources().getStringArray(R.array.definition);
final String definitionlabel = definition[position];
String[] cuyuno = getResources().getStringArray(R.array.cuyuno);
final String cuyunodefinition = cuyuno[position];
String[] english = getResources().getStringArray(R.array.english);
final String englishdefinition = english[position];
Intent intent = new Intent(getApplicationContext(), DefinitionActivity.class);
intent.putExtra("tagword", tagword);
intent.putExtra("definitionlabel", definitionlabel);
intent.putExtra("cuyunodefinition",cuyunodefinition);
intent.putExtra("englishdefinition", englishdefinition);
startActivity(intent);
}
});
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String text) {
return false;
}
#Override
public boolean onQueryTextChange(String text) {
adapter.getFilter().filter(text);
return false;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
}
DefinitionActivity.java
public class DefinitionActivity extends AppCompatActivity {
String tagalogword;
String worddefinition;
String cuyunoword;
String englishword;
int[] sounds = new int[]{R.raw.alaala,
R.raw.araw,
R.raw.baliw,
R.raw.basura,
R.raw.kaibigan,
R.raw.kakatuwa,
R.raw.kasunduan,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_definition);
TextView wordtv = (TextView) findViewById(R.id.wordtv);
TextView definitiontv = (TextView) findViewById(R.id.definitiontv);
TextView cuyunotv = (TextView) findViewById(R.id.cuyunotv);
TextView englishtv = (TextView) findViewById(R.id.englishtv);
Button play = (Button) findViewById(R.id.playbty);
final Bundle extras = getIntent().getExtras();
if (extras != null) {
tagalogword = extras.getString("tagword");
wordtv.setText(tagalogword);
worddefinition = extras.getString("definitionlabel");
definitiontv.setText(worddefinition);
cuyunoword = extras.getString("cuyunodefinition");
cuyunotv.setText(cuyunoword);
englishword = extras.getString("englishdefinition");
englishtv.setText(englishword);
}
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// I do not know how to play the audio when button click
}
});
}
}
Like Pedif said, you should use SoundPool for playing short sounds.
Here is Code from my Tetris like game, the Activity creates the Instance and get a callback when sounds were loaded.
Example as Singleton:
public class Sounds {
private Context ctx;
private static Sounds mSounds = null;
private static SoundPool mSPool = null;
private int sound_gameover;
private int sound_teil_drehen;
private int sound_1_zeile;
private int sound_2_zeile;
private int sound_3_zeile;
private int sound_4_zeile;
private int soundsToLoad = 6;
/**
* Volumecontrol
*/
private AudioManager audioManager;
private float actualVolume;
private float maxVolume;
private float volume;
private IOnSoundReady callback = null;
public static Sounds getInstance(Context ctx, IOnSoundReady mCallback){
if(mSPool == null){
mSounds = new Sounds(ctx, mCallback);
}
return mSounds;
}
private Sounds(Context ctx, IOnSoundReady mIOSoundReady) {
this.ctx = ctx;
this.callback = mIOSoundReady;
initVolume();
AsyncTask<Void, Void, Void> mTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
initSoundPool();
return null;
}
};
mTask.execute();
}
public void unprepare() {
if (mSPool == null) return;
mSPool.release();
mSPool = null;
}
private void initSoundPool(){
mSPool = new SoundPool(6, AudioManager.STREAM_MUSIC, 0);
mSPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
Log.w(TAG, "loaded soundid: " + sampleId);
if(--soundsToLoad == 0 && callback != null){
callback.onSoundReady();
}
}
});
sound_gameover = mSPool.load(ctx, R.raw.game_over, 1);
sound_teil_drehen = mSPool.load(ctx, R.raw.rotate, 1);
sound_1_zeile = mSPool.load(ctx, R.raw.line_1,1);
sound_2_zeile = mSPool.load(ctx, R.raw.line_2, 1);
sound_3_zeile = mSPool.load(ctx, R.raw.line_3, 1);
sound_4_zeile = mSPool.load(ctx, R.raw.line_4, 1);
}
/**
* calculate volume
*/
private void initVolume(){
audioManager = (AudioManager) ctx.getSystemService(SpielActivity.AUDIO_SERVICE);
actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
maxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
volume = actualVolume / maxVolume;
}
/**
* plays a sound
* #param soundid
*/
public void playSound(int soundid){
mSPool.play(soundid, volume, volume,1, 0, 1f);
}
}
Interface used when sounds are loaded, implemented by activity:
public interface IOnSoundReady {
void onSoundReady();
}
Usage in your activity:
Sounds mySounds = Sounds.getInstance(this, this);
Play sound:
public static void playSound(int soundid) {
mySounds.playSound(soundid);
}
Hope I could help a bit.
// Try this way
ListView lv;
SearchView sv;
String[] tagalog= new String[] {"alaala (png.)","araw (png.)","baliw (png.)","basura (png.)",
"kaibigan (png.)","kakatuwa (pu.)", "kasunduan (png.)","dambuhala (png.)",
"dulo (png.)","gawin (pd.)","guni-guni (png.)","hagdan (png.)","hintay (pd.)",
"idlip (png.)","maganda (pu.)","masarap (pu.)", "matalino (pu.)"};
ArrayAdapter<String> adapter;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView1);
sv = (SearchView) findViewById(R.id.searchView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,tagalog);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String tagword =tagalog[position];
String[] definition = getResources().getStringArray(R.array.definition);
final String definitionlabel = definition[position];
String[] cuyuno = getResources().getStringArray(R.array.cuyuno);
final String cuyunodefinition = cuyuno[position];
String[] english = getResources().getStringArray(R.array.english);
final String englishdefinition = english[position];
Intent intent = new Intent(getApplicationContext(), DefinitionActivity.class);
intent.putExtra("tagword", tagword);
intent.putExtra("definitionlabel", definitionlabel);
intent.putExtra("cuyunodefinition",cuyunodefinition);
intent.putExtra("englishdefinition", englishdefinition);
// put position of the file
intent.putExtra("position", position);
startActivity(intent);
}
});
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String text) {
return false;
}
#Override
public boolean onQueryTextChange(String text) {
adapter.getFilter().filter(text);
return false;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
// DictionaryActivity.class
public class DefinitionActivity extends AppCompatActivity {
String tagalogword;
String worddefinition;
String cuyunoword;
String englishword;
int[] sounds = new int[]{R.raw.alaala,
R.raw.araw,
R.raw.baliw,
R.raw.basura,
R.raw.kaibigan,
R.raw.kakatuwa,
R.raw.kasunduan,
};
private int songPosition = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_definition);
TextView wordtv = (TextView) findViewById(R.id.wordtv);
TextView definitiontv = (TextView) findViewById(R.id.definitiontv);
TextView cuyunotv = (TextView) findViewById(R.id.cuyunotv);
TextView englishtv = (TextView) findViewById(R.id.englishtv);
Button play = (Button) findViewById(R.id.playbty);
final Bundle extras = getIntent().getExtras();
if (extras != null) {
tagalogword = extras.getString("tagword");
wordtv.setText(tagalogword);
worddefinition = extras.getString("definitionlabel");
definitiontv.setText(worddefinition);
cuyunoword = extras.getString("cuyunodefinition");
cuyunotv.setText(cuyunoword);
englishword = extras.getString("englishdefinition");
englishtv.setText(englishword);
songPosition = extras.getInt("position");
}
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Play it here like
MediaPlayer mediaPlayer=MediaPlayer.create(DictionaryActivity.class,sounds[position]);
mediaPlayer.start();
}
});
}
}
You have to use SoundPool.
For sound effects which are short you would use SoundPool otherwise you should use MediaPlayer.
I'm developing an android kind-of-gallery-app with Firebase, so I will have plenty of images. I know that I need to be careful about memory management.
When I was searching how to find memory leak in android apps, I came across with LeakCanary. It looks really great, so I used in my app.
Basically my app has 3 fragments, which are Drawer, ProductGrid and ProductDetail. Sometimes LeakCanary says that I have a memory leak in ProductGrid, but I couldn't find it! Usually, adapters or static methods or listeners could cause memory leak because of Context object, but my knowledge is not sufficient to say 'aah that's because of here'
Here are the classes. Where is the leak?(If you suggest me anything that I can improve my code or approach, I would be appreciated!)
Because of body character limit, I put the link leak canary log file.
How I suspect there is a memory leak
First of all, LeakCanary shows a dialog and logs the dump. Second thing is, when I click on an item in drawer, in grid and in detail like 15 times(respectively), memory usage increases. It starts with 18M, increases 22M-23M after showing 3 images(normal). Then it heads up to 29M-30M after clicking on 15 times. If you click on around 30-40, memory usage increases 34M-35M
Edit: I've just figured out that, if I open and close drawer, memory usage increases 0.05M everytime, so one time opening and closing drawer costs 0.1M! What am i missing?
Main.java
public class Main extends ActionBarActivity implements DrawerListener {
private Toolbar mToolbar;
private Drawer drawerFragment;
private HomePage homeFragment;
private FragmentHelper fh = new FragmentHelper();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (homeFragment == null)
homeFragment = new HomePage();
if (savedInstanceState == null) {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (Drawer)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
drawerFragment.setUp(R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
drawerFragment.setRetainInstance(true);
displayView(null);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_home) {
getSupportActionBar().setTitle(getString(R.string.app_name));
fh.replace(getSupportFragmentManager(), homeFragment, R.id.container_body);
return true;
}
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.action_search) {
Toast.makeText(getApplicationContext(), "Search action is selected!", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onDrawerItemSelected(View view, int position, Category category) {
displayView(category);
}
private void displayView(Category category) {
if (category != null) {
getSupportActionBar().setTitle(category.getName());
ProductGrid gridFragment = new ProductGrid();
Bundle args = new Bundle();
args.putString(Product.CATEGORY_ID, category.getId());
gridFragment.setArguments(args);
fh.replace(getSupportFragmentManager(), gridFragment, R.id.container_body);
} else {
getSupportActionBar().setTitle(getString(R.string.app_name));
fh.replace(getSupportFragmentManager(), homeFragment, R.id.container_body);
}
}
}
Drawer.java
public class Drawer extends Fragment {
private Firebase mFirebase;
private Alert alert;
private RecyclerView recyclerView;
private View containerView;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerListener drawerListener;
private DrawerAdapter mAdapter;
private List<Category> mCategories;
public Drawer() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alert = new Alert(getActivity().getApplicationContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.drawer, container, false);
mCategories = new ArrayList<>();
mAdapter = new DrawerAdapter(mCategories);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawer_list);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
recyclerView.setItemAnimator(new SlideInOutLeftItemAnimator(recyclerView));
recyclerView.setAdapter(mAdapter);
mFirebase = new Firebase(getActivity().getResources().getString(R.string.firebase_ref))
.child(FirebaseRoots.CATEGORY);
Query query = mFirebase.orderByChild(Category.PRIO);
query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Category model = dataSnapshot.getValue(Category.class);
model.setId(dataSnapshot.getKey());
mCategories.add(model);
recyclerView.scrollToPosition(mCategories.size() - 1);
mAdapter.notifyItemInserted(mCategories.size() - 1);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Category model = dataSnapshot.getValue(Category.class);
model.setId(dataSnapshot.getKey());
int index = -1;
for (int i = 0; i < mCategories.size(); i++) {
if (mCategories.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mCategories.set(index, model);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemChanged(index);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Category model = dataSnapshot.getValue(Category.class);
model.setId(dataSnapshot.getKey());
int index = -1;
for (int i = 0; i < mCategories.size(); i++) {
if (mCategories.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mCategories.remove(index);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemRemoved(index);
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
alert.show(firebaseError.toString());
}
});
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity().getApplicationContext(),
recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
Category category = mCategories.get(position);
drawerListener.onDrawerItemSelected(view, position, category);
mDrawerLayout.closeDrawer(containerView);
}
#Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
containerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
}
public void setDrawerListener(DrawerListener listener) {
this.drawerListener = listener;
}
}
ProductGrid.java
public class ProductGrid extends Fragment implements ChildEventListener{
private Firebase mFirebaseRef;
private Alert alert;
private RecyclerView recyclerView;
private GridAdapter mAdapter;
private String categoryId;
private ArrayList<Product> mProducts;
private FileSystem fs;
public ProductGrid() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.categoryId = getArguments().getString(Product.CATEGORY_ID);
this.alert = new Alert(getActivity().getApplicationContext());
this.fs = new FileSystem(getActivity().getApplicationContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.grid, container, false);
fieldInitialize(layout);
mProducts = new ArrayList<>();
mAdapter = new GridAdapter(mProducts, getActivity().getApplicationContext());
recyclerView.addItemDecoration(new MarginDecoration(getActivity()));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
recyclerView.setAdapter(mAdapter);
mFirebaseRef = new Firebase(getActivity().getResources().getString(R.string.firebase_ref))
.child(FirebaseRoots.PRODUCT);
Query query = mFirebaseRef.orderByChild(Product.CATEGORY_ID).equalTo(categoryId);
query.addChildEventListener(this);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
ProductDetail detailFragment = new ProductDetail();
Bundle args = new Bundle();
args.putSerializable("product", mProducts);
args.putInt("position", position);
detailFragment.setArguments(args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, detailFragment);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
}
public void fieldInitialize(View layout) {
recyclerView = (RecyclerView) layout.findViewById(R.id.product_grid_layout);
}
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Product model = dataSnapshot.getValue(Product.class);
model.setId(dataSnapshot.getKey());
mProducts.add(model);
if (!fs.getFileNames().contains(model.getName() + FileExt.JPG.get())) {
fs.writeImage(model.getName(), ImageUtil.base64ToBitmap(
StringUtil.getBase64FromUrl(model.getImageData().getDataUrl())));
}
Collections.sort(mProducts);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemInserted(mProducts.size() - 1);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Product model = dataSnapshot.getValue(Product.class);
model.setId(dataSnapshot.getKey());
fs.writeImage(model.getName(), ImageUtil.base64ToBitmap(
StringUtil.getBase64FromUrl(model.getImageData().getDataUrl())));
int index = -1;
for (int i = 0; i < mProducts.size(); i++) {
if (mProducts.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mProducts.set(index, model);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemChanged(index);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Product model = dataSnapshot.getValue(Product.class);
model.setId(dataSnapshot.getKey());
fs.deleteImage(model.getName());
int index = -1;
for (int i = 0; i < mProducts.size(); i++) {
if (mProducts.get(i).getId().equals(model.getId())) {
index = i;
break;
}
}
mProducts.remove(index);
recyclerView.scrollToPosition(0);
mAdapter.notifyItemRemoved(index);
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
alert.show(firebaseError.toString());
}
#Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = AcarsanApp.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}
ProductDetail.java
public class ProductDetail extends Fragment {
private FullScreenImageAdapter adapter;
private ViewPager viewPager;
private ArrayList<Product> products;
private int position;
public ProductDetail() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
products = (ArrayList<Product>) getArguments().getSerializable("product");
position = getArguments().getInt("position");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.product_detail, container, false);
viewPager = (ViewPager) view.findViewById(R.id.product_gallery);
adapter = new FullScreenImageAdapter(getActivity().getApplicationContext(), products);
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(position);
return view;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
}
}
FileSystem
public class FileSystem {
private Context mContext;
public static final String PHOTOS_FOLDER = "photos";
public FileSystem(Context mContext) {
this.mContext = mContext;
}
public void writeImage(String name, Bitmap bitmap) {
String filename = name + FileExt.JPG.get();
File dir = mContext.getDir(PHOTOS_FOLDER, Context.MODE_PRIVATE);
File fileWithinDir = new File(dir, filename);
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(fileWithinDir);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public List<String> getFileNames() {
List<String> fileNames = new ArrayList<>();
File file = mContext.getDir(PHOTOS_FOLDER, Context.MODE_PRIVATE);
File[] files = file.listFiles();
for (File f : files) {
fileNames.add(f.getName());
}
return fileNames;
}
}
ImageUtil
public class ImageUtil {
public static Bitmap base64ToBitmap(String encodedImage) {
if (encodedImage == null)
return null;
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}
}