What I'm trying do to is using a custom CursorAdapter, in order to choose which layout to show and also to populate View items such as TextViews and also ImageView.
Now not in all the listview items there gonna be an image.
My CursorAdapter code is -
private static class ViewHolder {
TextView mesg;
TextView mesg2;
TextView send;
ImageView myImage;
}
public class ChatCursorAdapter extends CursorAdapter implements OnClickListener {
public ChatCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
}
#Override
public int getCount() {
return getCursor() == null ? 0 : super.getCount();
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int _position) {
Cursor cursor = (Cursor) getItem(_position);
return getItemViewType(cursor);
}
private int getItemViewType(Cursor cursor) {
String sender = cursor.getString(2);
String saveUser = user;
if (saveUser.equalsIgnoreCase(sender)){
return 0;
}else{
return 1;
}
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
String msg = cursor.getString(3);
String msg2 = cursor.getString(4);
String sender = cursor.getString(2);
holder.mesg.setText(getSmiledText(Main.this,msg));
holder.mesg2.setText(getSmiledText(Main.this,msg2));
holder.send.setText(sender);
picPath = cursor.getString(8);
if(picPath == null || picPath.isEmpty()){
holder.myImage.setVisibility(View.GONE);
}else{
File file = new File(picPath);
if(file.exists()){
new AsyncImageSetter(holder.myImage, picPath).execute();
holder.myImage.setOnClickListener(this);
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
View itemLayout = null;
switch(getItemViewType(cursor)){
case 0:
itemLayout = getLayoutInflater().inflate(R.layout.msg_item1,parent, false);
break;
case 1:
itemLayout = getLayoutInflater().inflate(R.layout.msg_item13, parent,false);
break;
}
itemLayout.setTag(holder);
holder.mesg = (TextView) itemLayout.findViewById(R.id.text_start);
holder.mesg2 = (TextView) itemLayout.findViewById(R.id.text_end);
holder.send = (TextView) itemLayout.findViewById(R.id.text_from);
holder.myImage = (ImageView) itemLayout.findViewById(R.id.imageView_msgpic);
return itemLayout;
}
}
As you can see when there a need to load an image to the ImageView, I'm using asynctask in order to let the flow of the list view scrolling to be much more smoother.
This how the asynctask code is -
public class AsyncImageSetter extends AsyncTask<Void, Void, Void> {
private ImageView img;
private String path;
private Bitmap bm;
public AsyncImageSetter(ImageView img, String path) {
this.img = img;
this.path = path;
}
#Override
protected Void doInBackground(Void... params) {
bm = BitmapFactory.decodeFile(path);
bm = setImageToImageView(path);
return null;
}
#Override
protected void onPostExecute(Void result) {
img.setTag(path);
img.setImageBitmap(bm);
//img.setVisibility(View.VISIBLE);
super.onPostExecute(result);
}
}
Well the thing is that it sure made the scrolling alot more smoother, but it seems to make the app crash a lot of times.
The logcat says the next -
03-24 17:07:34.125: E/AndroidRuntime(15422): FATAL EXCEPTION: AsyncTask #2
03-24 17:07:34.125: E/AndroidRuntime(15422): java.lang.RuntimeException: An error occured while executing doInBackground()
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.os.AsyncTask$3.done(AsyncTask.java:299)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.lang.Thread.run(Thread.java:841)
03-24 17:07:34.125: E/AndroidRuntime(15422): Caused by: java.lang.OutOfMemoryError
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:417)
03-24 17:07:34.125: E/AndroidRuntime(15422): at at.vcity.androidim.MainChat$AsyncImageSetter.doInBackground(MainChat.java:3356)
03-24 17:07:34.125: E/AndroidRuntime(15422): at at.vcity.androidim.MainChat$AsyncImageSetter.doInBackground(MainChat.java:1)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.os.AsyncTask$2.call(AsyncTask.java:287)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
03-24 17:07:34.125: E/AndroidRuntime(15422): ... 4 more
So what am I doing wrong here?
Thanks for any kind of help
It looks to me like the Bitmap you are trying to store in memory is too large to be stored in your tablet/emulator's memory. Here;
bm = BitmapFactory.decodeFile(path);
See if the code works with a much smaller file than the one that is coming from your current path (also see if it works with a smaller list). This could also be an instance of 'The straw that broke the camel's back'. If your current application is already very memory intensive you might have to go through your current code and optimise for memory management.
Because your are creating an AsyncTask for each item in the ListView, your trying to hold that many images in memory at once. So you might need to find another way to do it. You might need to try loading the image's thumbnail into your ImageViews instead.
An example of getting an images thumbnail.
I hope this helps.
An Example Implementation
Just to run through a potential way to implement the above linked thumbnail example, what I might do to get the thumbnail is I could store the context passed to your ChatCursorAdapter by adding the following as a class variable (and instantiate it in the constructor);
Context ourContext;
public ChatCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
ourContext = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
...
new AsyncImageSetter(holder.myImage, picPath, ourContext.getContentResolver()).execute();
...
}
Then (as above) I might use the Context to get the ContentResolver instance and pass that instance into your AsyncTask via it's constructor. Then we could add the method in the example code to get the thumbnail into the custom AsyncTask, which might look something like this;
ContentResolver cr;
public AsyncImageSetter(ImageView img, String path, ContentResolver cr) {
this.img = img;
this.path = path;
this.cr = cr;
}
...
#Override
protected Void doInBackground(Void... params) {
try{
bm = getThumbnail(cr, path);
}catch(Exception e){}
return null;
}
private Bitmap getThumbnail(ContentResolver cr, String path) throws Exception {
Cursor ca = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
if (ca != null && ca.moveToFirst()) {
int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
ca.close();
return MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null );
}
ca.close();
return null;
}
The cause is in your stacktrace: java.lang.OutOfMemoryError. It looks like one of two things -- either your images are too large or you are leaking memory (or both).
My recommendation would be to use one of the several libraries for doing background image loading. Here are a couple of suggestions:
https://github.com/nostra13/Android-Universal-Image-Loader
https://github.com/square/picasso
Related
I want to make it clear that this question will look very similar to one I asked earlier, but that I'm not asking exactly the same thing.
In my previous question, I got a RuntimeException/IllegalStateException, which told me my Activity got destroyed upon adding a new fragment.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tim.timapp
/com.example.tim.timapp.MainActivity}: java.lang.IllegalStateException:
Activity has been destroyed
In that case, it turned out it had to do with me creating new instances of MainActivityin an invalid way:
MainActivity ma = new MainActivity();
(PSA: Don't do the above, use MainActivity ma = (MainActivity) getActivity(); instead.)
I have now corrected this in my entire project, and am getting almost exactly the same error. Let me be clear: I (think I) know the original error was fixed, because I got a different error in between these two RE's, which I was able to fix myself.
To reiterate on my gibberish: Got the first RE, fixed it with the answer on my question, got a different error, fixed that myself, got almost exactly the same RE.
I have searched through my entire project to see if I had anything similar to the error I made before, but I can't find anything, so here I am. So basically, the answer I got on my previous question fixed my issue, temporarily. That answer however, does not help me with this new error I'm getting, that's why I'm asking this question.
TL;DR: Answer on Q1 fixed my issue at first(which makes it a working answer), but it does not fix the issue I'm having right now, which is almost the same.
The actual question
So, now we've got that bit out of the way, let's get on with my issue. So, I'm getting a RuntimeException/IllegalStateExcetion:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.tim.timapp/com.example.tim.timapp.MainActivity}:
java.lang.IllegalStateException: Activity has been destroyed
(PS. It's only a RE because I have my app navigate to the GeneralSettings fragment on startup, for debugging ease.)
I've read up on this kind of error, but nothing I could find that applies on my project.
So, what is causing this RuntimeException/IllegalStateException?
Full log
04-05 14:17:53.140 23411-23411/? I/art: Not late-enabling -Xcheck:jni (already on)
04-05 14:17:53.190 23411-23411/com.example.tim.timapp W/System: ClassLoader referenced unknown path: /data/app/com.example.tim.timapp-1/lib/x86_64
04-05 14:17:53.210 23411-23411/com.example.tim.timapp D/TEST DBHandler: sInstance == null
04-05 14:17:53.370 23411-23411/com.example.tim.timapp D/AndroidRuntime: Shutting down VM
04-05 14:17:53.370 23411-23411/com.example.tim.timapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tim.timapp, PID: 23411
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tim.timapp/com.example.tim.timapp.MainActivity}: java.lang.IllegalStateException: Activity has been destroyed
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Activity has been destroyed
at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1433)
at android.app.BackStackRecord.commitInternal(BackStackRecord.java:687)
at android.app.BackStackRecord.commit(BackStackRecord.java:663)
at com.example.tim.timapp.MainActivity.DrawVariableFragments(MainActivity.java:276)
at com.example.fragments.Settings.GeneralSettingsFragment.onCreateView(GeneralSettingsFragment.java:58)
at android.app.Fragment.performCreateView(Fragment.java:2220)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:973)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
at android.app.BackStackRecord.run(BackStackRecord.java:793)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1535)
at android.app.FragmentController.execPendingActions(FragmentController.java:325)
at android.app.Activity.performStart(Activity.java:6252)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
MainActivity (Snippet)
package com.example.tim.timapp;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private static boolean isMainShown = false;
private static boolean isSettingsShown = false;
private static boolean doSavePopup = false;
private static String backTitle = "";
private String tag = "TEST MA";
DBHandler dbHandler;
Menu menu;
public void DrawVariableFragments(String base,String token){
// FragmentManager fm = getFragmentManager();
ArrayList<String> Data;
dbHandler = DBHandler.getInstance(this);
int AmountOfEntries;
int SettingsContainer;
String SettingsTag;
Fragment SettingsVariableFragment;
Fragment SettingsEmptyFragment;
if (base.equalsIgnoreCase("StuffManager")) {
Data = new ArrayList<String>() {{add("StuffManager"); add("name"); add("tag"); }};
SettingsContainer = R.id.FragmentContainer2;
SettingsTag = getString(R.string.navdrawer_stuffmanager);
SettingsVariableFragment = new StuffManagerVariableFragment();
SettingsEmptyFragment = new StuffManagerEmptyFragment();
} else if (base.equalsIgnoreCase("GeneralSettings")) {
Data = new ArrayList<String>() {{add("GeneralSettings"); add("name"); add("ip"); add("port"); add("username"); add("pass"); }};
SettingsContainer = R.id.FragmentContainerGeneralSettings;
SettingsTag = getString(R.string.navdrawer_generalsettings);
SettingsVariableFragment = new GeneralSettingsVariableFragment();
SettingsEmptyFragment = new GeneralSettingsEmptyFragment();
} else {
Log.e(tag, "String Base not recognised");
return;
}
AmountOfEntries = dbHandler.returnArray(base, Data.get(1)).size();
FragmentManager fm = getFragmentManager().findFragmentByTag(SettingsTag).getChildFragmentManager();
if ((dbHandler.returnArray(base, Data.get(1))).size() == 0 ) {
// Log.d(tag, "SettingsContainer1: " + String.valueOf(SettingsContainer) + "; SettingsEmtpyFragment1: " + SettingsEmptyFragment + "; Base1: " + base);
fm.beginTransaction().add(SettingsContainer, SettingsEmptyFragment, (base + "EmptyFragment")).commit();
fm.executePendingTransactions();
return;
}
if (AmountOfEntries > 0) {
String EmptyFragName = (base + "EmptyFragment");
if ((fm.findFragmentByTag(EmptyFragName)) != null) {
fm.beginTransaction().remove(fm.findFragmentByTag(EmptyFragName)).commit();
fm.executePendingTransactions();
}
for (int i = 0; i < AmountOfEntries; i++) {
ArrayList<String> fragmentData = new ArrayList<>();
for (int k=1; k < Data.size(); k++) {
int j=k-1;
fragmentData.set(j, (dbHandler.returnArray(base, Data.get(k)).get(j)));
}
if (token.equalsIgnoreCase("edit")) {
LinearLayout linearLayout = (LinearLayout) findViewById(SettingsContainer);
linearLayout.removeAllViews();
DrawVariableFragments(base ,"draw");
} else if (token.equalsIgnoreCase("add")) {
if (fm.findFragmentByTag(fragmentData.get(i)) == null) {
fm.beginTransaction().add(SettingsContainer, SettingsVariableFragment, fragmentData.get(0)).commit();
fm.executePendingTransactions();
if (base.equalsIgnoreCase("StuffManager")) {
((StuffManagerVariableFragment) fm
.findFragmentByTag(fragmentData.get(i)))
.setText(fragmentData.get(0), fragmentData.get(1));
} else if (base.equalsIgnoreCase("GeneralSettings")) {
((GeneralSettingsVariableFragment) fm
.findFragmentByTag(fragmentData.get(i)))
.setText(fragmentData.get(0), fragmentData.get(1), fragmentData.get(2), fragmentData.get(3));
}
}
} else if (token.equalsIgnoreCase("draw")) {
fm.beginTransaction().add(SettingsContainer, SettingsVariableFragment, fragmentData.get(0)).commit();
fm.executePendingTransactions();
if (base.equalsIgnoreCase("StuffManager")) {
((StuffManagerVariableFragment) fm
.findFragmentByTag(fragmentData.get(i)))
.setText(fragmentData.get(0), fragmentData.get(1));
} else if (base.equalsIgnoreCase("GeneralSettings")) {
((GeneralSettingsVariableFragment) fm
.findFragmentByTag(fragmentData.get(i)))
.setText(fragmentData.get(0), fragmentData.get(1), fragmentData.get(2), fragmentData.get(3));
}
}
}
} else {
Log.d("TEST", "WTF, nameArray.size != 0 && !> 0");
}
}
}
GeneralSettingsFragment (Snippet)
package com.example.fragments.Settings;
public class GeneralSettingsFragment extends Fragment {
MainActivity ma;
DBHandler dbHandler;
private static Menu optionsMenu;
public static boolean hideDeleteAllButton = false;
LinearLayout linearLayout;
View rootView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_generalsettings, container, false);
ma = (MainActivity) getActivity();
linearLayout = (LinearLayout) rootView.findViewById(R.id.FragmentContainerGeneralSettings);
if (linearLayout == null) {
Log.e("GMF", "Layout is null");
} else if (linearLayout.getChildCount() == 0) {
GeneralSettingsInitialInputDialog GSIID = new GeneralSettingsInitialInputDialog();
GSIID.show(getFragmentManager(), "dialog");
hideDeleteAllButton = true;
} else {
hideDeleteAllButton = false;
}
ma.DrawVariableFragments("GeneralSettings", "draw");
return rootView;
}
}
You are still doing things in an unsupported way. In MainActivity.DrawVariableFragments() you are creating a new GeneralSettingsVariableFragment() and then call getChildFragmentManager() on it and attempt to commit a fragment.
The GeneralSettingsFragment has not yet been attached to an Activity so it does not have a host. This throws the IllegalStateException("Activity has been destroyed") exception you are seeing when you try to commit the FragmentTransaction.
It is unclear why you are creating a new GeneralSettingsVariableFragmentwhen you are already inside a new instance of one.
To properly lookup an existing fragment use getFragmentManager().findFragmentByTag(...) or getFragmentManager().findFragmentById(...).
I have creted a class through which i want to get a list url's from the database. But I get this error:
03-30 15:05:35.599 3591-3591/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.imran.myapp, PID: 3591
java.lang.NullPointerException: Attempt to read from null array
at com.example.imran.myapp.gridgallery.onCreateView(gridgallery.java:55)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1026)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1207)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1572)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:493)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6145)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
03-30 15:05:35.599 1032-1045/? V/ApplicationPolicy: isApplicationStateBlocked userId 0 pkgname com.example.imran.myapp
03-30 15:05:35.599 1032-1045/? W/ActivityManager: Force finishing activity com.example.imran.myapp/.Home
03-30 15:05:35.609 1032-1045/? V/ApplicationPolicy: isApplicationStateBlocked userId 0 pkgname com.example.imran.myapp
03-30 15:05:35.909 1032-1032/? D/CrashAnrDetector: processName: com.example.imran.myapp
03-30 15:05:35.919 1032-1032/? D/CrashAnrDetector: broadcastEvent : com.example.imran.myapp data_app_crash
03-30 15:05:36.159 1032-1059/? W/ActivityManager: Activity pause timeout for ActivityRecord{3f2af340 u0 com.example.imran.myapp/.Home t3125 f}
03-30 15:05:37.019 1032-1521/? I/WindowState: WIN DEATH: Window{224e112b u0 com.example.imran.myapp/com.example.imran.myapp.Home}
03-30 15:05:37.079 1032-1528/? I/ActivityManager: Process com.example.imran.myapp (pid 3591)(adj 9) has died(67,606)
03-30 15:05:37.359 10199-10199/? D/AASAservice-UpdateReceiver: AASAUpdateReceiver: android.intent.action.PACKAGE_REPLACED, package = com.example.imran.myapp, uid = -1
03-30 15:05:37.379 2433-3619/? D/PkgBroadcastIntentOp: Received broadcast action=android.intent.action.PACKAGE_REPLACED and uri=com.example.imran.myapp
03-30 15:05:37.559 2433-3974/? D/k: Processing package: com.example.imran.myapp
03-30 15:05:37.559 2227-3976/? D/Compatibility: intentservice saw: Intent { act=android.intent.action.PACKAGE_REPLACED dat=package:com.example.imran.myapp flg=0x4000010 cmp=com.sec.android.app.soundalive/.compatibility.Compatibility$Receiver (has extras) } Bundle[{android.intent.extra.UID=10252, android.intent.extra.REPLACING=true, android.intent.extra.user_handle=0}]
03-30 15:05:37.589 2433-3974/? D/GassUtils: Found app info for package com.example.imran.myapp:1. Hash: 6b9333e031907d7a6a6c12cd9fdfa0d23bd13ee0f40c9617ddd005dc358321b0
03-30 15:05:37.589 2433-3974/? D/k: Found info for package com.example.imran.myapp in db.
This is the activity in which i am using the class:
gridgallery.java
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_gridgallery, null);
Myserver myserver = new Myserver();
//postStringRequest(myserver.url + "/api/albums/getalbums.php", view);
AlbumsList albumsList = new AlbumsList(myserver.url+"/api/albums/getalbums.php",getContext(),view);
albumsList.connection(); // Do connection
Toast.makeText(getContext(),albumsList.imgsurls[1],Toast.LENGTH_LONG).show();
/*
GridView gv = (GridView)view.findViewById(R.id.fragment_gridgallery);
ImageAdapter myadapter = new ImageAdapter(getContext(),albumsList.imgurls());
gv.setAdapter(myadapter);
*/
return view;
}
AlbumsList.java
public class AlbumsList {
private String server;
Context mycontext;
public String[] imgsurls;
private View view;
AlbumsList(String serverurl, Context c,View uview){
mycontext = c;
server = serverurl;
view = uview;
}
public View connection(){
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(mycontext);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.POST, server,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//GridView gv = (GridView)view.findViewById(R.id.fragment_gridgallery);
final ArrayList<String> urls2 = new ArrayList<String>();
try {
JSONArray jsonObj = new JSONArray(response);
Myserver myserver = new Myserver();
for (int i=0;i<jsonObj.length();i++){
JSONObject c = jsonObj.getJSONObject(i);
String imgurl = myserver.url+"/images/thumbs/tn_"+c.getString("album_thumbnail");
urls2.add(imgurl);
}
final String myabc[] = urls2.toArray(new String[urls2.size()]); //Do not remove this
imgsurls = myabc;
Toast.makeText(mycontext, imgsurls[0], Toast.LENGTH_LONG).show(); //Interestingly this toast works and imgsurls[] is ok
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(mycontext,e.getLocalizedMessage(),Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mycontext, "Unable to reach server", Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("getalbum", "getalbum");
return params;
}
};
queue.add(stringRequest);
return view;
}
public String[] imgurls(){
return imgsurls;
}
}
In AlbumsList.java, I want to return the list of URLS by either a function or variables, but both approachs don't work. Interestingly the url's are fetched proper from database. And that Toast inside AlbumsList.java: Toast.makeText(mycontext, imgsurls[0], Toast.LENGTH_LONG).show(); also works. Then I don't know why the imgsurls is not returned to main function. Thanks in advance.
Because Volley request is asynchronous.
Thus when are you calling albumsList.connection();, the request is running in background and before it is completed, control comes to the following line:
Toast.makeText(getContext(),albumsList.imgsurls[1],Toast.LENGTH_LONG).show();
And by that time, your request is not completed.
Volley works in an asynchronous fashion. This means that it doesn't return the result of the operation immediately. You are trying to access the results before they are fetched from the server.
You should move your view initialisation logic to the onResponse(), when the result is actually being delivered.
I would like to update my Listview in a fragmen in a onPostExecute() separate class.
The first initialization of the the Listview doas work, but wehe I call createList() again, the App crashes (NullPointerException)
Any Idea?
Main_Fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View fragmentView = inflater.inflate(R.layout.main_fragment, container, false);
StartSocketService = (Button) fragmentView.findViewById(R.id.start_socketservice);
StartSocketService.setOnClickListener(this);
StopSocketService = (Button) fragmentView.findViewById(R.id.stop_socketservice);
StopSocketService.setOnClickListener(this);
listview = (ListView) fragmentView.findViewById(R.id.listView1);
createList();
return fragmentView;
}
public void createList(){
//Reading Server IPs from SharedPreferences and put them to ListView
SharedPreferences settings = getActivity().getSharedPreferences("Found_Devices", 0);
for (int i = 0; i < 255; i++) {
if ((settings.getString("Server"+i,null)) != null) {
serverList.add(settings.getString("Server"+i, null));
Log.v("Reading IP: " +settings.getString("Server"+i, null), " from SraredPreferrences at pos.: "+i );
}
}
//Initializing listView
final StableArrayAdapter adapter = new StableArrayAdapter(getActivity(),android.R.layout.simple_list_item_1, serverList);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
final String item = (String) parent.getItemAtPosition(position);
view.animate().setDuration(2000).alpha(0).withEndAction(new Runnable() {
#Override
public void run() {
serverList.remove(item);
adapter.notifyDataSetChanged();
view.setAlpha(1);
}
});
}
});
}
Some class:
async_cient = new AsyncTask<Void, Void, Void>() {
...
protected void onPostExecute(Void result) {
Toast.makeText(mContext, "Scan Finished", Toast.LENGTH_SHORT).show();
Main_Fragment cList = new Main_Fragment();
cList.createList();
super.onPostExecute(result);
}
};
Log:
07-29 14:42:46.428 3382-3382/de.liquidbeam.LED.control D/AndroidRuntime﹕ Shutting down VM
07-29 14:42:46.428 3382-3382/de.liquidbeam.LED.control W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41549ba8)
07-29 14:42:46.438 3382-3382/de.liquidbeam.LED.control E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: de.liquidbeam.LED.control, PID: 3382
java.lang.NullPointerException
at de.liquidbeam.LED.control.fragments.Main_Fragment.createList(Main_Fragment.java:56)
at de.liquidbeam.LED.control.background.UDP_Discover$1.onPostExecute(UDP_Discover.java:94)
at de.liquidbeam.LED.control.background.UDP_Discover$1.onPostExecute(UDP_Discover.java:57)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
07-29 14:47:46.591 3382-3382/de.liquidbeam.LED.control I/Process﹕ Sending signal. PID: 3382 SIG: 9
Lines:
56 : SharedPreferences settings = getActivity().getSharedPreferences("Found_Devices", 0);
94 : cList.createList();
57: async_cient = new AsyncTask<Void, Void, Void>() {
You creating a new instance of your fragment with no context (activity) to run in. So
the line
SharedPreferences settings = getActivity().getSharedPreferences("Found_Devices", 0);
Tries to get his activity but there is no activity where the fragment lives in ;)
Building on a theme from yesterday...I'm getting an NPE accessing a method in a singleton Application class from within an AlertDialog.
Activity SavedMealsActivity sets OnLongClickListenerSavedMeals as the listener for a series of TextViews in a ScrollView. OnLongClickListenerSavedMeals is defined as a separate class.
OnLongClickListenerSavedMeals displays an AlertDialog which gives the option of going to a different Activity, but it first needs to fire the methods of an Application class which is defined as a singleton (MealTimerApplication). This is the first line of the onClick method (line 25 in the first code sample below), and it throws the NPE because the activity is null at the time.
I've tried passing in the activity from the calling Activity (SavedMealsActivity) but for some reason it's not working as I'd hoped. Any ideas?
OnLongClick listener class - OnLongClickListenerSavedMeals:
public class OnLongClickListenerSavedMeals implements OnLongClickListener {
Context context;
String id;
private Activity activity;
public OnLongClickListenerSavedMeals(Activity activity) {
this.activity = activity;
this.context = activity;
}
#Override
public boolean onLongClick(View view){
// TODO Auto-generated method stub
this.context = context;
id = view.getTag().toString();
final CharSequence[] items = { "Edit", "Delete" };
//Set activity to allow context to be used in the OnClickListener/onClick method below
this.activity = activity;
new AlertDialog.Builder(context).setTitle("Meal Item")
.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (item == 0) {
//Set the global meal_id variable and invoke the MealActivity
((MealTimerApplication) activity.getApplication()).setMealId(Long.getLong(id));
Intent myIntent = new Intent(activity.getBaseContext(),MealActivity.class);
activity.startActivityForResult(myIntent, 0);
}
else if (item == 1) {
boolean deleteSuccessful = new TableControllerMeal(context).delete(id);
if (deleteSuccessful){
Toast.makeText(context, "Record was deleted.", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context, "Unable to delete record.", Toast.LENGTH_SHORT).show();
}
((SavedMealsActivity) context).readRecords();
}
dialog.dismiss();
}
}).show();
return false;
}
Calling Activity - SavedMealsActivity:
public class SavedMealsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_saved_meals);
//Read saved meal records from the database and display them
readRecords();
}
public void readRecords() {
LinearLayout linearLayoutRecords = (LinearLayout) findViewById(R.id.linearLayoutRecords);
linearLayoutRecords.removeAllViews();
List<meal> meal = new TableControllerMeal(this).read();
if (meal.size() > 0) {
for (meal obj : meal) {
long id = obj.id;
String MealDesc = obj.meal_desc;
int MealMinutes = obj.meal_ready_time;
String textViewContents = MealDesc + " - ready at "
+ Utilities.formatTime(MealMinutes);
TextView textViewItem = new TextView(this);
textViewItem.setPadding(0, 10, 0, 10);
textViewItem.setText(textViewContents);
textViewItem.setTag(Long.toString(id));
textViewItem.setOnLongClickListener(new OnLongClickListenerSavedMeals(this));
linearLayoutRecords.addView(textViewItem);
}
}
else {
TextView Item = new TextView(this);
Item.setPadding(8, 8, 8, 8);
Item.setText("No records yet.");
linearLayoutRecords.addView(Item);
}
}
Application class:
public class MealTimerApplication extends Application {
private static MealTimerApplication singleton;
private long mealId = 0;
// Returns the application instance
public static MealTimerApplication getInstance() {
return singleton;
}
public final void onCreate() {
super.onCreate();
singleton = this;
}
public void setMealId(long mealId) {
this.mealId = mealId;
}
public long getMealId() {
return this.mealId;
}
}
Logcat:
05-28 16:48:03.637: E/AndroidRuntime(4241): java.lang.NullPointerException
05-28 16:48:03.637: E/AndroidRuntime(4241): at com.ian.mealtimer.OnLongClickListenerSavedMeals$1.onClick(OnLongClickListenerSavedMeals.java:39)
05-28 16:48:03.637: E/AndroidRuntime(4241): at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:941)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.widget.AdapterView.performItemClick(AdapterView.java:299)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2904)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.widget.AbsListView$3.run(AbsListView.java:3638)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.os.Handler.handleCallback(Handler.java:733)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.os.Handler.dispatchMessage(Handler.java:95)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.os.Looper.loop(Looper.java:136)
05-28 16:48:03.637: E/AndroidRuntime(4241): at android.app.ActivityThread.main(ActivityThread.java:5017)
05-28 16:48:03.637: E/AndroidRuntime(4241): at java.lang.reflect.Method.invokeNative(Native Method)
05-28 16:48:03.637: E/AndroidRuntime(4241): at java.lang.reflect.Method.invoke(Method.java:515)
05-28 16:48:03.637: E/AndroidRuntime(4241): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
05-28 16:48:03.637: E/AndroidRuntime(4241): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
05-28 16:48:03.637: E/AndroidRuntime(4241): at dalvik.system.NativeStart.main(Native Method)
You get NPE because of autoboxing. Long.getLong(String) is not what you actually you need, check its description:
Returns the Long value of the system property identified by string.
It definitely returns null in your case. Moreover it returns null reference to Long object, but your MealTimerApplication.setMealId expects argument with primitive type long. Here is the point where auto-boxing implicitly trying to cast your Long object returned by getLong method to the long primitive. But as value was null auto-boxing fails and you get NPE.
You should just use Long.valueOf(String) instead of Long.getLong(String).
Here is the code that uses the youtube api:
public class ArticleAdapter extends BaseAdapter {
private ArrayList<ArticlePart> articlePartList;
private Activity activity;
private LayoutInflater layoutInflater;
public ArticleAdapter(Activity activity, ArrayList<ArticlePart> articlePartList) {
this.activity = activity;
this.articlePartList = articlePartList;
layoutInflater = LayoutInflater.from(activity);
if (articlePartList == null) {
Log.i("articlePartList", "null");
}
}
...
...
public View getView(int position, View convertView, final ViewGroup parent) {
final ArticlePart articlePart = articlePartList.get(position);
String articlePartKind = articlePart.getKind();
View view = null;
String[] leaves = {"text", "richtext"};
if (articlePartKind.equals("video_entry")) {
final String videoId = "blabla";
YouTubePlayerView ytPlayerView = new YouTubePlayerView(activity);
view = ytPlayerView;
ytPlayerView.initialize("apikey", new OnInitializedListener() {
#Override
public void onInitializationFailure(Provider arg0, YouTubeInitializationResult arg1) {
Log.e("ArticleAdapter", "onInitializationFailure");
}
#Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) {
Log.e("ArticleAdapter", "onInitializationSuccess");
player.cueVideo(videoId);
}
});
}
view.setTag(R.id.tag_article_part_id, articlePart.getId());
return view;
}
}
The player view initially loads (I can see a black rectangle with a "loading" image in the middle) but my app hangs and crashes shortly after that.
This is what happens:
06-11 16:44:59.495 11097-11097/app E/dalvikvm~U Could not find class 'com.google.android.apps.youtube.core.player.overlay.bm', referenced from method ccgom.google.android.apps.youtube.core.player.overlay.SubtitlesPreferences.<init>
06-11 16:44:59.500 11097-11097/app E/dalvikvm~U Could not find class 'android.view.accessibility.CaptioningManager', referenced from method com.google..randroid.apps.youtube.core.player.overlay.SubtitlesPreferences.c
06-11 16:44:59.545 11763-11763/? E/dalvikvm~U Could not find class 'com.google.android.apps.youtube.core.player.overlay.bm', referenced from method commo.google.android.apps.youtube.core.player.overlay.SubtitlesPreferences.<init>
06-11 16:44:59.545 11763-11763/? E/dalvikvm~U Could not find class 'android.view.accessibility.CaptioningManager', referenced from method com.google.annidroid.apps.youtube.core.player.overlay.SubtitlesPreferences.c
06-11 16:44:59.580 11763-11763/? E/YouTubeAndroidPlayerAPI~U apps.youtube.core.player.Director.F:521 Media progress reported outside media playback
06-11 16:44:59.635 11763-11763/? E/AndroidRuntime~U FATAL EXCEPTION: main
java.lang.IllegalArgumentException
at com.google.android.apps.youtube.core.utils.ab.a(SourceFile:112)
at com.google.android.apps.youtube.core.player.a.a.a(SourceFile:92)
at com.google.android.apps.youtube.core.player.sequencer.o.a(SourceFile:212)
at com.google.android.apps.youtube.core.player.sequencer.o.g(SourceFile:116)
at com.google.android.apps.youtube.core.player.sequencer.o.i(SourceFile:128)
at com.google.android.apps.youtube.core.player.Director.o(SourceFile:801)
at com.google.android.apps.youtube.core.player.Director.a(SourceFile:629)
at com.google.android.apps.youtube.api.ApiPlayer.b(SourceFile:297)
at com.google.android.apps.youtube.api.b.a.p.run(SourceFile:210)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)
here is a link to the whole thing - no filters, just searching for "youtube" in logcat:
http://pastebin.com/6DjBbn0B
I tried using loadVideo() instead of cueVideo() and surrounding the cueVideo() in a try/catch block as suggested here https://code.google.com/p/gdata-issues/issues/detail?id=4395 but that did not help.