In my static method(Parameter is only one string), I want to use Dialog(new AlertDialog.Builder(mContext)), but dialog needs an activity context to construct. If I do not pass through the external context parameters, only by reflection or other methods, how to get an object of current top activity?
public static Activity getActivity() {
Class activityThreadClass = null;
try {
activityThreadClass = Class.forName("android.app.ActivityThread");
Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
activitiesField.setAccessible(true);
Map activities = (Map) activitiesField.get(activityThread);
for (Object activityRecord : activities.values()) {
Class activityRecordClass = activityRecord.getClass();
Field pausedField = activityRecordClass.getDeclaredField("paused");
pausedField.setAccessible(true);
if (!pausedField.getBoolean(activityRecord)) {
Field activityField = activityRecordClass.getDeclaredField("activity");
activityField.setAccessible(true);
Activity activity = (Activity) activityField.get(activityRecord);
return activity;
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
I used this code, but when I call this method in non-Activity class, the activities is null.
Is there any other way? Can not use dialog, as long as it is able to pop up the information can be seen by the user. A point limit: does not get context from the parameter.
Use Application.ActivityLifecycleCallbacks
Implementation example:
class ActivityLifeCycleCallbackImpl implements Application.ActivityLifecycleCallbacks {
private Set<Activity> set = new HashSet<>();
#Override
public void onActivityStarted(Activity activity) {
set.add(activity);
}
#Override
public void onActivityStopped(Activity activity) {
set.remove(activity);
}
Activity getCurrentActivity() {
if (set.isEmpty()) {
return null;
}
return set.iterator().next();
}
}
and in your custom application class:
ActivityLifeCycleCallbackImpl activityLifeCycleCallback = new ActivityLifeCycleCallbackImpl();
#Override
public void onCreate() {
registerActivityLifecycleCallbacks(activityLifeCycleCallback);
}
Related
I am using Glide function to load an image form a server response. The code below is working properly inside an onViewCreated function, but i want to make a Handler to verify the internet connection and I am declaring the Runnable as a global variable. Well inside that Runnable I can't use getActivity as a context/container. What should I use?
Here is the code inside onViewCreated():
try {
Glide.with(this.getActivity()).load(jsonObject.getString("dispensary_thumbmail")).into(image);
} catch (JSONException e) {
e.printStackTrace();
}
And here is the Runnable:
Runnable runnable = new Runnable() {
#Override
public void run() {
if(!isNetworkConnected())
{
handler.postDelayed(runnable , time);
}
else
{
try {
jsonObject = new JSONObject(MainActivity.dispensaries);
jsonArray = jsonObject.optJSONArray("dispensaries");
Log.e(TAG, "jsonArray = " + jsonArray);
jsonObject = null;
} catch (JSONException e) {
e.printStackTrace();
}
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject object = jsonArray.getJSONObject(i);
if(MainActivity.ID.equals(object.get("dispensary_id")))
{
jsonObject = object;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
try {
Glide.with(this.).load(jsonObject.getString("dispensary_thumbmail")).into(image);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
};
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
Try this, basically, you needed runOnUiThread of activity class
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Glide.with(getActivity()).load(jsonObject.getString("dispensary_thumbmail")).into(image);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
I want to write a method that creates multiple fragments for me and I am not sure how to do this. After a few attempts I got more confused.
Here is how I typically and creating two fragments
private void createFragDog(Animals animals) {
DogFragment frag = DogFragment.newInstance(ArrayList<Dogs> animals.getDogs());
...
*frag.(do fragment manager stuff and commit())*
...
}
Second call to create fragment
private void createFragCat(Animals animals) {
CatFragment frag = CatFragment.newInstance(ArrayList<Cats> animals.getCats());
...
*frag.(do fragment manager stuff and commit())*
...
}
Being that the newInstance method is static I can't seem to figure out how to make a generic method and just pass in the class types. Also the object passed into newInstance is not always an array. Here is my attempt:
private <T,E> void animalFragments(Class<T> frag, Class<E> animalType, Object obj){
if (obj == null) return;
if (obj instanceof List<?>) {
if (((List<E>)obj).isEmpty()) return;
}
try {
T fragment = (T) frag.newInstance();
?? Not sure what to do now or how to call up method that is static but specific to both.
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Did it this way hope this helps.
private <T,E> void animalFragments(Class<T> frag, Object obj){
Method m = null;
try {
m = frag.newInstance().getClass().getDeclaredMethod("newInstance", obj.getClass());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (m != null) {
T fragment = null;
try {
fragment = (T) m.invoke(null, obj);
if (fragment != null) {
FragmentTransaction trans = this.getSupportFragmentManager().beginTransaction();
trans.add(R.id.ll_fragments_container, (Fragment) fragment, fragment.getClass().getSimpleName());
trans.commit();
return true;
}
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
How can you call a method within an AsyncTask? In my asynctask,which is an inner class in my java file 'xyz', when the user clicks a button, it should call a method within 'xyz' which also happens to be an alertDialog, i know it calls it, but when it reaches the method, the app crashes and gives a runtime exception, which says 'Can't create handler inside thread that has not called Looper.prepare()'. I looked up examples here but it threw the same runtime exception. How can i make it work? isn't calling an outer method from within the asynctask a possibility?
this is the snippet to call the method:
private class DownloadFilesTask extends AsyncTask<Void,Void,Void> {
private LoginActivity loginActivity;
public DownloadFilesTask(LoginActivity loginActivity){
this.loginActivity=loginActivity;
}
#Override
protected Void doInBackground(Void... voids) {
long start=System.currentTimeMillis();
in=null;
try {
website=new URI(URL);
request.setURI(website);
} catch (URISyntaxException e) {
e.printStackTrace();
}
HttpPost httpPost=new HttpPost(URL);
List<NameValuePair>nameValuePairs=new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("name",name));
nameValuePairs.add(new BasicNameValuePair("pwd",pwd));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
response=httpClient.execute(request);
} catch (IOException e) {
e.printStackTrace();
}
try {
in=new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
} catch (IOException e) {
e.printStackTrace();
}
try {
String line=in.readLine();
long end=System.currentTimeMillis();
long times=end-start;
String time=String.valueOf(times);
System.out.println(name);
System.out.println(NAME_PATTERN);
System.out.println(pwd);
System.out.println(PWD_PATTERN);
if (name.equals(NAME_PATTERN) && (pwd.equals(PWD_PATTERN))) {
bloggedIn=true;
System.out.println("Youre right");
}else
{
bloggedIn=false;
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private void onPostExecute(String line, String time) {
if(bloggedIn=true){
navigateToMainActivity(time);
}else{ if (bloggedIn=false){
newp(line,time);
}
}
}
}
and this is the method called:
public void navigateToMainActivity(String timetoo) {
al=new AlertDialog.Builder(LoginActivity.this);
al.setTitle("Welcome");
al.setMessage("Hey there");
al.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
startActivity(new Intent(LoginActivity.this, Main.class));
}
});
al.show();
}
It looks like you need doInBackground to return true or false when it's finsished. You need doInBackground to return the boolean. Try this:
#Override
protected Boolean doInBackground(Void... arg0)
{
// your stuff
return bloggedIn; // instead of null or return the boolean where you are setting it true or false
}
Then your onPostExecute should look like this:
#Override
protected void onPostExecute(Boolean result)
{
super.onPostExecute(result);
if(result){
navigateToMainActivity(time);
}else{
newp(line,time);
}
}
Other class:
SpotifyTask st = new SpotifyTask(new Closure<JSONObject>() {
#Override
public void executeOnSuccess(JSONObject result) {
track.setJson(result);
}
});
st.execute("asd");
Being SpotifyTask:
public class SpotifyTask extends AsyncTask<Object, Void, JSONObject> {
private final Closure<JSONObject> closure;
public SpotifyTask(Closure<JSONObject> closure) {
this.closure = closure;
}
public static void getTrack(Closure<JSONObject> closure) {
new SpotifyTask(closure).execute("asd");
}
#Override
protected JSONObject doInBackground(Object... params) {
JSONObject result = null;
SpotifyCall spcall = new SpotifyCall();
try {
result = spcall.getTrack();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(JSONObject result) {
System.out.println("ASD: on post execute "+result);
closure.executeOnSuccess(result);
}
}
So... doInBackground is running OK, and and returning a JSONObject all right; I know because Im debbuging it and "result" IS a JSONObject.
But onPostExecute is never executed, the debugger never gets there and "ASD: on postexecute "+result is never logged.
Any suggestions?
Thanks in advance!
The problem was that I was "holding" the UI Thread:
this.status = "loading";
final Track track = new Track();
SpotifyTask.getTrack(new Closure<JSONObject>() {
#Override
public void executeOnSuccess(JSONObject result) {
track.setJson(result);
}
});
while (this.status.equals("loading")) {
if (track.getJson() != null) {
this.trackUno = track.getJson();
this.status = "ready";
} else {
try {
System.out.println("Not ready, waiting.");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
As soon I removed the while block, it worked perfectly.
I would have to find another way to "wait" for the call to be complete.
Thanks for your time fellas!
I think I got a similar problem like in this post: Return ArrayList and use it in another method problm.
In a several class an ArrayList<...> will be created with "new". In this List I store several DataContainer(defined by another class).
Now if I saved all my data classes, I return this List back to my Activity via "OnMessageReceived".
The strange thing is, sometimes it works but mostly I get an empty list.
I compressed the code for better view. If I debug I can see the data is accessible until it jumps into the method "public void messageReceived(final ArrayList _Container){...}"
Is that kind of returning not possible?
Some Code:
(Class 1) Method for getting Data:
public boolean run() {
try {
...
try {
....
while (mRun) {
if(in.ready()) {
...
...
mMessageListener.messageReceived(_ConvertData.GetMessage(new String(Puffer).substring(0,length)));
}
}
}
}
}
(Class 2)
public ArrayList<DatenContainer> GetMessage(String message) {
Sensoren SensorName = Sensoren.NONE;
int _Length = 0;
int _ID = 0;
double _TimeStamp = 0;
int _NumberOfPackage = 0;
String _msg = "";
while (!message.isEmpty()) {
...
...
Container.add(new DatenContainer(_Length, _ID, _TimeStamp, _NumberOfPackage, _msg, SensorName));
}
catch (Exception e) {}
}
return Container;
}
(Activity)
TCP_Client_Thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
// create a TCPClient object and
mTcpClient = new TCP_Client(new TCP_Client.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(final ArrayList<DatenContainer> _Container) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
for (DatenContainer datenContainer : _Container) {
...
...
}
} catch (Exception e) {
Show_Toast(e.toString());
}
}
});
}
},Infos.getSERVERIP(),Infos.getSERVERPORT());
}
catch (Exception e) {}
}
Now it works. I forgot the sync-method. Thx guys for helping me out :)
#Override
//here the messageReceived method is implemented
public void messageReceived(final ArrayList<DatenContainer> _Container) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
ArrayList<DatenContainer> Container;
synchronized (_Container) {
Container = _Container;
}
try {
if (Container != null && !Container.isEmpty()) {
for(int i = 0; i < Container.size(); i++) {
DatenContainer datenContainer = (DatenContainer)Container.get(i);
switch (datenContainer.get_ActSensor()) {
case SPEED:
edt_3.setText(datenContainer.get_Data());
break;
case COG:
edt_4.setText(datenContainer.get_Data());
break;
default:
break;
}
}
}
}
catch (Exception e) {
Show_Toast(e.toString());
}
Container.clear();
}
});
}